From 00dd3faa95c824db548186ed15936452a52d7fc0 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sun, 23 May 2021 22:29:59 -0500 Subject: [PATCH] svg stroke-dasharray --- src/pixie/fileformats/svg.nim | 24 ++++++++++++++++++------ src/pixie/paths.nim | 7 ++++--- tests/images/paths/dashes.png | Bin 824 -> 837 bytes tests/images/svg/dashes.png | Bin 0 -> 2958 bytes tests/images/svg/dashes.svg | 20 ++++++++++++++++++++ tests/test_svg.nim | 3 ++- 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 tests/images/svg/dashes.png create mode 100644 tests/images/svg/dashes.svg diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index beed00d..35e0b00 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -14,6 +14,7 @@ type Ctx = object strokeLineCap: LineCap strokeLineJoin: LineJoin strokeMiterLimit: float32 + strokeDashArray: seq[float32] transform: Mat3 shouldStroke: bool @@ -43,6 +44,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx = strokeLineCap = node.attr("stroke-linecap") strokeLineJoin = node.attr("stroke-linejoin") strokeMiterLimit = node.attr("stroke-miterlimit") + strokeDashArray = node.attr("stroke-dasharray") transform = node.attr("transform") style = node.attr("style") @@ -70,6 +72,9 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx = of "stroke-miterlimit": if strokeMiterLimit.len == 0: strokeMiterLimit = parts[1].strip() + of "stroke-dasharray": + if strokeDashArray.len == 0: + strokeDashArray = parts[1].strip() if fillRule == "": discard # Inherit @@ -149,6 +154,13 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx = else: result.strokeMiterLimit = parseFloat(strokeMiterLimit) + if strokeDashArray == "": + discard + else: + var values = strokeDashArray.replace(',', ' ').split(' ') + for value in values: + result.strokeDashArray.add(parseFloat(value)) + if transform == "": discard # Inherit else: @@ -230,7 +242,8 @@ proc stroke(img: Image, ctx: Ctx, path: Path) {.inline.} = ctx.stroke, ctx.transform, ctx.strokeWidth, - miterLimit = ctx.strokeMiterLimit + miterLimit = ctx.strokeMiterLimit, + dashes = ctx.strokeDashArray ) proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) = @@ -270,10 +283,7 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) = var path: Path path.moveTo(x1, y1) path.lineTo(x2, y2) - path.closePath() - if ctx.fill != ColorRGBX(): - img.fill(ctx, path) if ctx.shouldStroke: img.stroke(ctx, path) @@ -305,11 +315,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) = path.lineTo(vecs[i]) # The difference between polyline and polygon is whether we close the path + # and fill or not if node.tag == "polygon": path.closePath() - if ctx.fill != ColorRGBX(): - img.fill(ctx, path) + if ctx.fill != ColorRGBX(): + img.fill(ctx, path) + if ctx.shouldStroke: img.stroke(ctx, path) diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 2555420..f027f84 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1424,15 +1424,16 @@ proc strokeShapes( shape[0] )) + var dashes = dashes + if dashes.len mod 2 != 0: + dashes.add(dashes) + for i in 1 ..< shape.len: let pos = shape[i] prevPos = shape[i - 1] if dashes.len > 0: - var dashes = dashes - if dashes.len mod 2 != 0: - dashes.add(dashes) var distance = dist(prevPos, pos) let dir = dir(pos, prevPos) var currPos = prevPos diff --git a/tests/images/paths/dashes.png b/tests/images/paths/dashes.png index 5389bd8b8b89e0882f36c7e880f3a7dfc0d51e84..3681bb09bbc525de11f7d8b4091407d01566e1af 100644 GIT binary patch literal 837 zcmeAS@N?(olHy`uVBq!ia0vp^Hb7j#!3HGPnNH+jU|{C)ba4!+V0=5{_9|&d9+uh@ z{kP-a1#q%1T71){KcF$_uqg2&1X0N{O_+-vH52+-p8N$#br0&Kjqz% zzyH#=T<7Ci{bA`F`+;Q9{^_Fg{8oQB zfByXZ{|*JWn{Ge$vfl7Ny6C~}$EWyswrkJ2A0OGOXkJns6WRK(%=Pnc?bQZP+Vc9f z*B*+oFgSReMP9hZ=Yt^zV`E?012juE>`yFQdgRl!B5&LM(zhBVH%(&CU-`WJFwhze zjg?F8&##PVJ;>{s_i9>Io%xzW1>H@Pyng+i*&Zr!XTpv%2rsd{!kM3@a39Amor7bnXlfncEwcLI4wYm(-dCL7Mbk$yMAukuFY!!3%RJEgbf={ytu zy+*qG=MkU*MW+sH@hs<^>3?SfOz9c*Z;|HHg5|;zEpkuPJZf7DRhneC5opt#PaC)n zXF5LSYlj*>JuyB?9QJxT|bZ1*d47YI^}HrA*JjA$mx(sSsps$ ze#?%vcmBP}V1K4}>cDn;>#~F$v61`tCyTO~m;BzGEZTN^>et`aVTlFKK*^}qoh1j} zp2rsEsf>2vK4)f6zamwtQ@!N%QhDpS6PItEbG)Lx_J{hd##+V)-uqTuQvpg%y)0R2 zrM>5{-5+6VgAJP7TlAkTL6=xfJ&Co4zB25aHe>yH;jQX_|4;lI%kyl02K&4-d^U4K dVR89~P5gey8QBfibAZ`{!PC{xWt~$(699#us|f%A delta 756 zcmX@gwu5bgay`?3PZ!6K3dXlH-ma21rTu`U!SHfz093g zxA*@0@5U8-KhM7?XKk?N(DY6Jm&pG%|1vR#>e)WN&X@|Bv}#E_a@8zxLY$|ME{Z=J#t` z8{Ao!QCFWT+IHu{+d?39TlDPv^=l4IkltmxZVOlO!vhm9O4J)3JZ^QXQ60_1e{Dyn z3Z0HVt^4&)UIu&G2`{-lOXuC^1sb_%!IDXJ_0JMT+00dTu8e;5^X>+&!@68vS}(t+ z%Y`KtI8U0r3#4@IA(JrgEM9xXaNU)re_CR;F1hwWxG2Ki`a??DgO_U#U5;#BzM0Fv zetGDP`)fXJOPaSj)%5oo>F%FZZ1?S6A4{5dFY8;R`LtlUTaA^LPrA>j19@VfJ8Q4? z9<525Uz%+BG?BgSa@!g8yc@eV&hUS;IZx-AFwlV0n*6H`=9s0}6&{8uHJpDV{ceO` zWkl=4EsCEzrME$qcK*t(1v3&EVx3ZhKn59dTeHeK=d#Wz Gp$PzL=!K>L diff --git a/tests/images/svg/dashes.png b/tests/images/svg/dashes.png new file mode 100644 index 0000000000000000000000000000000000000000..3e1f667b308c1e0389367a6a875e0a88085520f4 GIT binary patch literal 2958 zcmeHJYfO_@7(TU9HcMrR7cMGnEOBN`%f$^rXkp5jLB%WsO9Wd5WQf89R@QQ9i!r*1 zR^|}7mc&gmDFr4s3zVwSa+B(qtt-%?P(PrSaxbN{-PeW+ZlL}!OSUZe^5)BPp1$Wf zZ=d&k?|1w524Gg$uK)mGc749{3jmf8;P>XYP;lJJV$}eE4&JrX@5^ry%AN<;-VexF zet)@cx{)Xiycc)-@Us)OPMJG`A-YRMN@SG(PphZzlp}#}Hp2q!J3>N$AMN05QK+@R zH+Kn$jA1)M1z4=m*D}fccx|Xdi6&hTV3TVF0IgOZfeufoAd&uq*b^$9I0!&N1f07{ z(Gmz*%R;`p2UOk_>-!HjX_svs$>g@m#PiB&FBDElW3`1P!*cY)!t@`FXeMcvP28b?pI`ba6!z@O2{>o|O zbVkebZQGL!R_yL1z9Zje_Zv`R6bJ9PTP@_b?y;Ojq~462g9eC4xHMEqoL8@PFM6Yi zWfIY;bFWDFN2MD4O8QGDa6yy0-%sYu6(V<7rdW?S{rBQG#gf7u?<*Q~R?P!aZBKpC zhFpamwNd8h##N`QInf?Ud)TR~U)c*U*!3N+*_#S$!#Y5}ute+3)5ZLm6CIi{s@5(w z$307+4Gr_T6fiZ*iGGyYvcusXu1DF}&0HsA!a7gM)0Ai@W~O&dbHrI=2>jR@>AWA) zZxDH_E(+FCj%69cFHaAVzl02sYSu_fF%`YtNuzepQXBNZdEG=sWn zwu_gpHQY3Oz}!6c$cef6q4z;(7Q&Q!Oj1>$RV|Mj*QeuZYgj4;Qzidx<7sumw5D5< z&MU|Basu<$OWPhpiKSflCI$X4yH4jlv5>_t@nTcU(p>;ODC%Xm@(Vr+6<$e`mc&5y zMFHA|AT8(U+*@ZyvJZ2LQYyoW`CRD*bv3%q#F)cbR|{2C2jw_!&vx0Qw*)G4t4L5T z+iUZ*V1@#(#n;o0&o8Fsk$DPAmGD3mNiMM{*pkUu6AN_>6A!>U{v}@se3_9ECFls! z9f_t!D;D8YomJ!E3q=OQ{tV|2-m)cBl6gvfb+u5tRhcRt|B9uKk!U#316+JIBRkgS zYpx3_gl&>SBTH{%wR(BexHwfOkxiAy%ySpP$Oef7GK)4RuWjYG zR-?Ct+ajGs9ko48HB-ieE?R`U{O_yBkE_ee7F5<;Pb+p~Gcv=OQ6m0yB2UO_lIVw6*TCoc z>?CRVah)a$HajOxI;3qBu^a%u#5{d0^~qmiFrdqldgB}PPvJ>uB!7vC;n!G_ZX1+J zY1CQq+H%>jHC5b6Z;>jl9&7A}`ZynJb)QaFLwoXv&ro_8Qb9e_P#%8S*ihlMMFK9F zD1vRB+(UIxNYYH58e=rStxaSb40SV867g=sf^&8RPn&+}EIsm#AaN7O1U*J3rw#1a z=-@_Js6?VD(D;g~(R~@mLWL29+7t1^0e5wEu1IGnqdVX6Lgv32sf0hAh?K%wmR}cj zZP4{1!3-3eBB6-Oph~?)Qbd- + + + + + + + + + + + + + + + diff --git a/tests/test_svg.nim b/tests/test_svg.nim index 562c3dc..ac620aa 100644 --- a/tests/test_svg.nim +++ b/tests/test_svg.nim @@ -12,7 +12,8 @@ const files = [ "quad01", "Ghostscript_Tiger", "scale", - "miterlimit" + "miterlimit", + "dashes" ] for file in files: