From: Jean-Philippe Bruyère Date: Tue, 18 Jan 2022 18:55:29 +0000 (+0100) Subject: simple concave path handling X-Git-Tag: v0.3.0-beta~2 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=9079c9a86ec78e565c35159dbebd10a99b4bc988;p=jp%2Fvkvg.git simple concave path handling --- diff --git a/src/vkvg_context.c b/src/vkvg_context.c index f497a54..432e9f7 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -396,9 +396,14 @@ void vkvg_arc (VkvgContext ctx, float xc, float yc, float radius, float a1, floa if (_current_path_is_empty(ctx)){ _set_curve_start (ctx); _add_point (ctx, v.x, v.y); + if (!ctx->pathPtr) + ctx->simpleConvex = true; + else + ctx->simpleConvex = false; }else{ _line_to(ctx, v.x, v.y); _set_curve_start (ctx); + ctx->simpleConvex = false; } a+=step; @@ -444,9 +449,14 @@ void vkvg_arc_negative (VkvgContext ctx, float xc, float yc, float radius, float if (_current_path_is_empty(ctx)){ _set_curve_start (ctx); _add_point (ctx, v.x, v.y); + if (!ctx->pathPtr) + ctx->simpleConvex = true; + else + ctx->simpleConvex = false; }else{ _line_to(ctx, v.x, v.y); _set_curve_start (ctx); + ctx->simpleConvex = false; } a-=step; @@ -505,6 +515,30 @@ void vkvg_get_current_point (VkvgContext ctx, float* x, float* y) { *x = cp.x; *y = cp.y; } +void _curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) { + //prevent running _recursive_bezier when all 4 curve points are equal + if (EQUF(x1,x2) && EQUF(x2,x3) && EQUF(y1,y2) && EQUF(y2,y3)) { + if (_current_path_is_empty(ctx) || (EQUF(_get_current_position(ctx).x,x1) && EQUF(_get_current_position(ctx).y,y1))) + return; + } + _set_curve_start (ctx); + if (_current_path_is_empty(ctx)) + _add_point(ctx, x1, y1); + + vec2 cp = _get_current_position(ctx); + + //compute dyn distanceTolerance depending on current scale + float sx = 1, sy = 1; + vkvg_matrix_get_scale (&ctx->pushConsts.mat, &sx, &sy); + float distanceTolerance = fabs(1.0f / fmaxf(sx,sy)); + + _recursive_bezier (ctx, distanceTolerance, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0); + /*cp.x = x3; + cp.y = y3; + if (!vec2_equ(ctx->points[ctx->pointCount-1],cp))*/ + _add_point(ctx,x3,y3); + _set_curve_end (ctx); +} const double quadraticFact = 2.0/3.0; void _quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2) { float x0, y0; @@ -513,7 +547,7 @@ void _quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float y2) { y0 = y1; } else vkvg_get_current_point (ctx, &x0, &y0); - vkvg_curve_to (ctx, + _curve_to (ctx, x0 + (x1 - x0) * quadraticFact, y0 + (y1 - y0) * quadraticFact, x2 + (x1 - x2) * quadraticFact, @@ -535,30 +569,6 @@ void vkvg_rel_quadratic_to (VkvgContext ctx, float x1, float y1, float x2, float vec2 cp = _get_current_position(ctx); _quadratic_to (ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2); } -void _curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) { - //prevent running _recursive_bezier when all 4 curve points are equal - if (EQUF(x1,x2) && EQUF(x2,x3) && EQUF(y1,y2) && EQUF(y2,y3)) { - if (_current_path_is_empty(ctx) || (EQUF(_get_current_position(ctx).x,x1) && EQUF(_get_current_position(ctx).y,y1))) - return; - } - _set_curve_start (ctx); - if (_current_path_is_empty(ctx)) - _add_point(ctx, x1, y1); - - vec2 cp = _get_current_position(ctx); - - //compute dyn distanceTolerance depending on current scale - float sx = 1, sy = 1; - vkvg_matrix_get_scale (&ctx->pushConsts.mat, &sx, &sy); - float distanceTolerance = fabs(1.0f / fmaxf(sx,sy)); - - _recursive_bezier (ctx, distanceTolerance, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0); - /*cp.x = x3; - cp.y = y3; - if (!vec2_equ(ctx->points[ctx->pointCount-1],cp))*/ - _add_point(ctx,x3,y3); - _set_curve_end (ctx); -} void vkvg_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) { if (ctx->status) return; @@ -597,7 +607,7 @@ vkvg_status_t vkvg_rectangle (VkvgContext ctx, float x, float y, float w, float _add_point (ctx, x + w, y + h); _add_point (ctx, x, y + h); - ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT; + ctx->pathes[ctx->pathPtr] |= (PATH_CLOSED_BIT|PATH_IS_CONVEX_BIT); _finish_path(ctx); return VKVG_STATUS_SUCCESS; diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index d40d2b7..58db466 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2018-2022 Jean-Philippe Bruyère * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -172,6 +172,9 @@ void _finish_path (VkvgContext ctx){ LOG(VKVG_LOG_INFO_PATH, "PATH: points count=%10d\n", ctx->pathes[ctx->pathPtr]&PATH_ELT_MASK); + if (ctx->pathPtr == 0 && ctx->simpleConvex) + ctx->pathes[0] |= PATH_IS_CONVEX_BIT; + if (ctx->segmentPtr > 0) { ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT; //if last segment is not a curve and point count > 0 @@ -188,6 +191,7 @@ void _finish_path (VkvgContext ctx){ ctx->pathes[ctx->pathPtr] = 0; ctx->segmentPtr = 0; ctx->subpathCount++; + ctx->simpleConvex = false; } //clear path datas in context void _clear_path (VkvgContext ctx){ @@ -196,6 +200,7 @@ void _clear_path (VkvgContext ctx){ ctx->pointCount = 0; ctx->segmentPtr = 0; ctx->subpathCount = 0; + ctx->simpleConvex = false; } void _remove_last_point (VkvgContext ctx){ ctx->pathes[ctx->pathPtr]--; @@ -360,6 +365,15 @@ void _add_triangle_indices(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_IND _check_index_cache_size(ctx); LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0,i1,i2,ctx->indCount); } +void _add_triangle_indices_unchecked (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2){ + VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount]; + inds[0] = i0; + inds[1] = i1; + inds[2] = i2; + ctx->indCount+=3; + + LOG(VKVG_LOG_INFO_IBO, "Triangle IDX: %d %d %d (indCount=%d)\n", i0,i1,i2,ctx->indCount); +} void _vao_add_rectangle (VkvgContext ctx, float x, float y, float width, float height){ Vertex v[4] = { @@ -1399,6 +1413,7 @@ void _line_to (VkvgContext ctx, float x, float y) { return; } _add_point (ctx, x, y); + ctx->simpleConvex = false; } void _elliptic_arc (VkvgContext ctx, float x1, float y1, float x2, float y2, bool largeArc, bool counterClockWise, float _rx, float _ry, float phi) { if (ctx->status) @@ -1486,9 +1501,11 @@ void _elliptic_arc (VkvgContext ctx, float x1, float y1, float x2, float y2, boo if (_current_path_is_empty(ctx)){ _set_curve_start (ctx); _add_point (ctx, xy.x, xy.y); + ctx->simpleConvex = true; }else{ _line_to(ctx, xy.x, xy.y); _set_curve_start (ctx); + ctx->simpleConvex = false; } _set_curve_start (ctx); @@ -1656,6 +1673,28 @@ void _fill_non_zero (VkvgContext ctx){ uint32_t ptrPath = 0; uint32_t firstPtIdx = 0; + if (ctx->pathPtr == 1 && ctx->pathes[0] & PATH_IS_CONVEX_BIT) { + //simple concave rectangle or circle + VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset); + uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK; + + _ensure_vertex_cache_size(ctx, pathPointCount); + _ensure_index_cache_size(ctx, (pathPointCount-2)*3); + + VKVG_IBO_INDEX_TYPE i = 0; + while (i < 2){ + v.pos = ctx->points [i++]; + _set_vertex (ctx, ctx->vertCount++, v); + } + while (i < pathPointCount){ + v.pos = ctx->points [i]; + _set_vertex (ctx, ctx->vertCount++, v); + _add_triangle_indices_unchecked(ctx, firstVertIdx, firstVertIdx + i - 1, firstVertIdx + i); + i++; + } + return; + } + GLUtesselator *tess = gluNewTess(); gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index 537fc8f..ebc7e48 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -192,6 +192,7 @@ typedef struct _vkvg_context_t { uint32_t segmentPtr; //current segment count in current path having curves uint32_t subpathCount; //store count of subpath, not straight forward to retrieve from segmented path array + bool simpleConvex; //true if path is single rect or concave closed curve. float lineWidth; uint32_t dashCount; //value count in dash array, 0 if dash not set. diff --git a/src/vkvg_internal.h b/src/vkvg_internal.h index fa590c6..7af8fa4 100644 --- a/src/vkvg_internal.h +++ b/src/vkvg_internal.h @@ -55,7 +55,8 @@ #define PATH_HAS_CURVES_BIT 0x40000000 /* 2rd most significant bit of path elmts is curved status * for main path, this indicate that curve datas are present. * For segments, this indicate that the segment is curved or not */ -#define PATH_ELT_MASK 0x3FFFFFFF /* Bit mask for fetching path element value */ +#define PATH_IS_CONVEX_BIT 0x20000000 /* simple rectangle or circle. */ +#define PATH_ELT_MASK 0x1FFFFFFF /* Bit mask for fetching path element value */ #define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c))) #define ROUND_DOWN(v,p) (floorf(v * p) / p)