}
}
-void _draw_stoke_cap (VkvgContext ctx, float hw, vec2 p0, vec2 p1, bool isStart) {
+void _draw_stoke_cap (VkvgContext ctx, float hw, vec2 p0, vec2 n, bool isStart) {
Vertex v = {0};
v.uv.z = -1;
VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
if (isStart){
- vec2 n = vec2_line_norm(p0, p1);
vec2 vhw = vec2_mult(n,hw);
if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
_add_tri_indices_for_rect(ctx, firstIdx);
}else{
- vec2 n = vec2_line_norm(p1, p0);
+ vec2_inv (&n);
vec2 vhw = vec2_mult(n, hw);
if (ctx->lineCap == VKVG_LINE_CAP_SQUARE)
}
}
}
+
+static bool dashOn = true;
+static uint32_t curDash = 0; //current dash index
+static float curDashOffset = 0.f; //cur dash offset between defined path point and last dash segment(on/off) start
+static vec2 normal = {0};
+
+void _draw_dashed_segment (VkvgContext ctx, vec2 pL, vec2 p, vec2 pR, float hw) {
+ Vertex v = {0};
+ v.uv.z = -1;
+
+ if (!dashOn)//we test in fact the next dash start, if dashOn = true => next segment is a void.
+ _build_vb_step (ctx, v, hw, pL, p, pR, false);
+
+ vec2 d = vec2_sub (pR, p);
+ normal = vec2_norm (d);
+ float segmentLength = vec2_length(d);
+
+ while (curDashOffset < segmentLength){
+ vec2 p0 = vec2_add (p, vec2_mult(normal, curDashOffset));
+
+ _draw_stoke_cap (ctx, hw, p0, normal, dashOn);
+ dashOn ^= true;
+
+ curDashOffset += ctx->dashes[curDash++];
+ if (curDash == ctx->dashCount)
+ curDash = 0;
+ }
+ curDashOffset -= segmentLength;
+}
void vkvg_stroke_preserve (VkvgContext ctx)
{
if (ctx->pathPtr == 0)//nothing to stroke
while (ptrPath < ctx->pathPtr){
uint32_t ptrCurve = 0;
+
+ //used for dashed lines
+ dashOn = true;
+ curDash = 0; //current dash index
+ curDashOffset = 0.f; //cur dash offset between defined path point and last dash segment(on/off) start
+ //---
+
VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
curPathPointIdx = ctx->pathes[ptrPath]&PATH_ELT_MASK;
lastPathPointIdx = ctx->pathes[ptrPath+1]&PATH_ELT_MASK;
LOG(LOG_INFO_PATH, "end = %d\n", lastPathPointIdx);
- if (_path_is_closed(ctx,ptrPath)){
+/* 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]))
iL = lastPathPointIdx;
}else{
_draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], ctx->points[curPathPointIdx+1], true);
-
iL = curPathPointIdx++;
- }
+ }*/
- if (_path_has_curves (ctx,ptrPath)) {
+ /*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;
iL = curPathPointIdx++;
}
}
- }else{
- while (curPathPointIdx < lastPathPointIdx){
- iR = curPathPointIdx+1;
- _build_vb_step (ctx, v, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], false);
- iL = curPathPointIdx++;
+ }else{*/
+ iL = lastPathPointIdx;
+ if (ctx->dashCount > 0) {
+ while (curPathPointIdx < lastPathPointIdx){
+ iR = curPathPointIdx+1;
+ _draw_dashed_segment(ctx, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], hw);
+ iL = curPathPointIdx++;
+ }
+ if (_path_is_closed(ctx,ptrPath)){
+ iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+ _draw_dashed_segment(ctx, ctx->points[iL++], ctx->points[curPathPointIdx++], ctx->points[iR], hw);
+ }
+ if (!dashOn)
+ _draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], normal, false);
+ } else {
+ while (curPathPointIdx < lastPathPointIdx){
+ iR = curPathPointIdx+1;
+ _build_vb_step (ctx, v, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], false);
+ iL = curPathPointIdx++;
+ }
}
- }
+ //}
- if (!_path_is_closed(ctx,ptrPath)){
- _draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], ctx->points[curPathPointIdx-1], false);
- //curPathPointIdx++;
- }else{
+ /*if (_path_is_closed(ctx,ptrPath)){
iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
float cross = _build_vb_step (ctx, v, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], false);
inds[5] = ii+1;
}
curPathPointIdx++;
- }
+ }else
+ _draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], ctx->points[curPathPointIdx-1], false);*/
ptrPath+=2+ptrCurve;
}
--- /dev/null
+#include "test.h"
+
+void test(){
+ vkvg_surface_clear(surf);
+
+ VkvgContext ctx = vkvg_create(surf);
+ const float dashes[] = {60.0f, 40};
+ vkvg_set_line_cap(ctx, VKVG_LINE_CAP_ROUND);
+ vkvg_set_dash(ctx, dashes, 2, 0.f);
+ vkvg_set_line_width(ctx, 20);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+
+ vkvg_move_to (ctx, 50, 50);
+ vkvg_rel_line_to (ctx, 500, 0);
+ vkvg_rel_line_to (ctx, 0, 500);
+ vkvg_rel_line_to (ctx, 200, 0);
+ vkvg_rel_line_to (ctx, 0, 200);
+ vkvg_rel_line_to (ctx, -700, 0);
+ vkvg_stroke (ctx);
+
+ vkvg_destroy(ctx);
+}
+
+int main(int argc, char *argv[]) {
+
+ perform_test (test, 1024, 768);
+
+ return 0;
+}