]> O.S.I.I.S - jp/vkvg.git/commitdiff
move internal stroke func and struct to vkvg_context_internal
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Dec 2021 04:11:15 +0000 (05:11 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Dec 2021 04:11:15 +0000 (05:11 +0100)
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
tests/inverse_colinear.c [new file with mode: 0644]

index 91d689b5266d080bc2fb317ddddb4313685a878a..d87c41ab272ee5cb4ffc7db56038791f0aa6c120 100644 (file)
@@ -673,124 +673,6 @@ void vkvg_fill_preserve (VkvgContext ctx){
                _ensure_renderpass_is_started(ctx);
        _fill_ec(ctx);
 }
-void _draw_stoke_cap (VkvgContext ctx, float hw, vec2 p0, vec2 n, bool isStart) {
-       Vertex v = {{0},ctx->curColor,{0,0,-1}};
-
-       VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);      
-
-       if (isStart){
-               vec2 vhw = vec2_mult(n,hw);
-
-               if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
-                       p0 = vec2_sub(p0, vhw);
-
-               vhw = vec2_perp(vhw);
-
-               if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
-                       float step = M_PIF / fmaxf(hw, 4.f);
-                       float a = acosf(n.x) + M_PIF_2;
-                       if (n.y < 0)
-                               a = M_PIF-a;
-                       float a1 = a + M_PIF;
-
-                       a+=step;
-                       while (a < a1){
-                               _add_vertexf(ctx, cosf(a) * hw + p0.x, sinf(a) * hw + p0.y);
-                               a+=step;
-                       }
-                       VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-                       for (VKVG_IBO_INDEX_TYPE p = firstIdx; p < p0Idx; p++)
-                               _add_triangle_indices(ctx, p0Idx+1, p, p+1);
-                       firstIdx = p0Idx;
-               }
-
-               v.pos = vec2_add(p0, vhw);
-               _add_vertex(ctx, v);
-               v.pos = vec2_sub(p0, vhw);
-               _add_vertex(ctx, v);
-
-               _add_tri_indices_for_rect(ctx, firstIdx);
-       }else{
-               vec2 vhw = vec2_mult(n, hw);
-
-               if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
-                       p0 = vec2_add(p0, vhw);
-
-               vhw = vec2_perp(vhw);
-
-               v.pos = vec2_add(p0, vhw);
-               _add_vertex(ctx, v);
-               v.pos = vec2_sub(p0, vhw);
-               _add_vertex(ctx, v);
-
-               firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
-
-               if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
-                       float step = M_PIF / fmaxf(hw, 4.f);
-                       float a = acosf(n.x)+ M_PIF_2;
-                       if (n.y < 0)
-                               a = M_PIF-a;
-                       float a1 = a - M_PIF;
-
-                       a-=step;
-                       while ( a > a1){
-                               _add_vertexf(ctx, cosf(a) * hw + p0.x, sinf(a) * hw + p0.y);
-                               a-=step;
-                       }
-
-                       VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset - 1);
-                       for (VKVG_IBO_INDEX_TYPE p = firstIdx-1 ; p < p0Idx; p++)
-                               _add_triangle_indices(ctx, p+1, p, firstIdx-2);
-               }
-       }
-}
-
-typedef struct {
-       bool    dashOn;
-       uint32_t curDash;       //current dash index
-       float   curDashOffset;  //cur dash offset between defined path point and last dash segment(on/off) start
-       float   totDashLength;  //total length of dashes
-       vec2    normal;
-}dash_context_t;
-
-typedef struct {
-       uint32_t iL;
-       uint32_t iR;
-       uint32_t cp;//current point
-}stroke_context_t;
-
-float _draw_dashed_segment (VkvgContext ctx, float hw, dash_context_t* dc, vec2 pL, vec2 p, vec2 pR, bool isCurve) {
-       if (!dc->dashOn)//we test in fact the next dash start, if dashOn = true => next segment is a void.
-               _build_vb_step (ctx, hw, pL, p, pR, isCurve);
-
-       vec2 d = vec2_sub (pR, p);
-       dc->normal = vec2_norm (d);
-       float segmentLength = vec2_length(d);
-
-       while (dc->curDashOffset < segmentLength){
-               vec2 p0 = vec2_add (p, vec2_mult(dc->normal, dc->curDashOffset));
-
-               _draw_stoke_cap (ctx, hw, p0, dc->normal, dc->dashOn);
-               dc->dashOn ^= true;
-               dc->curDashOffset += ctx->dashes[dc->curDash];
-               if (++dc->curDash == ctx->dashCount)
-                       dc->curDash = 0;
-       }
-       dc->curDashOffset -= segmentLength;
-       dc->curDashOffset = fmodf(dc->curDashOffset, dc->totDashLength);
-       return segmentLength;
-}
-
-
-
-void _draw_segment (VkvgContext ctx, float hw, stroke_context_t* str, dash_context_t* dc, bool isCurve) {
-       str->iR = str->cp + 1;
-       if (ctx->dashCount > 0)
-               _draw_dashed_segment(ctx, hw, dc, ctx->points[str->iL], ctx->points[str->cp], ctx->points[str->iR], isCurve);
-       else
-               _build_vb_step (ctx, hw, ctx->points[str->iL], ctx->points[str->cp], ctx->points[str->iR], isCurve);
-       str->iL = str->cp++;
-}
 
 void vkvg_stroke_preserve (VkvgContext ctx)
 {
@@ -870,7 +752,11 @@ void vkvg_stroke_preserve (VkvgContext ctx)
                if (ctx->dashCount > 0) {
                        if (_path_is_closed(ctx,ptrPath)){
                                str.iR = firstPathPointIdx;
-                               _draw_dashed_segment(ctx, hw, &dc, ctx->points[str.iL++], ctx->points[str.cp++], ctx->points[str.iR], false);
+
+                               _draw_dashed_segment(ctx, hw, &str, &dc, false);
+
+                               str.iL++;
+                               str.cp++;
                        }
                        if (!dc.dashOn){
                                //finishing last dash that is already started, draw end caps but not too close to start
@@ -884,7 +770,7 @@ void vkvg_stroke_preserve (VkvgContext ctx)
                        }
                } else if (_path_is_closed(ctx,ptrPath)){
                        str.iR = firstPathPointIdx;
-                       float cross = _build_vb_step (ctx, hw, ctx->points[str.iL], ctx->points[str.cp], ctx->points[str.iR], false);
+                       float cross = _build_vb_step (ctx, hw, &str, false);
 
                        VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6];
                        VKVG_IBO_INDEX_TYPE ii = firstIdx;
index 2cef1ad91a634c12d6615a5ec4b8e3a36a47b971..bd1593bfe8a7df833a1c2ad0a9e2076e3526a702 100644 (file)
@@ -737,8 +737,11 @@ void _init_descriptor_sets (VkvgContext ctx){
        VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsGrad));
 }
 //populate vertice buff for stroke
