From 2e93a75bb7fb4ec14928d3abc87c87ecb7edad7c Mon Sep 17 00:00:00 2001 From: Joris Bontje Date: Wed, 21 Apr 2021 15:26:09 +0200 Subject: [PATCH] Add SVG scale transform and non-zero / negative viewbox offset --- examples/data/scale.svg | 16 ++++++++++++++++ examples/scale.nim | 12 ++++++++++++ src/pixie/fileformats/svg.nim | 23 ++++++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 examples/data/scale.svg create mode 100644 examples/scale.nim diff --git a/examples/data/scale.svg b/examples/data/scale.svg new file mode 100644 index 0000000..16dae0e --- /dev/null +++ b/examples/data/scale.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/examples/scale.nim b/examples/scale.nim new file mode 100644 index 0000000..2003f11 --- /dev/null +++ b/examples/scale.nim @@ -0,0 +1,12 @@ +import pixie + +let image = newImage(100, 100) +image.fill(rgba(255, 255, 255, 255)) + +let flower = readImage("examples/data/scale.svg") + +image.draw( + flower +) + +image.writeFile("examples/scale.png") diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index 4465ac9..d3f1769 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -192,6 +192,21 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx = let center = vec2(cx, cy) result.transform = result.transform * translate(center) * rotate(angle) * translate(-center) + elif f.startsWith("scale("): + let + values = + if f.contains(","): + f[6 .. ^2].split(",") + else: + f[6 .. ^2].split(" ") + let + sx: float32 = parseFloat(values[0].strip()) + sy: float32 = + if values.len > 1: + parseFloat(values[1].strip()) + else: + sx + result.transform = result.transform * scale(vec2(sx, sy)) else: failInvalidTransform(transform) @@ -348,12 +363,18 @@ proc decodeSvg*(data: string, width = 0, height = 0): Image = let viewBox = root.attr("viewBox") box = viewBox.split(" ") + viewBoxMinX = parseInt(box[0]) + viewBoxMinY= parseInt(box[1]) viewBoxWidth = parseInt(box[2]) viewBoxHeight = parseInt(box[3]) var rootCtx = initCtx() rootCtx = decodeCtx(rootCtx, root) + if viewBoxMinX != 0 or viewBoxMinY != 0: + rootCtx.transform = rootCtx.transform * translate( + vec2(-viewBoxMinX.float32, -viewBoxMinY.float32)) + if width == 0 and height == 0: # Default to the view box size result = newImage(viewBoxWidth, viewBoxHeight) else: @@ -362,7 +383,7 @@ proc decodeSvg*(data: string, width = 0, height = 0): Image = let scaleX = width.float32 / viewBoxWidth.float32 scaleY = height.float32 / viewBoxHeight.float32 - rootCtx.transform = scale(vec2(scaleX, scaleY)) + rootCtx.transform = rootCtx.transform * scale(vec2(scaleX, scaleY)) var ctxStack = @[rootCtx] for node in root: