gliffy / canvas2svg

Translates HTML5 Canvas draw commands to SVG
MIT License
683 stars 155 forks source link

Calling ctx.save does not always entail writing to a new group element #64

Open barberousse opened 6 years ago

barberousse commented 6 years ago

I am attempting to snapshot canvas renders as SVGs from points in time of playback of a CreateJS timeline. So I want set the timeline to a certain frame and snapshot the EaselJS submodule output which writes to the canvas object.

I have no control over the composition of the graphics I am working with in these timelines, so re-drawing the graphics to workaround this issue is not an option.

The issue is that the EaselJS module frequently applies the following sequence of commands while drawing path, at the point at which it wants to stroke the path and move on to the next graphic entity:

ctx.strokeStyle = this.style;
// this.ignoreScale is by default falsy
if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); }
ctx.stroke();
if (this.ignoreScale) { ctx.restore(); }

The intent here is to re-use the current canvas state except for the transform. The problem is that the library interprets any call to ctx.save as not only stack push for the style state, but also calls for a new group element to be attached the SVG tree, I imagine, since SVG is declarative and has no state, to persist the state changes being called between ctx.save and ctx.restore, but this does not capture the range of intents in using ctx.save and ctx.restore.

So when its stroking a path, which is usually the last thing it calls for that path, this library changes elements and attempts to write a path to the newly create <g> instead of the path its supposed to write to. This creates incorrect output. I've attached a screenshot where the SVG output is to the left and the Canvas render to the right. screen shot 2017-12-05 at 5 44 24 pm

The outlining paths used to "ink" the graphic as in the Canvas render all end up missing, and once can see multiple paths without a populated d attribute followed by an empty g peer.