]> O.S.I.I.S - jp/vkvg.git/commitdiff
path array with only segment lengths instead of start/stop points
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Jul 2020 10:32:49 +0000 (12:32 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Jul 2020 10:32:49 +0000 (12:32 +0200)
include/vkvg.h
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
src/vkvg_internal.h

index 28af6cf11680c20a51081c8f84001e5d713bd822..81a73f417a0ebb3496c406ac7b0361ebfff93a74 100644 (file)
@@ -64,7 +64,8 @@ typedef enum {
        VKVG_STATUS_INVALID_FORMAT,
        VKVG_STATUS_INVALID_VISUAL,
        VKVG_STATUS_FILE_NOT_FOUND,
-       VKVG_STATUS_INVALID_DASH
+       VKVG_STATUS_INVALID_DASH,
+       VKVG_STAtUS_NOT_ENOUGH_POINTS_TO_CLOSE_PATH
 }vkvg_status_t;
 
 typedef enum {
index fbbbf89313dfd5eb46e2a874cdb87174c4bd5c0e..eaf7f7f1d451cece072dbdd792c83a76400e3e6d 100644 (file)
@@ -320,19 +320,19 @@ void vkvg_new_path (VkvgContext ctx){
  * @param context pointer
  */
 void vkvg_close_path (VkvgContext ctx){
-       if (_current_path_is_empty(ctx)){
-               ctx->status = VKVG_STATUS_NO_CURRENT_POINT;
+       //check if at least 3 points are present
+       if (ctx->pathes[ctx->pathPtr] < 3){
+               ctx->status = VKVG_STAtUS_NOT_ENOUGH_POINTS_TO_CLOSE_PATH;
                return;
        }
-       //check if at least 3 points are present
-       if (ctx->pointCount - (ctx->pathes [ctx->pathPtr-1]&PATH_ELT_MASK) > 2){
-               ctx->pathes[ctx->pathPtr] = ctx->pointCount - 1;
-               ctx->pathes[ctx->pathPtr-1] |= PATH_CLOSED_BIT;
-               _check_pathes_array(ctx);
-               ctx->pathPtr += ctx->curvePtr + 1;
-               ctx->curvePtr = 0;
-       }else
-               _finish_path(ctx);
+       //prevent closing on the same point
+       if (vec2_equ(ctx->points[ctx->pointCount-1],
+                                ctx->points[ctx->pointCount - ctx->pathes[ctx->pathPtr]]))
+               _remove_last_point(ctx);
+
+       ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
+
+       _finish_path(ctx);
 }
 /**
  * @brief draw line with second point coordinates relative to current point
@@ -357,13 +357,12 @@ void vkvg_rel_line_to (VkvgContext ctx, float x, float y){
 void vkvg_line_to (VkvgContext ctx, float x, float y)
 {
        vec2 p = {x,y};
-       if (_current_path_is_empty(ctx)){
-               vkvg_move_to(ctx, x,y);
-               return;
-       }else if (vec2_equ(_get_current_position(ctx),p))
-               return;
-
-       _add_point(ctx,x,y);
+       if (!_current_path_is_empty (ctx)){
+               //prevent adding the same point
+               if (vec2_equ (_get_current_position (ctx), p))
+                       return;
+       }
+       _add_point (ctx, x, y);
 }
 /**
  * @brief Draw arc in clockwise order following angles of the trigonometric circle.
@@ -386,18 +385,19 @@ void vkvg_arc (VkvgContext ctx, float xc, float yc, float radius, float a1, floa
        float step = _get_arc_step(ctx, radius);
        float a = a1;
 
-       if (_current_path_is_empty(ctx))
-               vkvg_move_to(ctx, v.x, v.y);
-       else
+       if (_current_path_is_empty(ctx)){
+               _set_curve_start (ctx);
+               _add_point (ctx, v.x, v.y);
+       }else{
                vkvg_line_to(ctx, v.x, v.y);
+               _set_curve_start (ctx);
+       }
 
        a+=step;
 
        if (EQUF(a2, a1))
                return;
 
-       _set_curve_start (ctx);
-
        while(a < a2){
                v.x = cosf(a)*radius + xc;
                v.y = sinf(a)*radius + yc;
@@ -438,10 +438,12 @@ void vkvg_arc_negative (VkvgContext ctx, float xc, float yc, float radius, float
        float step = _get_arc_step(ctx, radius);
        float a = a1;
 
-       if (_current_path_is_empty(ctx))
-               vkvg_move_to(ctx, v.x, v.y);
-       else {
+       if (_current_path_is_empty(ctx)){
+               _set_curve_start (ctx);
+               _add_point (ctx, v.x, v.y);
+       }else{
                vkvg_line_to(ctx, v.x, v.y);
+               _set_curve_start (ctx);
        }
 
        a-=step;
@@ -449,8 +451,6 @@ void vkvg_arc_negative (VkvgContext ctx, float xc, float yc, float radius, float
        if (EQUF(a2, a1))
                return;
 
-       _set_curve_start (ctx);
-
        while(a > a2){
                v.x = cosf(a)*radius + xc;
                v.y = sinf(a)*radius + yc;
@@ -493,16 +493,16 @@ void vkvg_rel_move_to (VkvgContext ctx, float x, float y)
 void vkvg_move_to (VkvgContext ctx, float x, float y)
 {
        _finish_path(ctx);
-       _start_sub_path(ctx, x, y);
+       _add_point (ctx, x, y);
 }
 
 void vkvg_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
+       _set_curve_start (ctx);
        if (_current_path_is_empty(ctx))
-               vkvg_move_to(ctx, x1, y1);
+               _add_point(ctx, x1, y1);
 
        vec2 cp = _get_current_position(ctx);
 
-       _set_curve_start (ctx);
        _recursive_bezier (ctx, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0);
        /*cp.x = x3;
        cp.y = y3;
@@ -590,7 +590,7 @@ void vkvg_clip_preserve (VkvgContext ctx){
        CmdSetStencilCompareMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
 }
 void vkvg_fill_preserve (VkvgContext ctx){
-       if (ctx->pathPtr == 0)      //nothing to fill
+       if (!(ctx->pathPtr || ctx->segmentPtr))      //nothing to fill
                return;
        _finish_path(ctx);
 
@@ -718,7 +718,7 @@ void _draw_segment (VkvgContext ctx, float hw, bool isCurve) {
 }
 void vkvg_stroke_preserve (VkvgContext ctx)
 {
-       if (ctx->pathPtr == 0)//nothing to stroke
+       if (ctx->pathPtr == 0 && _current_path_is_empty(ctx))//nothing to stroke
                return;
        _finish_path(ctx);
 
@@ -728,15 +728,19 @@ void vkvg_stroke_preserve (VkvgContext ctx)
        curPathPointIdx = lastPathPointIdx = ptrPath = iL = iR = 0;
 
        while (ptrPath < ctx->pathPtr){
-               uint32_t ptrCurve = 0;
+               uint32_t ptrSegment = 0, lastSegmentPointIdx = 0;
+               uint32_t firstPathPointIdx = curPathPointIdx;
+               uint32_t pathPointCount = ctx->pathes[ptrPath]&PATH_ELT_MASK;
+               lastPathPointIdx = curPathPointIdx + pathPointCount - 1;
 
+               if (_path_has_curves (ctx,ptrPath)) {
+                       ptrSegment = 1;
+                       lastSegmentPointIdx = curPathPointIdx + (ctx->pathes[ptrPath+ptrSegment]&PATH_ELT_MASK)-1;
+               }
 
                VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-               curPathPointIdx = ctx->pathes[ptrPath]&PATH_ELT_MASK;
-
-               LOG(VKVG_LOG_INFO_PATH, "\tPATH: start=%d end=%d", ctx->pathes[ptrPath]&PATH_ELT_MASK, ctx->pathes[ptrPath+1]&PATH_ELT_MASK);
 
-               lastPathPointIdx = ctx->pathes[ptrPath+1]&PATH_ELT_MASK;
+               //LOG(VKVG_LOG_INFO_PATH, "\tPATH: start=%d end=%d", ctx->pathes[ptrPath]&PATH_ELT_MASK, ctx->pathes[ptrPath+1]&PATH_ELT_MASK);
                LOG(VKVG_LOG_INFO_PATH, "end = %d\n", lastPathPointIdx);
 
                if (ctx->dashCount > 0) {
@@ -760,10 +764,6 @@ void vkvg_stroke_preserve (VkvgContext ctx)
 
                        iL = lastPathPointIdx;
                } else if (_path_is_closed(ctx,ptrPath)){
-                       //prevent closing on the same position, this could be generalize
-                       //to prevent processing of two consecutive point at the same position
-                       if (vec2_equ(ctx->points[curPathPointIdx], ctx->points[lastPathPointIdx]))
-                               lastPathPointIdx--;
                        iL = lastPathPointIdx;
                }else{
                        _draw_stoke_cap(ctx, hw, ctx->points[curPathPointIdx], vec2_line_norm(ctx->points[curPathPointIdx], ctx->points[curPathPointIdx+1]), true);
@@ -772,20 +772,28 @@ void vkvg_stroke_preserve (VkvgContext ctx)
 
                if (_path_has_curves (ctx,ptrPath)) {
                        while (curPathPointIdx < lastPathPointIdx){
-                               if (ptrPath + ptrCurve + 2 < ctx->pathPtr && (ctx->pathes [ptrPath + 2 + ptrCurve] & PATH_ELT_MASK) == curPathPointIdx){
-                                       uint32_t lastCurvePointIdx = ctx->pathes[ptrPath + 3 + ptrCurve]&PATH_ELT_MASK;
-                                       while (curPathPointIdx < lastCurvePointIdx)
-                                               _draw_segment(ctx, hw, true);
-                                       ptrCurve += 2;
-                               }else
-                                       _draw_segment(ctx, hw, false);
+
+                               bool curved = ctx->pathes [ptrPath + ptrSegment] & PATH_IS_CURVE_BIT;
+                               if (lastSegmentPointIdx == lastPathPointIdx)//last segment of path, dont draw end point here
+                                       lastSegmentPointIdx--;
+                               while (curPathPointIdx <= lastSegmentPointIdx)
+                                       _draw_segment(ctx, hw, curved);
+
+                               ptrSegment ++;
+                               uint32_t cptSegPts = ctx->pathes [ptrPath + ptrSegment]&PATH_ELT_MASK;
+                               lastSegmentPointIdx = curPathPointIdx + cptSegPts - 1;
+                               if (lastSegmentPointIdx == lastPathPointIdx && cptSegPts == 1) {
+                                       //single point last segment
+                                       ptrSegment++;
+                                       break;
+                               }
                        }
                }else while (curPathPointIdx < lastPathPointIdx)
                        _draw_segment(ctx, hw, false);
 
                if (ctx->dashCount > 0) {
                        if (_path_is_closed(ctx,ptrPath)){
-                               iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+                               iR = firstPathPointIdx;
                                _draw_dashed_segment(ctx, hw, ctx->points[iL++], ctx->points[curPathPointIdx++], ctx->points[iR], false);
                        }
                        if (!dashOn){
@@ -799,7 +807,7 @@ void vkvg_stroke_preserve (VkvgContext ctx)
                                _draw_stoke_cap (ctx, hw, p, normal, false);
                        }
                } else if (_path_is_closed(ctx,ptrPath)){
-                       iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+                       iR = firstPathPointIdx;
                        float cross = _build_vb_step (ctx, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], false);
 
                        VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6];
@@ -817,7 +825,12 @@ void vkvg_stroke_preserve (VkvgContext ctx)
                }else
                        _draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], vec2_line_norm(ctx->points[curPathPointIdx-1], ctx->points[curPathPointIdx]), false);
 
-               ptrPath+=2+ptrCurve;
+               curPathPointIdx = firstPathPointIdx + pathPointCount;
+
+               if (ptrSegment > 0)
+                       ptrPath += ptrSegment;
+               else
+                       ptrPath++;
        }
        _record_draw_cmd(ctx);
 }
index 9c01720b711874e304c9c457b2370f8664615dfc..1910635c3ea42d1d6435b2cea7e75af3e1ad19fb 100644 (file)
@@ -72,36 +72,40 @@ void _check_index_cache_size (VkvgContext ctx) {
        }
        ctx->indexCache = tmp;
 }
-void _check_pathes_array (VkvgContext ctx){
-       if (ctx->sizePathes - ctx->pathPtr - ctx->curvePtr > VKVG_ARRAY_THRESHOLD)
-               return;
+//check host path array size, return true if error. pathPtr is already incremented
+bool _check_pathes_array (VkvgContext ctx){
+       if (ctx->sizePathes - ctx->pathPtr - ctx->segmentPtr > VKVG_ARRAY_THRESHOLD)
+               return false;
        ctx->sizePathes += VKVG_PATHES_SIZE;
        uint32_t* tmp = (uint32_t*) realloc (ctx->pathes, (size_t)ctx->sizePathes * sizeof(uint32_t));
        LOG(VKVG_LOG_DBG_ARRAYS, "resize PATH: new size: %u Ptr: %p -> %p\n", ctx->sizePathes, ctx->pathes, tmp);
        if (tmp == NULL){
                ctx->status = VKVG_STATUS_NO_MEMORY;
                LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePathes * sizeof(uint32_t));
-               ctx->pathPtr = 0 + (ctx->pathPtr % 2);
-       }else
-               ctx->pathes = tmp;
+               _clear_path(ctx);
+               return true;
+       }
+       ctx->pathes = tmp;
+       return false;
 }
-void _check_point_array (VkvgContext ctx){
+//check host point array size, return true if error
+bool _check_point_array (VkvgContext ctx){
        if (ctx->sizePoints - ctx->pointCount > VKVG_ARRAY_THRESHOLD)
-               return;
-       ctx->sizePoints += VKVG_PATHES_SIZE;
+               return false;
+       ctx->sizePoints += VKVG_PTS_SIZE;
        vec2* tmp = (vec2*) realloc (ctx->points, (size_t)ctx->sizePoints * sizeof(vec2));
        LOG(VKVG_LOG_DBG_ARRAYS, "resize Points: new size(point): %u Ptr: %p -> %p\n", ctx->sizePoints, ctx->points, tmp);
        if (tmp == NULL){
                ctx->status = VKVG_STATUS_NO_MEMORY;
                LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePoints * sizeof(vec2));
-               ctx->pointCount = 0;
-       }else
-               ctx->points = tmp;
+               _clear_path (ctx);
+               return true;
+       }
+       ctx->points = tmp;
+       return false;
 }
-//when empty, ptr is even, else it's odd
-//when empty, no current point is defined.
 bool _current_path_is_empty (VkvgContext ctx) {
-       return ctx->pathPtr % 2 == 0;
+       return ctx->pathes [ctx->pathPtr] == 0;
 }
 //this function expect that current point exists
 vec2 _get_current_position (VkvgContext ctx) {
@@ -109,14 +113,28 @@ vec2 _get_current_position (VkvgContext ctx) {
 }
 //set curve start point and set path has curve bit
 void _set_curve_start (VkvgContext ctx) {
-       ctx->pathes[ctx->pathPtr + ctx->curvePtr + 1] = (ctx->pointCount - 1);
-       ctx->pathes[ctx->pathPtr - 1] |= PATH_HAS_CURVES_BIT;
+       if (ctx->segmentPtr > 0) {
+               //check if current segment has points (straight)
+               if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) > 0)
+                       ctx->segmentPtr++;
+       }else{
+               //not yet segmented path, first segment length is copied
+               if (ctx->pathes [ctx->pathPtr] > 0){//create first straight segment first
+                       ctx->pathes [ctx->pathPtr + 1] = ctx->pathes [ctx->pathPtr];
+                       ctx->segmentPtr = 2;
+               }else
+                       ctx->segmentPtr = 1;
+       }
+       _check_pathes_array(ctx);
+       ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
 }
-//set curve end point and set path is curve bit
+//compute segment length and set is curved bit
 void _set_curve_end (VkvgContext ctx) {
-       ctx->pathes [ctx->pathPtr + ctx->curvePtr + 2] = (ctx->pointCount - 1) | PATH_IS_CURVE_BIT;
-       ctx->curvePtr+=2;
+       //ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = ctx->pathes [ctx->pathPtr] - ctx->pathes [ctx->pathPtr + ctx->segmentPtr];
+       ctx->pathes [ctx->pathPtr + ctx->segmentPtr] |= PATH_IS_CURVE_BIT;
+       ctx->segmentPtr++;
        _check_pathes_array(ctx);
+       ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
 }
 //path start pointed at ptrPath has curve bit
 bool _path_has_curves (VkvgContext ctx, uint32_t ptrPath) {
@@ -124,33 +142,56 @@ bool _path_has_curves (VkvgContext ctx, uint32_t ptrPath) {
 }
 //this function expect that current path is empty
 void _start_sub_path (VkvgContext ctx, float x, float y) {
-       //set start to current idx in point array
-       ctx->pathes[ctx->pathPtr] = ctx->pointCount;
-       _add_point(ctx, x, y);
-       _check_pathes_array(ctx);
-       ctx->pathPtr++;
+       _add_point (ctx, x, y);
 }
 void _finish_path (VkvgContext ctx){
-       if (_current_path_is_empty(ctx))
+       if (ctx->pathes [ctx->pathPtr] == 0)//empty
                return;
-       if (ctx->pathes[ctx->pathPtr-1] == ctx->pointCount - 1){
+       if ((ctx->pathes [ctx->pathPtr]&PATH_ELT_MASK) < 2){
                //only current pos is in path
-               ctx->pathPtr--;
+               ctx->pointCount -= ctx->pathes[ctx->pathPtr];//what about the bounds?
+               ctx->pathes[ctx->pathPtr] = 0;
+               ctx->segmentPtr = 0;
                return;
        }
 
-       //set end index of current path to last point in points array
-       ctx->pathes[ctx->pathPtr] = ctx->pointCount - 1;
-       _check_pathes_array(ctx);
-       ctx->pathPtr += ctx->curvePtr + 1;
-       ctx->curvePtr = 0;
+       if (ctx->segmentPtr > 0) {
+               ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT;
+               //if last segment is not a curve and point count > 0
+               if ((ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_IS_CURVE_BIT)==0 &&
+                               (ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_ELT_MASK) > 0)
+                       ctx->segmentPtr++;//current segment has to be included
+               ctx->pathPtr += ctx->segmentPtr;
+       }else
+               ctx->pathPtr ++;
+
+       if (_check_pathes_array(ctx))
+               return;
+
+       ctx->pathes[ctx->pathPtr] = 0;
+       ctx->segmentPtr = 0;
 }
+//clear path datas in context
 void _clear_path (VkvgContext ctx){
        ctx->pathPtr = 0;
+       ctx->pathes [ctx->pathPtr] = 0;
        ctx->pointCount = 0;
-       ctx->curvePtr = 0;
+       ctx->segmentPtr = 0;
        _resetMinMax(ctx);
 }
+void _remove_last_point (VkvgContext ctx){
+       ctx->pathes[ctx->pathPtr]--;
+       ctx->pointCount--;
+       if (ctx->segmentPtr > 0){//if path is segmented
+               if (!ctx->pathes [ctx->pathPtr + ctx->segmentPtr])//if current segment is empty
+                       ctx->segmentPtr--;
+               ctx->pathes [ctx->pathPtr + ctx->segmentPtr]--;//decrement last segment point count
+               if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) == 0)//if no point left (was only one)
+                       ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;//reset current segment
+               else if (ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_IS_CURVE_BIT)//if segment is a curve
+                       ctx->segmentPtr++;//then segPtr has to be forwarded to new segment
+       }
+}
 bool _path_is_closed (VkvgContext ctx, uint32_t ptrPath){
        return ctx->pathes[ptrPath] & PATH_CLOSED_BIT;
 }
@@ -159,10 +200,14 @@ void _resetMinMax (VkvgContext ctx) {
        ctx->xMax = ctx->yMax = FLT_MIN;
 }
 void _add_point (VkvgContext ctx, float x, float y){
-       ctx->points[ctx->pointCount] = (vec2){x,y};
-       ctx->pointCount++;
+       if (_check_point_array(ctx))
+               return;
 
-       _check_point_array(ctx);
+       ctx->points[ctx->pointCount] = (vec2){x,y};
+       ctx->pointCount++;//total point count of pathes, (for array bounds check)
+       ctx->pathes[ctx->pathPtr]++;//total point count in path
+       if (ctx->segmentPtr > 0)
+               ctx->pathes[ctx->pathPtr + ctx->segmentPtr]++;//total point count in path's segment
 
        //bounds are computed here to scissor the painting operation
        //that speed up fill drastically.
@@ -1033,53 +1078,53 @@ void _poly_fill (VkvgContext ctx){
 
        CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelinePolyFill);
 
-       uint32_t ptrPath = 0;
        Vertex v = {{0},{0,0,-1}};
+       uint32_t ptrPath = 0;
+       uint32_t firstPtIdx = 0;
 
        while (ptrPath < ctx->pathPtr){
-               if (ctx->pathes[ptrPath+1]&PATH_IS_CURVE_BIT){
-                       ptrPath += 2;
-                       continue;
-               }
                //close path
                ctx->pathes[ptrPath] |= PATH_CLOSED_BIT;
 
-               uint32_t firstPtIdx = ctx->pathes [ptrPath] & PATH_ELT_MASK;
-               uint32_t lastPtIdx  = ctx->pathes [ptrPath+1] & PATH_ELT_MASK;
-               uint32_t pathPointCount = lastPtIdx - firstPtIdx + 1;
-               uint32_t firstVertIdx = ctx->vertCount;
+               uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+               VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
 
                for (uint32_t i = 0; i < pathPointCount; i++) {
                        v.pos = ctx->points [i+firstPtIdx];
-                       ctx->vertexCache[ctx->vertCount] = v;
-                       ctx->vertCount++;
-
+                       ctx->vertexCache[ctx->vertCount++] = v;
                        _check_vertex_cache_size(ctx);
                }
 
                LOG(VKVG_LOG_INFO_PATH, "\tpoly fill: point count = %d; 1st vert = %d; vert count = %d\n", pathPointCount, firstVertIdx, ctx->vertCount - firstVertIdx);
                CmdDraw (ctx->cmd, pathPointCount, 1, firstVertIdx , 0);
 
-               ptrPath+=2;
+               firstPtIdx += pathPointCount;
+
+               if (_path_has_curves (ctx, ptrPath)) {
+                       //skip segments lengths used in stroke
+                       ptrPath++;
+                       uint32_t totPts = 0;
+                       while (totPts < pathPointCount)
+                               totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+               }else
+                       ptrPath++;
        }
        ctx->curVertOffset = ctx->vertCount;
 }
 void _fill_ec (VkvgContext ctx){
-       uint32_t ptrPath = 0;;
        Vertex v = {0};
        v.uv.z = -1;
 
+       uint32_t ptrPath = 0;
+       uint32_t firstPtIdx = 0;
+
        while (ptrPath < ctx->pathPtr){
-               if (ctx->pathes[ptrPath+1] & PATH_IS_CURVE_BIT){
-                       ptrPath += 2;
-                       continue;
-               }
                ctx->pathes[ptrPath] |= PATH_CLOSED_BIT;//close path
 
-               uint32_t firstPtIdx             = ctx->pathes[ptrPath]  &PATH_ELT_MASK;
-               uint32_t lastPtIdx              = ctx->pathes[ptrPath+1]&PATH_ELT_MASK;
-               uint32_t pathPointCount = lastPtIdx - firstPtIdx + 1;
-               VKVG_IBO_INDEX_TYPE firstVertIdx        = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+               uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+               VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
 
                ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
                uint32_t ecps_count = pathPointCount;
@@ -1135,7 +1180,15 @@ void _fill_ec (VkvgContext ctx){
                if (ecps_count == 3)
                        _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
 
-               ptrPath+=2;
+               firstPtIdx += pathPointCount;
+               if (_path_has_curves (ctx, ptrPath)) {
+                       //skip segments lengths used in stroke
+                       ptrPath++;
+                       uint32_t totPts = 0;
+                       while (totPts < pathPointCount)
+                               totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+               }else
+                       ptrPath++;
                free (ecps);
        }
        _record_draw_cmd(ctx);
index 5e5b548bb2cbd68ae2752e21bc323efb8d8094d4..6751090ff9ae919c4f212cb99cd47de6be269dde 100644 (file)
@@ -121,17 +121,12 @@ typedef struct _vkvg_context_t {
        uint32_t        sizePoints;     //reserved size
        uint32_t        pointCount;     //effective points count
 
-       //pathes array is a list of couple (start,end) point idx refering to point array
-       //it split points list in subpathes and tell if path is closed.
-       uint32_t        pathPtr;        //pointer in the path array, even=start point;odd=end point
+       //pathes array is a list of point count per segment
+       uint32_t        pathPtr;        //pointer in the path array
        uint32_t*       pathes;
        uint32_t        sizePathes;
 
-       //if current path contains curves, curve's start/end points are store next to the path start/stop
-       //curve start point = pathPtr + curvePtr
-       //when closing of finishing path, pathPtr is incremented by 1 + pathPtr
-       //note:number of pathes can no longer be computed from pathPtr/2, the array contains now curves datas
-       uint32_t    curvePtr;
+       uint32_t    segmentPtr;         //current segment count in current path having curves
 
        float           lineWidth;
        uint32_t    dashCount;      //value count in dash array, 0 if dash not set.
@@ -169,12 +164,13 @@ void _check_flush_needed    (VkvgContext ctx);
 void _check_vertex_cache_size(VkvgContext ctx);
 void _resize_vertex_cache      (VkvgContext ctx, uint32_t newSize);
 void _check_index_cache_size(VkvgContext ctx);
-void _check_pathes_array       (VkvgContext ctx);
+bool _check_pathes_array       (VkvgContext ctx);
 
 bool _current_path_is_empty (VkvgContext ctx);
 void _start_sub_path        (VkvgContext ctx, float x, float y);
 void _finish_path                      (VkvgContext ctx);
 void _clear_path                       (VkvgContext ctx);
+void _remove_last_point                (VkvgContext ctx);
 bool _path_is_closed           (VkvgContext ctx, uint32_t ptrPath);
 void _set_curve_start       (VkvgContext ctx);
 void _set_curve_end         (VkvgContext ctx);
index 1674e05c16194a3d70a5a0550f0293eeb9561808..ec7ccdeea7a439007fdfeb0c92e87d665f28aebf 100644 (file)
 #endif*/
 
 #define PATH_CLOSED_BIT     0x80000000              /* most significant bit of path elmts is closed/open path state */
-#define PATH_HAS_CURVES_BIT 0x40000000              /* 2d most significant bit of path elmts start = true if curve data are present,
-                                                                                                          stored to avoid emiting join in curves */
+#define PATH_HAS_CURVES_BIT 0x40000000              /* 2d most significant bit of path elmts  if curve data are present,
+                                                                                                          stored to avoid emiting joins in curves */
 #define PATH_IS_CURVE_BIT   0x80000000              /* most significant bit of path elmts end mark curves data in path array */
 #define PATH_IS_CONCAVE_BIT 0x40000000              /* 2d most significant bit of path elmts end = true if path is simple concave
-                                                                                                          triangulation for fill may be simplified*/
+                                                                                                          triangulation for fill may be simplified (not implemented)*/
 #define PATH_ELT_MASK       0x3FFFFFFF              /* Bit mask for fetching path element value */
 
 #define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))