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 0000000..0ff6c06 Binary files /dev/null and b/tests/images/svg/quad01.png differ 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" ]