]> O.S.I.I.S - jp/vkvg.git/commitdiff
simple concave path handling
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 18 Jan 2022 18:55:29 +0000 (19:55 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 18 Jan 2022 18:55:29 +0000 (19:55 +0100)
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
src/vkvg_internal.h

index f497a5442e8fb3f517fc6ca56d6b9363216e4fc1..432e9f717ae1dfaae9969d53e7f0f94a85bd5db8 100644 (file)
@@ -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;
index d40d2b7f0a0e8f712e125f97c299a48f43d7f697..58db46630207595ecacb5936d80d58f40fcee536 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2018-2022 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
  *
  * 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);
index 537fc8f081cb30e08cc53b843a993c55ea4875d3..ebc7e48a9a4357e08a6639dc73f4d6de59d43710 100644 (file)
@@ -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.
index fa590c6302fe12a55f93981800f78ec48bfbaa63..7af8fa44677719857dd1acfb080f1b714df5e402 100644 (file)
@@ -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)