-float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bool isCurve){
+float _build_vb_step (vkvg_context* ctx, float hw, stroke_context_t* str, bool isCurve){
        Vertex v = {{0},ctx->curColor, {0,0,-1}};
+       vec2 pL = ctx->points[str->iL];
+       vec2 p0 = ctx->points[str->cp];
+       vec2 pR = ctx->points[str->iR];
 
        vec2 v0 = vec2_sub(p0, pL);
        vec2 v1 = vec2_sub(pR, p0);
@@ -762,7 +765,7 @@ float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bo
        bisec_n = vec2_perp(bisec_n);
 
        //limit bisectrice length, may be improved but ok for perf
-       lh=fminf (lh, fminf (sqrtf(length_v0*length_v0+hw*hw), sqrtf(length_v1*length_v1+hw*hw)));
+       //lh=fminf (lh, fminf (sqrtf(length_v0*length_v0+hw*hw), sqrtf(length_v1*length_v1+hw*hw)));
 
 
        vec2 bisec = vec2_mult(bisec_n,lh);
@@ -823,7 +826,7 @@ float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bo
                        }
                        VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
                        _add_triangle_indices(ctx, idx, idx+2, idx+1);
-                       if (det<0){
+                       if (det < 0){
                                for (VKVG_IBO_INDEX_TYPE p = idx+2; p < p0Idx; p++)
                                        _add_triangle_indices(ctx, p, p+1, idx);
                                _add_triangle_indices(ctx, p0Idx, p0Idx+2, idx);
@@ -838,11 +841,13 @@ float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bo
                }
 
                vp = vec2_mult (vec2_perp(v1n), hw);
-               if (det<0)
+               if (det < 0)
                        v.pos = vec2_sub (p0, vp);
                else
                        v.pos = vec2_add (p0, vp);
                _add_vertex(ctx, v);
+               str->has_prev_v0n = true;
+               str->prev_v0n = v0n;
        }
 
 /*
@@ -861,6 +866,111 @@ float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bo
        return det;
 }
 
+void _draw_stoke_cap (VkvgContext ctx, float hw, vec2 p0, vec2 n, bool isStart) {
+       Vertex v = {{0},ctx->curColor,{0,0,-1}};
+
+       VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+       if (isStart){
+               vec2 vhw = vec2_mult(n,hw);
+
+               if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
+                       p0 = vec2_sub(p0, vhw);
+
+               vhw = vec2_perp(vhw);
+
+               if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
+                       float step = M_PIF / fmaxf(hw, 4.f);
+                       float a = acosf(n.x) + M_PIF_2;
+                       if (n.y < 0)
+                               a = M_PIF-a;
+                       float a1 = a + M_PIF;
+
+                       a+=step;
+                       while (a < a1){
+                               _add_vertexf(ctx, cosf(a) * hw + p0.x, sinf(a) * hw + p0.y);
+                               a+=step;
+                       }
+                       VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+                       for (VKVG_IBO_INDEX_TYPE p = firstIdx; p < p0Idx; p++)
+                               _add_triangle_indices(ctx, p0Idx+1, p, p+1);
+                       firstIdx = p0Idx;
+               }
+
+               v.pos = vec2_add(p0, vhw);
+               _add_vertex(ctx, v);
+               v.pos = vec2_sub(p0, vhw);
+               _add_vertex(ctx, v);
+
+               _add_tri_indices_for_rect(ctx, firstIdx);
+       }else{
+               vec2 vhw = vec2_mult(n, hw);
+
+               if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
+                       p0 = vec2_add(p0, vhw);
+
+               vhw = vec2_perp(vhw);
+
+               v.pos = vec2_add(p0, vhw);
+               _add_vertex(ctx, v);
+               v.pos = vec2_sub(p0, vhw);
+               _add_vertex(ctx, v);
+
+               firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+
+               if (ctx->lineCap == VKVG_LINE_CAP_ROUND){
+                       float step = M_PIF / fmaxf(hw, 4.f);
+                       float a = acosf(n.x)+ M_PIF_2;
+                       if (n.y < 0)
+                               a = M_PIF-a;
+                       float a1 = a - M_PIF;
+
+                       a-=step;
+                       while ( a > a1){
+                               _add_vertexf(ctx, cosf(a) * hw + p0.x, sinf(a) * hw + p0.y);
+                               a-=step;
+                       }
+
+                       VKVG_IBO_INDEX_TYPE p0Idx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset - 1);
+                       for (VKVG_IBO_INDEX_TYPE p = firstIdx-1 ; p < p0Idx; p++)
+                               _add_triangle_indices(ctx, p+1, p, firstIdx-2);
+               }
+       }
+}
+float _draw_dashed_segment (VkvgContext ctx, float hw, stroke_context_t* str, dash_context_t* dc, bool isCurve) {
+       //vec2 pL = ctx->points[str->iL];
+       vec2 p = ctx->points[str->cp];
+       vec2 pR = ctx->points[str->iR];
+
+       if (!dc->dashOn)//we test in fact the next dash start, if dashOn = true => next segment is a void.
+               _build_vb_step (ctx, hw, str, isCurve);
+
+       vec2 d = vec2_sub (pR, p);
+       dc->normal = vec2_norm (d);
+       float segmentLength = vec2_length(d);
+
+       while (dc->curDashOffset < segmentLength){
+               vec2 p0 = vec2_add (p, vec2_mult(dc->normal, dc->curDashOffset));
+
+               _draw_stoke_cap (ctx, hw, p0, dc->normal, dc->dashOn);
+               dc->dashOn ^= true;
+               dc->curDashOffset += ctx->dashes[dc->curDash];
+               if (++dc->curDash == ctx->dashCount)
+                       dc->curDash = 0;
+       }
+       dc->curDashOffset -= segmentLength;
+       dc->curDashOffset = fmodf(dc->curDashOffset, dc->totDashLength);
+       return segmentLength;
+}
+void _draw_segment (VkvgContext ctx, float hw, stroke_context_t* str, dash_context_t* dc, bool isCurve) {
+       str->iR = str->cp + 1;
+       if (ctx->dashCount > 0)
+               _draw_dashed_segment(ctx, hw, str, dc, isCurve);
+       else
+               _build_vb_step (ctx, hw, str, isCurve);
+       str->iL = str->cp++;
+}
+
 bool ptInTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2) {
        float dX = p.x-p2.x;
        float dY = p.y-p2.y;
index 9c6f962bb0a00b31ae85a22b7bf52250ff411dd1..1fa7830b38cb9ec7ce4877d063d068365f5bf52b 100644 (file)
@@ -191,6 +191,23 @@ typedef struct _ear_clip_point{
        struct _ear_clip_point* next;
 }ear_clip_point;
 
+typedef struct {
+       bool    dashOn;
+       uint32_t curDash;       //current dash index
+       float   curDashOffset;  //cur dash offset between defined path point and last dash segment(on/off) start
+       float   totDashLength;  //total length of dashes
+       vec2    normal;
+}dash_context_t;
+
+typedef struct {
+       uint32_t iL;
+       uint32_t iR;
+       uint32_t iR2;
+       uint32_t cp;//current point
+       bool has_prev_v0n;//true if set
+       vec2 prev_v0n;//store previous left normal for path correction
+}stroke_context_t;
+
 void _check_vertex_cache_size(VkvgContext ctx);
 void _resize_vertex_cache      (VkvgContext ctx, uint32_t newSize);
 void _check_index_cache_size(VkvgContext ctx);
@@ -213,6 +230,10 @@ void _add_point                            (VkvgContext ctx, float x, float y);
 
 void _resetMinMax                      (VkvgContext ctx);
 
+void _draw_stoke_cap           (VkvgContext ctx, float hw, vec2 p0, vec2 n, bool isStart);
+void _draw_segment                     (VkvgContext ctx, float hw, stroke_context_t* str, dash_context_t* dc, bool isCurve);
+float _draw_dashed_segment     (VkvgContext ctx, float hw, stroke_context_t *str, dash_context_t* dc, bool isCurve);
+
 void _poly_fill                                (VkvgContext ctx);
 void _fill_ec                          (VkvgContext ctx);//earclipping fill
 void _draw_full_screen_quad (VkvgContext ctx, bool useScissor);
@@ -224,7 +245,8 @@ void _add_vertexf                   (VkvgContext ctx, float x, float y);
 void _set_vertex                       (VkvgContext ctx, uint32_t idx, Vertex v);
 void _add_triangle_indices     (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_INDEX_TYPE i1, VKVG_IBO_INDEX_TYPE i2);
 void _add_tri_indices_for_rect (VkvgContext ctx, VKVG_IBO_INDEX_TYPE i);
-float _build_vb_step           (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bool isCurve);
+float _build_vb_step           (vkvg_context* ctx, float hw, stroke_context_t *str, bool isCurve);
+
 void _vao_add_rectangle                (VkvgContext ctx, float x, float y, float width, float height);
 
 void _bind_draw_pipeline       (VkvgContext ctx);
diff --git a/tests/inverse_colinear.c b/tests/inverse_colinear.c
new file mode 100644 (file)
index 0000000..5799aec
--- /dev/null
@@ -0,0 +1,148 @@
+#include "test.h"
+#include "vectors.h"
+
+vkvg_fill_rule_t fillrule = VKVG_FILL_RULE_NON_ZERO;
+static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT;
+float lineWidth = 50.0f;
+vkvg_line_join_t lineJoin = VKVG_LINE_JOIN_MITER;
+vkvg_line_cap_t lineCap = VKVG_LINE_CAP_BUTT;
+bool isClosed = false;
+
+int ptsCount = 4;
+int initPtsCount = 4;
+vec2 pts[] = {
+       {150,150},
+       {200,300},
+       {250,150},
+       {280,350},
+};
+int hoverPt = -1;
+double pointSize = 7;
+
+
+void draw (){
+       VkvgContext ctx = vkvg_create(surf);
+       vkvg_clear(ctx);
+       vkvg_set_source_rgba(ctx,1,0,0,1);
+       vkvg_set_line_width(ctx,lineWidth);
+       vkvg_set_line_join      (ctx, line_join);
+       vkvg_move_to(ctx,pts[0].x,pts[0].y);
+       for (int i=1; i<ptsCount; i++)
+               vkvg_line_to(ctx,pts[i].x,pts[i].y);
+       if (isClosed)
+               vkvg_close_path(ctx);
+
+       if (hoverPt>=0) {
+               vkvg_stroke_preserve(ctx);
+               vkvg_set_line_width(ctx,2);
+               vkvg_set_source_rgba(ctx,0,0,0,1);
+               vkvg_stroke(ctx);
+               vkvg_set_source_rgba(ctx,0.5f,0.5f,1.0f,0.7f);
+               vkvg_arc(ctx, pts[hoverPt].x, pts[hoverPt].y, pointSize, 0, M_PIF*2);
+               vkvg_fill_preserve(ctx);
+               vkvg_stroke(ctx);
+       } else
+               vkvg_stroke(ctx);
+
+       //draw_v(ctx, 200, 20, VKVG_LINE_JOIN_BEVEL);
+       //draw_v(ctx, 300, 80, VKVG_LINE_JOIN_ROUND);
+       vkvg_destroy(ctx);
+}
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+       if (action != GLFW_PRESS)
+               return;
+       switch (key) {
+       case GLFW_KEY_ESCAPE :
+               glfwSetWindowShouldClose(window, GLFW_TRUE);
+               break;
+       case GLFW_KEY_C :
+               isClosed ^= true;
+               break;
+       case GLFW_KEY_KP_ADD :
+               if (ptsCount < initPtsCount)
+                       ptsCount++;
+               break;
+       case GLFW_KEY_KP_SUBTRACT :
+               if (ptsCount > 1)
+                       ptsCount--;
+               break;
+       }
+}
+static void mouse_move_callback(GLFWwindow* window, double x, double y){
+       if (mouseDown) {
+               if (hoverPt < 0)
+                       return;
+               pts[hoverPt].x = x;
+               pts[hoverPt].y = y;
+       } else {
+               for (int i=0; i<ptsCount; i++) {
+                       if (x > pts[i].x - pointSize &&
+                               x < pts[i].x + pointSize &&
+                               y > pts[i].y - pointSize &&
+                               y < pts[i].y + pointSize) {
+                               hoverPt = i;
+                               return;
+                       }
+               }
+               hoverPt = -1;
+       }
+}
+static void scroll_callback(GLFWwindow* window, double x, double y){
+       if (y<0.f)
+               zoom *= 0.5f;
+       else
+               zoom *= 2.0f;
+}
+static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif){
+       if (but != GLFW_MOUSE_BUTTON_1)
+               return;
+       if (state == GLFW_TRUE)
+               mouseDown = true;
+       else
+               mouseDown = false;
+}
+
+
+
+int main(int argc, char* argv[]) {
+       _parse_args (argc, argv);
+       VkEngine e;
+       e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_FIFO_KHR, test_width, test_height);
+
+       VkhPresenter r = e->renderer;
+       vkengine_set_key_callback (e, key_callback);
+       vkengine_set_mouse_but_callback(e, mouse_button_callback);
+       vkengine_set_cursor_pos_callback(e, mouse_move_callback);
+       vkengine_set_scroll_callback(e, scroll_callback);
+
+       bool deferredResolve = false;
+
+       device = vkvg_device_create_from_vk_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, samples, deferredResolve);
+       surf = vkvg_surface_create(device, test_width, test_height);
+
+       vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+
+       while (!vkengine_should_close (e)) {
+               glfwPollEvents();
+
+               draw ();
+
+               if (!vkh_presenter_draw (r)){
+                       vkh_presenter_get_size (r, &test_width, &test_height);
+                       vkvg_surface_destroy (surf);
+                       surf = vkvg_surface_create(device, test_width, test_height);
+                       vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), test_width, test_height);
+                       vkDeviceWaitIdle(r->dev->dev);
+                       continue;
+               }
+       }
+       vkDeviceWaitIdle(e->dev->dev);
+
+       vkvg_surface_destroy    (surf);
+
+       vkvg_device_destroy     (device);
+
+       vkengine_destroy (e);
+
+       return 0;
+}