creativescala / doodle

Compositional vector graphics in Scala / Scala.JS
https://creativescala.org/doodle/
Apache License 2.0
329 stars 76 forks source link

SVG Renderer misplaces ClosedPath #91

Open Pucilowski opened 4 years ago

Pucilowski commented 4 years ago

Hey man, I really like what you've done here and it's cool to see the project alive and kicking. As far as I'm aware this is the best tool for generating Svg out of Scala so I appreciate it!

I'm having an issue with some Svg output.

Given:

val rect = Image.rectangle(200, 200).strokeColor(Color.red)
val rect2 = ClosedPath(List(
  MoveTo(Cartesian(0.0, 0.0)),
  LineTo(Cartesian(200.0, 0.0)),
  LineTo(Cartesian(200.0, 200.0)),
  LineTo(Cartesian(0.0, 200.0)),
  LineTo(Cartesian(0.0, 0.0))
))

val frame = doodle.svg.effect.Frame("svg").fitToPicture(10)
rect.write[Svg]((wd / "rect-200.svg").toString, frame)(svgWriter)
rect2.write[Svg]((wd / "rect2-200.svg").toString, frame)(svgWriter)

The first rect correctly yields a Rect(10, 10, 200, 200) where Rect(x,y,w,h) on a canvas of 220 by 220. The latter path yields a path with: d: M 0,0 M 0,0 L 200,0 L 200,200 L 0,200 L 0,0 Z transform: matrix(1.0,0.0,0.0,-1.0,0.0,0.0)

In this case we get a Rect(10, 210, 200, 200). As soon as I remove the transformation the rectangle moves to be center in the viewbox but I suspect for the wrong reason (it'll be upside down). I suspect the y-mirror transformation fails because the transforms are applied around the 'origin' of the shape. In the case of a svg rect that's its centroid. In the case of a path it's the coordinates of the very first draw call.

Entire Svg output for rect2: https://gist.github.com/Pucilowski/ace2dce5f15872ebca173b345cbd6826?short_path=fde0c33

Thanks for the time you're putting into this!

noelwelsh commented 4 years ago

Thanks for the report. I'm not sure what's causing the issue off the top of my head, but I'll take a look as soon as I have time.