From 68f86509610754788bc65828a26e5067ccf12960 Mon Sep 17 00:00:00 2001 From: Jonathan Neuhauser Date: Mon, 28 Jun 2021 22:39:05 +0200 Subject: [PATCH] ink2canvas: fix closed paths and opacity --- ink2canvas_lib/canvas.py | 5 +- ink2canvas_lib/svg.py | 14 ++++-- tests/data/refs/ink2canvas.out | 3 ++ tests/data/refs/ink2canvas__--id__path31.out | 49 +++++++++++++++++++ .../data/refs/ink2canvas__--id__rect3898.out | 3 ++ tests/data/svg/multiple_closed_subpaths.svg | 49 +++++++++++++++++++ tests/test_ink2canvas_svg.py | 7 ++- 7 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 tests/data/refs/ink2canvas__--id__path31.out create mode 100644 tests/data/svg/multiple_closed_subpaths.svg diff --git a/ink2canvas_lib/canvas.py b/ink2canvas_lib/canvas.py index 091bde38..ef293e37 100644 --- a/ink2canvas_lib/canvas.py +++ b/ink2canvas_lib/canvas.py @@ -129,6 +129,9 @@ class Canvas(object): def lineTo(self, x, y): self.write("ctx.lineTo(%f, %f);" % (x, y)) + def closePath(self): + self.write("ctx.closePath();") + def quadraticCurveTo(self, cpx, cpy, x, y): data = (cpx, cpy, x, y) self.write("ctx.quadraticCurveTo(%f, %f, %f, %f);" % data) @@ -178,7 +181,7 @@ class Canvas(object): def restore(self): self.write("ctx.restore();") - def closePath(self): + def finishPath(self): if self.style("fill") is not None: self.write("ctx.fill();") if self.style("stroke") is not None: diff --git a/ink2canvas_lib/svg.py b/ink2canvas_lib/svg.py index 4789eb9c..1aab455a 100644 --- a/ink2canvas_lib/svg.py +++ b/ink2canvas_lib/svg.py @@ -88,6 +88,8 @@ class AbstractShape(Element): if hasattr(self.ctx, method) and style[key] != "none": getattr(self.ctx, method)(style[key]) # saves style to compare in next iteration + if hasattr(self.ctx, "style_cache") and self.ctx.style_cache("opacity") != style("opacity"): + self.ctx.setOpacity(style("opacity")) # opacity is kept in memory, need to reset self.ctx.style_cache = style def has_transform(self): @@ -126,7 +128,7 @@ class AbstractShape(Element): self.set_style(style) # unpacks "data" in parameters to given method getattr(self.ctx, self.command)(*data) - self.ctx.closePath() + self.ctx.finishPath() def end(self): if self.has_transform() or self.has_clip(): @@ -189,7 +191,7 @@ class Ellipse(AbstractShape): self.ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry) self.ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy) self.ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry) - self.ctx.closePath() + self.ctx.finishPath() class Path(AbstractShape): @@ -207,6 +209,9 @@ class Path(AbstractShape): self.ctx.bezierCurveTo(x1, y1, x2, y2, x, y) self.currentPosition = x, y + def pathClose(self, data): + self.ctx.closePath() + def draw(self): """Gets the node type and calls the given method""" style = self.get_style() @@ -219,13 +224,14 @@ class Path(AbstractShape): # Draws path commands path_command = {"M": self.pathMoveTo, "L": self.pathLineTo, - "C": self.pathCurveTo} + "C": self.pathCurveTo, + "Z": self.pathClose} # Make sure we only have Lines and curves (no arcs etc) for comm, data in self.node.path.to_superpath().to_path().to_arrays(): if comm in path_command: path_command[comm](data) - self.ctx.closePath() + self.ctx.finishPath() class Line(Path): diff --git a/tests/data/refs/ink2canvas.out b/tests/data/refs/ink2canvas.out index 9080d0f0..c6bc3c09 100644 --- a/tests/data/refs/ink2canvas.out +++ b/tests/data/refs/ink2canvas.out @@ -24,6 +24,7 @@ // #c1 ctx.beginPath(); ctx.fillStyle = 'rgb(0, 0, 128)'; + ctx.globalAlpha = 1.0; ctx.arc(150.000000, 450.000000, 50.000000, 0.000000, 6.28318531, 1); ctx.fill(); @@ -49,6 +50,7 @@ ctx.bezierCurveTo(599.052409, 429.312488, 626.453123, 409.709909, 667.736130, 402.673890); ctx.bezierCurveTo(709.019129, 395.637872, 754.660551, 402.791598, 780.522930, 420.351820); ctx.lineTo(700.000000, 450.000000); + ctx.closePath(); ctx.fill(); ctx.stroke(); @@ -87,6 +89,7 @@ ctx.lineTo(200.000000, 815.037620); ctx.lineTo(245.458240, 807.599150); ctx.lineTo(223.711430, 848.205300); + ctx.closePath(); ctx.fill(); ctx.stroke(); diff --git a/tests/data/refs/ink2canvas__--id__path31.out b/tests/data/refs/ink2canvas__--id__path31.out new file mode 100644 index 00000000..fc306262 --- /dev/null +++ b/tests/data/refs/ink2canvas__--id__path31.out @@ -0,0 +1,49 @@ + + + + + Inkscape Output + + + + + + diff --git a/tests/data/refs/ink2canvas__--id__rect3898.out b/tests/data/refs/ink2canvas__--id__rect3898.out index 4d1bfde5..c0c8c136 100644 --- a/tests/data/refs/ink2canvas__--id__rect3898.out +++ b/tests/data/refs/ink2canvas__--id__rect3898.out @@ -28,6 +28,7 @@ ctx.lineTo(302.222790, 206.087400); ctx.lineTo(455.017240, 193.400620); ctx.lineTo(372.146640, 322.395040); + ctx.closePath(); ctx.fill(); ctx.restore(); @@ -48,6 +49,7 @@ ctx.bezierCurveTo(274.491580, 620.933630, 202.857150, 561.451460, 202.857150, 488.076480); ctx.bezierCurveTo(202.857150, 414.701510, 274.491580, 355.219340, 362.857140, 355.219340); ctx.bezierCurveTo(451.222700, 355.219340, 522.857140, 414.701510, 522.857140, 488.076480); + ctx.closePath(); ctx.fill(); // #text3918 @@ -114,6 +116,7 @@ ctx.bezierCurveTo(212.155040, 353.325700, 204.745450, 357.539260, 207.184090, 356.081270); ctx.bezierCurveTo(217.673090, 349.810220, 228.289930, 343.755500, 238.842850, 337.592610); ctx.lineTo(199.544030, 352.969140); + ctx.closePath(); ctx.fill(); diff --git a/tests/data/svg/multiple_closed_subpaths.svg b/tests/data/svg/multiple_closed_subpaths.svg new file mode 100644 index 00000000..1548b50c --- /dev/null +++ b/tests/data/svg/multiple_closed_subpaths.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/tests/test_ink2canvas_svg.py b/tests/test_ink2canvas_svg.py index 11462d8d..d3e3270c 100644 --- a/tests/test_ink2canvas_svg.py +++ b/tests/test_ink2canvas_svg.py @@ -16,4 +16,9 @@ class Ink2CanvasTestTextPath(ComparisonMixin, TestCase): # This file contains a textPath compare_filters = [CompareOrderIndependentLines()] # We don't need a selection for this case, but we need unique filenames for the tester - comparisons = [("--id=rect3898",)] \ No newline at end of file + comparisons = [("--id=rect3898",)] + +class Ink2CanvasTestClosedPath(ComparisonMixin, TestCase): + effect_class = Html5Canvas + compare_file = 'svg/multiple_closed_subpaths.svg' + comparisons = [("--id=path31",)] \ No newline at end of file -- GitLab