From 1e39ce2c80f081575201ccb5f17a0eda552d5836 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sun, 23 May 2021 21:43:47 -0500 Subject: [PATCH] context line dashes --- src/pixie/context.nim | 16 ++++++++++++-- src/pixie/fonts.nim | 29 ++++++++++++++++++++----- src/pixie/paths.nim | 4 ++-- tests/images/context/setLineDash_1.png | Bin 0 -> 1391 bytes tests/test_context.nim | 25 +++++++++++++++++++++ 5 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 tests/images/context/setLineDash_1.png diff --git a/src/pixie/context.nim b/src/pixie/context.nim index fd81133..0c60051 100644 --- a/src/pixie/context.nim +++ b/src/pixie/context.nim @@ -17,6 +17,7 @@ type font*: Font textAlign*: HAlignMode path: Path + lineDash: seq[float32] mat: Mat3 mask: Mask layer: Image @@ -30,6 +31,7 @@ type lineJoin: LineJoin font: Font textAlign: HAlignMode + lineDash: seq[float32] mat: Mat3 mask: Mask layer: Image @@ -60,6 +62,7 @@ proc state(ctx: Context): ContextState = result.lineJoin = ctx.lineJoin result.font = ctx.font result.textAlign = ctx.textAlign + result.lineDash = ctx.lineDash result.mat = ctx.mat result.mask = if ctx.mask != nil: ctx.mask.copy() else: nil @@ -94,6 +97,7 @@ proc restore*(ctx: Context) = ctx.lineJoin = state.lineJoin ctx.font = state.font ctx.textAlign = state.textAlign + ctx.lineDash = state.lineDash ctx.mat = state.mat ctx.mask = state.mask ctx.layer = state.layer @@ -124,7 +128,8 @@ proc stroke(ctx: Context, image: Image, path: Path) {.inline.} = ctx.lineWidth, ctx.lineCap, ctx.lineJoin, - ctx.miterLimit + ctx.miterLimit, + ctx.lineDash ) proc fillText(ctx: Context, image: Image, text: string, at: Vec2) {.inline.} = @@ -162,7 +167,8 @@ proc strokeText(ctx: Context, image: Image, text: string, at: Vec2) {.inline.} = hAlign = ctx.textAlign, lineCap = ctx.lineCap, lineJoin = ctx.lineJoin, - miterLimit = ctx.miterLimit + miterLimit = ctx.miterLimit, + dashes = ctx.lineDash ) proc beginPath*(ctx: Context) {.inline.} = @@ -375,6 +381,12 @@ proc measureText*(ctx: Context, text: string): TextMetrics = let bounds = typeset(ctx.font, text).computeBounds() result.width = bounds.x +proc getLineDash*(ctx: Context): seq[float32] {.inline.} = + ctx.lineDash + +proc setLineDash*(ctx: Context, lineDash: seq[float32]) {.inline.} = + ctx.lineDash = lineDash + proc getTransform*(ctx: Context): Mat3 {.inline.} = ## Retrieves the current transform matrix being applied to the context. ctx.mat diff --git a/src/pixie/fonts.nim b/src/pixie/fonts.nim index c52d667..4159620 100644 --- a/src/pixie/fonts.nim +++ b/src/pixie/fonts.nim @@ -443,7 +443,8 @@ proc strokeText*( strokeWidth = 1.0, lineCap = lcButt, lineJoin = ljMiter, - miterLimit = defaultMiterLimit + miterLimit = defaultMiterLimit, + dashes: seq[float32] = @[] ) = ## Strokes the text arrangement. for spanIndex, (start, stop) in arrangement.spans: @@ -456,10 +457,25 @@ proc strokeText*( ) when type(target) is Image: target.strokePath( - path, font.paint, transform, strokeWidth, lineCap, lineJoin + path, + font.paint, + transform, + strokeWidth, + lineCap, + lineJoin, + miterLimit, + dashes ) else: # target is Mask - target.strokePath(path, transform, strokeWidth, lineCap, lineJoin) + target.strokePath( + path, + transform, + strokeWidth, + lineCap, + lineJoin, + miterLimit, + dashes + ) proc strokeText*( target: Image | Mask, @@ -472,7 +488,8 @@ proc strokeText*( vAlign = vaTop, lineCap = lcButt, lineJoin = ljMiter, - miterLimit = defaultMiterLimit + miterLimit = defaultMiterLimit, + dashes: seq[float32] = @[] ) {.inline.} = ## Typesets and strokes the text. Optional parameters: ## transform: translation or matrix to apply @@ -487,5 +504,7 @@ proc strokeText*( transform, strokeWidth, lineCap, - lineJoin + lineJoin, + miterLimit, + dashes ) diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index c4a613f..2555420 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1432,7 +1432,7 @@ proc strokeShapes( if dashes.len > 0: var dashes = dashes if dashes.len mod 2 != 0: - dashes.add(dashes[^1]) + dashes.add(dashes) var distance = dist(prevPos, pos) let dir = dir(pos, prevPos) var currPos = prevPos @@ -1549,7 +1549,7 @@ proc strokePath*( lineCap = lcButt, lineJoin = ljMiter, miterLimit = defaultMiterLimit, - dashes: seq[float32] = @[], + dashes: seq[float32] = @[] ) = ## Strokes a path. var strokeShapes = strokeShapes( diff --git a/tests/images/context/setLineDash_1.png b/tests/images/context/setLineDash_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e57dbf81ec5b93e47d04be71188a814030f22b62 GIT binary patch literal 1391 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*W_W$&~1=mlzmW%{*NkLn;{G-g%gN+e3i$ z0pp$4>Y&DVhjUl(Z7-a`(fIsa%BCq9bK*YL9yr#0@Lh!5W&WQ>r!#RVZfKBT;_e`l zl8wj@E!}wLfbj##if`!)m|t&QWv65Ofv19P-e1WV2X=);rah4Sz+>~@_(CJAfMWuq zA&Z!RGfwK7xyFO&JvH9p4fzTf?f}{KHSXzZ%L=|fvNq*>B?)`Ou5LXQUi?Akhjqm} znHL9M#Rq-rK3hbYC7|>c9*M;^OCGJ*`95=PdFpSu+wUdKSHIo)rTEMJ)UdR#${WJ&ue|#{HZJn7)s_FBY_HwFog0?6 z^;7w`)yDO2?kD``UtPb$`1&;C-{tFdW9^G`EjQPHzjf&=5kkKfF>@<49bii0&{1du zQ$Mmp=S<(>&+}(1aq+R3`SsdWdgbfBf1G^IuKMfZ`|0b?$Ho4?{r*x-oh|!k&bj{V z*Rn%v@9bQsydiD=-d`8rZ@!+se%=4K<(YQ-=QaOqIk%j7b$#Xcb(!C0r2TzSH>-Sk zr2Ve>&+cYk>wmYrvV7Lp#lJJ}%_Ujt{yXap3`%fsL4Ajva&t%!J;1MT|BsaeDGI?k z#lkC$=T=G`Ek{y z#eY)zLgi&6{%)AFbJ@-EswH;s@9mzS*8g(iuRYc8>t@+5bAR>u-QM3ozss#Wzx(^U z{hEEV&UgN- z`RWdghU|UXRZnGa{rz}2re=GLx-n?(q{B@zFYgc8uZzuGFyR0 zg@3zjQ-9?i(BPZ?pZ^3_m#5dJ+MoUG{`T(NulL`@_tk|r{O?9iiD-U6_1H1{$Q91Q U9s-A+0}E0HPgg&ebxsLQ0AI3+#sB~S literal 0 HcmV?d00001 diff --git a/tests/test_context.nim b/tests/test_context.nim index 744f2da..b3d3152 100644 --- a/tests/test_context.nim +++ b/tests/test_context.nim @@ -490,3 +490,28 @@ block: let metrics = ctx.measureText("Hello world") doAssert metrics.width == 61 + +block: + let + image = newImage(300, 150) + ctx = newContext(image) + + var y = 15.float32 + + proc drawDashedLine(pattern: seq[float32]) = + ctx.beginPath(); + ctx.setLineDash(pattern); + ctx.moveTo(0, y); + ctx.lineTo(300, y); + ctx.stroke(); + y += 20; + + drawDashedLine(@[]); + drawDashedLine(@[1.float32, 1]); + drawDashedLine(@[10.float32, 10]); + drawDashedLine(@[20.float32, 5]); + drawDashedLine(@[15.float32, 3, 3, 3]); + drawDashedLine(@[20.float32, 3, 3, 3, 3, 3, 3, 3]); + drawDashedLine(@[12.float32, 3, 3]); + + image.writeFile("tests/images/context/setLineDash_1.png")