svg miterlimit

This commit is contained in:
Ryan Oldenburg 2021-05-23 21:17:30 -05:00
parent 8ca46d86e3
commit dfc062e0f2
4 changed files with 75 additions and 6 deletions

View file

@ -13,6 +13,7 @@ type Ctx = object
strokeWidth: float32
strokeLineCap: LineCap
strokeLineJoin: LineJoin
strokeMiterLimit: float32
transform: Mat3
shouldStroke: bool
@ -29,6 +30,7 @@ proc initCtx(): Ctx =
result.stroke = parseHtmlColor("black").rgbx
result.strokeWidth = 1
result.transform = mat3()
result.strokeMiterLimit = defaultMiterLimit
proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
result = inherited
@ -40,6 +42,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
strokeWidth = node.attr("stroke-width")
strokeLineCap = node.attr("stroke-linecap")
strokeLineJoin = node.attr("stroke-linejoin")
strokeMiterLimit = node.attr("stroke-miterlimit")
transform = node.attr("transform")
style = node.attr("style")
@ -64,6 +67,9 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
of "stroke-width":
if strokeWidth.len == 0:
strokeWidth = parts[1].strip()
of "stroke-miterlimit":
if strokeMiterLimit.len == 0:
strokeMiterLimit = parts[1].strip()
if fillRule == "":
discard # Inherit
@ -138,6 +144,11 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
PixieError, "Invalid stroke-linejoin value " & strokeLineJoin
)
if strokeMiterLimit == "":
discard
else:
result.strokeMiterLimit = parseFloat(strokeMiterLimit)
if transform == "":
discard # Inherit
else:
@ -234,7 +245,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if ctx.fill != ColorRGBX():
img.fillPath(path, ctx.fill, ctx.transform, ctx.fillRule)
if ctx.shouldStroke:
img.strokePath(path, ctx.stroke, ctx.transform, ctx.strokeWidth)
img.strokePath(
path,
ctx.stroke,
ctx.transform,
ctx.strokeWidth,
miterLimit = ctx.strokeMiterLimit
)
of "line":
let
@ -252,7 +269,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if ctx.fill != ColorRGBX():
img.fillPath(path, ctx.fill, ctx.transform)
if ctx.shouldStroke:
img.strokePath(path, ctx.stroke, ctx.transform, ctx.strokeWidth)
img.strokePath(
path,
ctx.stroke,
ctx.transform,
ctx.strokeWidth,
miterLimit = ctx.strokeMiterLimit
)
of "polyline", "polygon":
let
@ -288,7 +311,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if ctx.fill != ColorRGBX():
img.fillPath(path, ctx.fill, ctx.transform)
if ctx.shouldStroke:
img.strokePath(path, ctx.stroke, ctx.transform, ctx.strokeWidth)
img.strokePath(
path,
ctx.stroke,
ctx.transform,
ctx.strokeWidth,
miterLimit = ctx.strokeMiterLimit
)
of "rect":
let
@ -326,7 +355,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if ctx.fill != ColorRGBX():
img.fillPath(path, ctx.fill, ctx.transform)
if ctx.shouldStroke:
img.strokePath(path, ctx.stroke, ctx.transform, ctx.strokeWidth)
img.strokePath(
path,
ctx.stroke,
ctx.transform,
ctx.strokeWidth,
miterLimit = ctx.strokeMiterLimit
)
of "circle", "ellipse":
let
@ -348,7 +383,13 @@ proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
if ctx.fill != ColorRGBX():
img.fillPath(path, ctx.fill, ctx.transform)
if ctx.shouldStroke:
img.strokePath(path, ctx.stroke, ctx.transform, ctx.strokeWidth)
img.strokePath(
path,
ctx.stroke,
ctx.transform,
ctx.strokeWidth,
miterLimit = ctx.strokeMiterLimit
)
else:
raise newException(PixieError, "Unsupported SVG tag: " & node.tag & ".")

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -0,0 +1,27 @@
<svg viewBox="0 0 760 600" transform="scale(20, 20)" xmlns="http://www.w3.org/2000/svg">
<!-- Impact of the default miter limit -->
<path stroke="black" fill="none" stroke-linejoin="miter" id="p1" d="M1,9 l7 ,-3 l7 ,3
m2,0 l3.5 ,-3 l3.5 ,3
m2,0 l2 ,-3 l2 ,3
m2,0 l0.75,-3 l0.75,3
m2,0 l0.5 ,-3 l0.5 ,3"></path>
<!-- Impact of the smallest miter limit (1) -->
<path stroke="black" fill="none" stroke-linejoin="miter" stroke-miterlimit="1" id="p2" d="M1,19 l7 ,-3 l7 ,3
m2, 0 l3.5 ,-3 l3.5 ,3
m2, 0 l2 ,-3 l2 ,3
m2, 0 l0.75,-3 l0.75,3
m2, 0 l0.5 ,-3 l0.5 ,3"></path>
<!-- Impact of a large miter limit (8) -->
<path stroke="black" fill="none" stroke-linejoin="miter" stroke-miterlimit="8" id="p3" d="M1,29 l7 ,-3 l7 ,3
m2, 0 l3.5 ,-3 l3.5 ,3
m2, 0 l2 ,-3 l2 ,3
m2, 0 l0.75,-3 l0.75,3
m2, 0 l0.5 ,-3 l0.5 ,3"></path>
<!-- the following pink lines highlight the position of the path for each stroke -->
<path stroke="pink" fill="none" stroke-width="0.05" d="M1, 9 l7,-3 l7,3 m2,0 l3.5,-3 l3.5,3 m2,0 l2,-3 l2,3 m2,0 l0.75,-3 l0.75,3 m2,0 l0.5,-3 l0.5,3
M1,19 l7,-3 l7,3 m2,0 l3.5,-3 l3.5,3 m2,0 l2,-3 l2,3 m2,0 l0.75,-3 l0.75,3 m2,0 l0.5,-3 l0.5,3
M1,29 l7,-3 l7,3 m2,0 l3.5,-3 l3.5,3 m2,0 l2,-3 l2,3 m2,0 l0.75,-3 l0.75,3 m2,0 l0.5,-3 l0.5,3"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -11,7 +11,8 @@ const files = [
"triangle01",
"quad01",
"Ghostscript_Tiger",
"scale"
"scale",
"miterlimit"
]
for file in files: