From: Jean-Philippe Bruyère Date: Tue, 30 Apr 2019 03:40:54 +0000 (+0200) Subject: reimplement ear clipping for triangulation with non-zero fill rule X-Git-Tag: v0.1-alpha~89 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=beec464760b389deb8270d445bee05dfcd052653;p=jp%2Fvkvg.git reimplement ear clipping for triangulation with non-zero fill rule --- diff --git a/include/vkvg.h b/include/vkvg.h index acd89dc..9649561 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -121,6 +121,11 @@ typedef enum _vkvg_line_join { VKVG_LINE_JOIN_BEVEL } vkvg_line_join_t; +typedef enum _vkvg_fill_rule { + VKVG_FILL_RULE_EVEN_ODD, + VKVG_FILL_RULE_NON_ZERO +} vkvg_fill_rule_t; + typedef struct _vkvg_color_t{ float r; float g; @@ -258,11 +263,14 @@ void vkvg_set_line_join (VkvgContext ctx, vkvg_line_join_t join); void vkvg_set_source_surface(VkvgContext ctx, VkvgSurface surf, float x, float y); void vkvg_set_source (VkvgContext ctx, VkvgPattern pat); void vkvg_set_operator (VkvgContext ctx, vkvg_operator_t op); +void vkvg_set_fill_rule (VkvgContext ctx, vkvg_fill_rule_t fr); + float vkvg_get_line_width (VkvgContext ctx); vkvg_line_cap_t vkvg_get_line_cap (VkvgContext ctx); vkvg_line_join_t vkvg_get_line_join (VkvgContext ctx); vkvg_operator_t vkvg_get_operator (VkvgContext ctx); +vkvg_fill_rule_t vkvg_get_fill_rule (VkvgContext ctx); VkvgPattern vkvg_get_source (VkvgContext ctx); void vkvg_save (VkvgContext ctx); diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 28ab113..5e6ecf8 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -55,6 +55,7 @@ VkvgContext vkvg_create(VkvgSurface surf) ctx->lineWidth = 1; ctx->pSurf = surf; ctx->curOperator = VKVG_OPERATOR_OVER; + ctx->curFillRule = VKVG_FILL_RULE_EVEN_ODD; push_constants pc = { {.height=1}, @@ -436,34 +437,6 @@ void vkvg_fill (VkvgContext ctx){ vkvg_fill_preserve(ctx); _clear_path(ctx); } -void _poly_fill (VkvgContext ctx){ - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelinePolyFill); - - uint32_t ptrPath = 0; - Vertex v = {}; - v.uv.z = -1; - - while (ptrPath < ctx->pathPtr){ - if (!_path_is_closed(ctx, ptrPath)) - ctx->pathes[ptrPath+1] = ctx->pathes[ptrPath];//close path by setting start and end equal - - uint32_t firstPtIdx = ctx->pathes[ptrPath]; - uint32_t lastPtIdx = _get_last_point_of_closed_path (ctx, ptrPath); - uint32_t pathPointCount = lastPtIdx - ctx->pathes[ptrPath] + 1; - uint32_t firstVertIdx = ctx->vertCount; - - - for (int i = 0; i < pathPointCount; i++) { - v.pos = ctx->points[i+firstPtIdx]; - _add_vertex(ctx, v); - } - - LOG(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; - } -} void vkvg_clip_preserve (VkvgContext ctx){ if (ctx->pathPtr == 0) //nothing to fill return; @@ -472,12 +445,25 @@ void vkvg_clip_preserve (VkvgContext ctx){ if (ctx->pointCount * 4 > ctx->sizeIndices - ctx->indCount)//flush if vk buff is full vkvg_flush(ctx); - _check_cmd_buff_state(ctx); - _poly_fill (ctx); - - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping); + if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){ + _check_cmd_buff_state(ctx); + _poly_fill (ctx); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping); + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); + }else{ + _check_cmd_buff_state(ctx); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping); + CmdSetStencilReference (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + _fill_ec(ctx); + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); + } CmdDrawIndexed (ctx->cmd,6,1,0,0,0); - //should test current operator to bind correct pipeline _bind_draw_pipeline (ctx); CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); @@ -492,13 +478,19 @@ void vkvg_fill_preserve (VkvgContext ctx){ if (ctx->pointCount * 4 > ctx->sizeIndices - ctx->indCount)//flush if vk buff is full vkvg_flush(ctx); - _check_cmd_buff_state(ctx); - _poly_fill (ctx); - _bind_draw_pipeline (ctx); - CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); - CmdDrawIndexed (ctx->cmd,6,1,0,0,0); - CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD){ + _check_cmd_buff_state(ctx); + _poly_fill (ctx); + _bind_draw_pipeline (ctx); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + CmdDrawIndexed (ctx->cmd,6,1,0,0,0); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + }else{ + //CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); + _fill_ec(ctx); + //CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + } } void vkvg_stroke_preserve (VkvgContext ctx) { @@ -665,6 +657,12 @@ void vkvg_set_operator (VkvgContext ctx, vkvg_operator_t op){ ctx->curOperator = op; _bind_draw_pipeline (ctx); } +void vkvg_set_fill_rule (VkvgContext ctx, vkvg_fill_rule_t fr){ + ctx->curFillRule = fr; +} +vkvg_fill_rule_t vkvg_get_fill_rule (VkvgContext ctx){ + return ctx->curFillRule; +} float vkvg_get_line_width (VkvgContext ctx){ return ctx->lineWidth; } @@ -775,6 +773,7 @@ void vkvg_save (VkvgContext ctx){ sav->curOperator= ctx->curOperator; sav->lineCap = ctx->lineCap; sav->lineWidth = ctx->lineWidth; + sav->curFillRule= ctx->curFillRule; sav->selectedFont = ctx->selectedFont; sav->selectedFont.fontFile = (char*)calloc(FONT_FILE_NAME_MAX_SIZE,sizeof(char)); @@ -853,7 +852,8 @@ void vkvg_restore (VkvgContext ctx){ ctx->lineWidth = sav->lineWidth; ctx->curOperator= sav->curOperator; ctx->lineCap = sav->lineCap; - ctx->lineJoin = sav->lineJoint; + ctx->lineJoin = sav->lineJoint; + ctx->curFillRule= sav->curFillRule; ctx->selectedFont.charSize = sav->selectedFont.charSize; strcpy (ctx->selectedFont.fontFile, sav->selectedFont.fontFile); diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 2ffe7b3..21e7ac0 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -813,4 +813,95 @@ void _recursive_bezier (VkvgContext ctx, _recursive_bezier(ctx, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); _recursive_bezier(ctx, x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); } +void _poly_fill (VkvgContext ctx){ + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelinePolyFill); + uint32_t ptrPath = 0; + Vertex v = {}; + v.uv.z = -1; + + while (ptrPath < ctx->pathPtr){ + if (!_path_is_closed(ctx, ptrPath)) + ctx->pathes[ptrPath+1] = ctx->pathes[ptrPath];//close path by setting start and end equal + + uint32_t firstPtIdx = ctx->pathes[ptrPath]; + uint32_t lastPtIdx = _get_last_point_of_closed_path (ctx, ptrPath); + uint32_t pathPointCount = lastPtIdx - ctx->pathes[ptrPath] + 1; + uint32_t firstVertIdx = ctx->vertCount; + + + for (int i = 0; i < pathPointCount; i++) { + v.pos = ctx->points[i+firstPtIdx]; + _add_vertex(ctx, v); + } + + LOG(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; + } +} +void _fill_ec (VkvgContext ctx){ + uint32_t ptrPath = 0;; + Vertex v = {}; + v.uv.z = -1; + + while (ptrPath < ctx->pathPtr){ + if (!_path_is_closed(ctx, ptrPath)) + //close path + ctx->pathes[ptrPath+1] = ctx->pathes[ptrPath]; + + uint32_t firstPtIdx = ctx->pathes[ptrPath]; + uint32_t lastPtIdx = _get_last_point_of_closed_path (ctx, ptrPath); + uint32_t pathPointCount = lastPtIdx - ctx->pathes[ptrPath] + 1; + uint32_t firstVertIdx = ctx->vertCount; + + ear_clip_point ecps[pathPointCount]; + uint32_t ecps_count = pathPointCount; + uint32_t i = 0; + + //init points link list + while (i < pathPointCount-1){ + v.pos = ctx->points[i+firstPtIdx]; + ear_clip_point ecp = {v.pos, i+firstVertIdx, &ecps[i+1]}; + ecps[i] = ecp; + _add_vertex(ctx, v); + i++; + } + v.pos = ctx->points[i+firstPtIdx]; + ear_clip_point ecp = {v.pos, i+firstVertIdx, ecps}; + ecps[i] = ecp; + _add_vertex(ctx, v); + + ear_clip_point* ecp_current = ecps; + + while (ecps_count > 3) { + ear_clip_point* v0 = ecp_current->next, + *v1 = ecp_current, *v2 = ecp_current->next->next; + if (ecp_zcross (v0, v2, v1)<0){ + ecp_current = ecp_current->next; + continue; + } + ear_clip_point* vP = v2->next; + bool isEar = true; + while (vP!=v1){ + if (ptInTriangle (vP->pos, v0->pos, v2->pos, v1->pos)){ + isEar = false; + break; + } + vP = vP->next; + } + if (isEar){ + _add_triangle_indices (ctx, v0->idx, v1->idx, v2->idx); + v1->next = v2; + ecps_count --; + }else + ecp_current = ecp_current->next; + } + if (ecps_count == 3) + _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx); + + ptrPath+=2; + } + _record_draw_cmd(ctx); +} diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index 5614923..363ee77 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -66,6 +66,7 @@ typedef struct _vkvg_context_save_t{ vkvg_operator_t curOperator; vkvg_line_cap_t lineCap; vkvg_line_join_t lineJoint; + vkvg_fill_rule_t curFillRule; _vkvg_font_t selectedFont; //hold current face and size before cache addition _vkvg_font_t* currentFont; //font ready for lookup @@ -124,6 +125,7 @@ typedef struct _vkvg_context_t { vkvg_operator_t curOperator; vkvg_line_cap_t lineCap; vkvg_line_join_t lineJoin; + vkvg_fill_rule_t curFillRule; _vkvg_font_t selectedFont; //hold current face and size before cache addition _vkvg_font_t* currentFont; //font pointing to cached fonts ready for lookup @@ -138,6 +140,12 @@ typedef struct _vkvg_context_t { VkClearRect clearRect; }vkvg_context; +typedef struct _ear_clip_point{ + vec2 pos; + uint32_t idx; + struct _ear_clip_point* next; +}ear_clip_point; + bool _current_path_is_empty (VkvgContext ctx); void _start_sub_path (VkvgContext ctx, float x, float y); void _check_pathes_array (VkvgContext ctx); @@ -150,7 +158,10 @@ float _normalizeAngle (float a); vec2 _get_current_position (VkvgContext ctx); void _add_point (VkvgContext ctx, float x, float y); -void _add_point_vec2 (VkvgContext ctx, vec2 v); +void _add_point_vec2 (VkvgContext ctx, vec2 v); + +void _poly_fill (VkvgContext ctx); +void _fill_ec (VkvgContext ctx);//earclipping fill void _create_gradient_buff (VkvgContext ctx); void _create_vertices_buff (VkvgContext ctx); @@ -186,6 +197,9 @@ void _free_ctx_save (vkvg_context_save_t* sav); static inline float vec2_zcross (vec2 v1, vec2 v2){ return v1.x*v2.y-v1.y*v2.x; } +static inline float ecp_zcross (ear_clip_point* p0, ear_clip_point* p1, ear_clip_point* p2){ + return vec2_zcross (vec2_sub (p1->pos, p0->pos), vec2_sub (p2->pos, p0->pos)); +} void _recursive_bezier(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c index ad8b0dd..5ca87e3 100644 --- a/src/vkvg_device_internal.c +++ b/src/vkvg_device_internal.c @@ -207,7 +207,7 @@ void _setupPipelines(VkvgDevice dev) /*failOp,passOp,depthFailOp,compareOp, compareMask, writeMask, reference;*/ VkStencilOpState polyFillOpState ={VK_STENCIL_OP_KEEP,VK_STENCIL_OP_INVERT,VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_CLIP_BIT,STENCIL_FILL_BIT,0}; - VkStencilOpState clipingOpState = {VK_STENCIL_OP_REPLACE,VK_STENCIL_OP_ZERO,VK_STENCIL_OP_KEEP,VK_COMPARE_OP_NOT_EQUAL,STENCIL_FILL_BIT,STENCIL_ALL_BIT,0x2}; + VkStencilOpState clipingOpState = {VK_STENCIL_OP_ZERO,VK_STENCIL_OP_REPLACE,VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_FILL_BIT,STENCIL_ALL_BIT,0x2}; VkStencilOpState stencilOpState = {VK_STENCIL_OP_KEEP,VK_STENCIL_OP_ZERO,VK_STENCIL_OP_KEEP,VK_COMPARE_OP_EQUAL,STENCIL_FILL_BIT,STENCIL_FILL_BIT,0x1}; VkPipelineDepthStencilStateCreateInfo dsStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, @@ -222,6 +222,8 @@ void _setupPipelines(VkvgDevice dev) VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, + VK_DYNAMIC_STATE_STENCIL_REFERENCE, + VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, }; VkPipelineDynamicStateCreateInfo dynamicState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .dynamicStateCount = 2, @@ -292,7 +294,7 @@ void _setupPipelines(VkvgDevice dev) VkPipelineShaderStageCreateInfo shaderStages[] = {vertStage,fragStage}; - pipelineCreateInfo.stageCount = 2; + pipelineCreateInfo.stageCount = 1; pipelineCreateInfo.pStages = shaderStages; pipelineCreateInfo.pVertexInputState = &vertexInputState; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; @@ -309,11 +311,13 @@ void _setupPipelines(VkvgDevice dev) inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; dsStateCreateInfo.back = dsStateCreateInfo.front = clipingOpState; + dynamicState.dynamicStateCount = 5; VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipelineClipping)); dsStateCreateInfo.back = dsStateCreateInfo.front = stencilOpState; blendAttachmentState.colorWriteMask=0xf; dynamicState.dynamicStateCount = 3; + pipelineCreateInfo.stageCount = 2; VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_OVER)); blendAttachmentState.alphaBlendOp = blendAttachmentState.colorBlendOp = VK_BLEND_OP_SUBTRACT; @@ -390,6 +394,8 @@ void _init_function_pointers (VkvgDevice dev) { CmdDrawIndexed = GetInstProcAddress(dev->instance, vkCmdDrawIndexed); CmdDraw = GetInstProcAddress(dev->instance, vkCmdDraw); CmdSetStencilCompareMask= GetInstProcAddress(dev->instance, vkCmdSetStencilCompareMask); + CmdSetStencilReference = GetInstProcAddress(dev->instance, vkCmdSetStencilReference); + CmdSetStencilWriteMask = GetInstProcAddress(dev->instance, vkCmdSetStencilWriteMask); CmdBeginRenderPass = GetInstProcAddress(dev->instance, vkCmdBeginRenderPass); CmdEndRenderPass = GetInstProcAddress(dev->instance, vkCmdEndRenderPass); CmdSetViewport = GetInstProcAddress(dev->instance, vkCmdSetViewport); diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h index c888fed..f8af1ec 100644 --- a/src/vkvg_device_internal.h +++ b/src/vkvg_device_internal.h @@ -39,6 +39,8 @@ PFN_vkCmdDrawIndexed CmdDrawIndexed; PFN_vkCmdDraw CmdDraw; PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask; +PFN_vkCmdSetStencilReference CmdSetStencilReference; +PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask; PFN_vkCmdBeginRenderPass CmdBeginRenderPass; PFN_vkCmdEndRenderPass CmdEndRenderPass; PFN_vkCmdSetViewport CmdSetViewport; diff --git a/tests/clip.c b/tests/clip.c index e3a2aec..e2763e1 100644 --- a/tests/clip.c +++ b/tests/clip.c @@ -26,16 +26,29 @@ void test_clip(){ void test_clip2(){ vkvg_surface_clear(surf); VkvgContext ctx = vkvg_create(surf); - + vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO); vkvg_rectangle(ctx, 50,50,200,200); + vkvg_rectangle(ctx, 100,100,250,250); + vkvg_clip(ctx); + //vkvg_rectangle(ctx, 150,150,200,200); + //vkvg_clip(ctx); - vkvg_rectangle(ctx, 50,50,200,200); + // /*vkvg_clip_preserve(ctx); vkvg_set_operator(ctx, VKVG_OPERATOR_CLEAR); vkvg_fill_preserve(ctx);*/ - vkvg_clip(ctx); + //vkvg_clip(ctx); //vkvg_set_operator(ctx, VKVG_OPERATOR_OVER); + /*vkvg_rectangle(ctx, 200,200,220,220); + vkvg_set_source_rgb(ctx,1,0,0); + vkvg_paint(ctx);*/ + + vkvg_set_source_rgb(ctx,0,1,0); + vkvg_paint(ctx); + + vkvg_rectangle(ctx, 60,60,480,480); + vkvg_clip(ctx); vkvg_set_source_rgb(ctx,1,0,0); vkvg_paint(ctx); @@ -43,7 +56,7 @@ void test_clip2(){ } int main(int argc, char *argv[]) { - perform_test (test_clip, 1024, 768); + perform_test (test_clip2, 1024, 768); return 0; } diff --git a/tests/common/vkengine.c b/tests/common/vkengine.c index 8ea68e0..2be2a72 100644 --- a/tests/common/vkengine.c +++ b/tests/common/vkengine.c @@ -185,7 +185,6 @@ vk_engine_t* vkengine_create (VkPhysicalDeviceType preferedGPU, VkPresentModeKHR #if DEBUG dbgReport = vkh_device_create_debug_report (e->dev, VK_DEBUG_REPORT_ERROR_BIT_EXT| - VK_DEBUG_REPORT_INFORMATION_BIT_EXT| VK_DEBUG_REPORT_WARNING_BIT_EXT| VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT| VK_DEBUG_REPORT_DEBUG_BIT_EXT); diff --git a/tests/random_rects.c b/tests/random_rects.c index 6c3edd0..612905f 100644 --- a/tests/random_rects.c +++ b/tests/random_rects.c @@ -9,6 +9,7 @@ void test(){ const float w = 1024.f; VkvgContext ctx = vkvg_create(surf); + vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO); vkvg_set_line_width(ctx,1); for (int i=0; i<5000; i++) { randomize_color(ctx); diff --git a/tests/rect_fill.c b/tests/rect_fill.c index 9453a3c..dd0b15f 100644 --- a/tests/rect_fill.c +++ b/tests/rect_fill.c @@ -3,7 +3,7 @@ void test(){ vkvg_surface_clear(surf); VkvgContext ctx = vkvg_create(surf); - + vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO); vkvg_set_line_width(ctx,10); vkvg_set_source_rgba(ctx,0,0,1,0.5); vkvg_rectangle(ctx,100,100,200,200); diff --git a/vkh b/vkh index f9a1b07..b93c31b 160000 --- a/vkh +++ b/vkh @@ -1 +1 @@ -Subproject commit f9a1b07cbafbb8b96fc47a25cb27d8f8218c96c8 +Subproject commit b93c31b7ba01ccfbc12dd7e907aa6cd6a986ae81