From 7cf59c85fe254a5fd7afd4f02b9ce542591bba93 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sat, 19 Dec 2020 20:47:05 -0600 Subject: [PATCH] svg circle --- src/pixie/fileformats/svg.nim | 34 ++++++++++++++++++++++++++++++++-- src/pixie/paths.nim | 6 ++++-- tests/images/svg/quad01.png | Bin 0 -> 33943 bytes tests/images/svg/quad01.svg | 28 ++++++++++++++++++++++++++++ tests/test_svg.nim | 1 + 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/images/svg/quad01.png create mode 100644 tests/images/svg/quad01.svg diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index 61518b2..90560f5 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -78,12 +78,14 @@ proc draw( discard of "desc": discard + of "g": let ctx = decodeCtx(ctxStack[^1], node) ctxStack.add(ctx) for child in node: img.draw(child, ctxStack) discard ctxStack.pop() + of "path": let d = node.attr("d") @@ -91,11 +93,12 @@ proc draw( if ctx.fill != ColorRGBA(): let (bounds, fillImg) = fillPathBounds(d, ctx.fill, ctx.transform) img.draw(fillImg, bounds.xy) - if ctx.stroke != ColorRGBA(): + if ctx.stroke != ColorRGBA() and ctx.strokeWidth > 0: let (bounds, strokeImg) = strokePathBounds( d, ctx.stroke, ctx.strokeWidth, ctx.transform ) img.draw(strokeImg, bounds.xy) + of "rect": let ctx = decodeCtx(ctxStack[^1], node) @@ -111,8 +114,35 @@ proc draw( path.closePath() if ctx.fill != ColorRGBA(): img.fillPath(path, ctx.fill, ctx.transform) - if ctx.stroke != ColorRGBA(): + if ctx.stroke != ColorRGBA() and ctx.strokeWidth > 0: img.strokePath(path, ctx.stroke, ctx.strokeWidth, ctx.transform) + + of "circle": + # Reference for magic constant: + # https://dl3.pushbulletusercontent.com/a3fLVC8boTzRoxevD1OgCzRzERB9z2EZ/unknown.png + let + ctx = decodeCtx(ctxStack[^1], node) + cx = parseFloat(node.attr("cx")) + cy = parseFloat(node.attr("cy")) + r = parseFloat(node.attr("r")) + magic = (4.0 * (-1.0 + sqrt(2.0)) / 3) * r + path = newPath() + path.moveTo(cx + r, cy) + path.bezierCurveTo(cx + r, cy + magic, cx + magic, cy + r, cx, cy + r) + path.bezierCurveTo(cx - magic, cy + r, cx - r, cy + magic, cx - r, cy) + path.bezierCurveTo(cx - r, cy - magic, cx - magic, cy - r, cx, cy - r) + path.bezierCurveTo(cx + magic, cy - r, cx + r, cy - magic, cx + r, cy) + path.closePath() + let d = $path + if ctx.fill != ColorRGBA(): + let (bounds, fillImg) = fillPathBounds(d, ctx.fill, ctx.transform) + img.draw(fillImg, bounds.xy) + if ctx.stroke != ColorRGBA() and ctx.strokeWidth > 0: + let (bounds, strokeImg) = strokePathBounds( + d, ctx.stroke, ctx.strokeWidth, ctx.transform + ) + img.draw(strokeImg, bounds.xy) + else: raise newException(PixieError, "Unsupported SVG tag: " & node.tag & ".") diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 7fd35d3..eebebca 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -833,9 +833,11 @@ proc lineTo*(path: Path, x, y: float32) = path.commands.add PathCommand(kind: Line, numbers: @[x, y]) path.at = vec2(x, y) -proc bezierCurveTo*(path: Path) = +proc bezierCurveTo*(path: Path, x1, y1, x2, y2, x3, y3: float32) = ## Adds a cubic Bézier curve to the path. It requires three points. The first two points are control points and the third one is the end point. The starting point is the last point in the current path, which can be changed using moveTo() before creating the Bézier curve. - raise newException(ValueError, "not implemented") + path.commands.add(PathCommand(kind: Cubic, numbers: @[ + x1, y1, x2, y2, x3, y3 + ])) proc quadraticCurveTo*(path: Path) = ## Adds a quadratic Bézier curve to the current path. diff --git a/tests/images/svg/quad01.png b/tests/images/svg/quad01.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff6c06d097e516a788109cb4adbb4ed2df41703 GIT binary patch literal 33943 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

g=0t1}_EO-p~&7 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 US*dX!f-D?mukoI|-FBh>2k%yizW@LL literal 0 HcmV?d00001 diff --git a/tests/images/svg/quad01.svg b/tests/images/svg/quad01.svg new file mode 100644 index 0000000..0f30020 --- /dev/null +++ b/tests/images/svg/quad01.svg @@ -0,0 +1,28 @@ + + + Example quad01 - quadratic Bézier commands in path data + Picture showing a "Q" a "T" command, + along with annotations showing the control points + and end points + + + + + + + + + + + + + + + + + diff --git a/tests/test_svg.nim b/tests/test_svg.nim index 1abc0bd..435fbae 100644 --- a/tests/test_svg.nim +++ b/tests/test_svg.nim @@ -2,6 +2,7 @@ import pixie/fileformats/svg, pixie, strformat const files = [ "triangle01", + "quad01", "Ghostscript_Tiger" ]