Add SVG scale transform and non-zero / negative viewbox offset
This commit is contained in:
parent
101619a9e6
commit
2e93a75bb7
16
examples/data/scale.svg
Normal file
16
examples/data/scale.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<svg viewBox="-50 -50 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- uniform scale -->
|
||||
<circle cx="0" cy="0" r="10" fill="red"
|
||||
transform="scale(4)" />
|
||||
|
||||
<!-- vertical scale -->
|
||||
<circle cx="0" cy="0" r="10" fill="yellow"
|
||||
transform="scale(1,4)" />
|
||||
|
||||
<!-- horizontal scale -->
|
||||
<circle cx="0" cy="0" r="10" fill="pink"
|
||||
transform="scale(4,1)" />
|
||||
|
||||
<!-- No scale -->
|
||||
<circle cx="0" cy="0" r="10" fill="black" />
|
||||
</svg>
|
After Width: | Height: | Size: 459 B |
12
examples/scale.nim
Normal file
12
examples/scale.nim
Normal file
|
@ -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")
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue