From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- share/extensions/tests/test_inkex_tween.py | 215 +++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 share/extensions/tests/test_inkex_tween.py (limited to 'share/extensions/tests/test_inkex_tween.py') diff --git a/share/extensions/tests/test_inkex_tween.py b/share/extensions/tests/test_inkex_tween.py new file mode 100644 index 0000000..f1eabf1 --- /dev/null +++ b/share/extensions/tests/test_inkex_tween.py @@ -0,0 +1,215 @@ +# coding=utf-8 +# +# Copyright (C) 2020-2021 Jonathan Neuhauser, jonathan.neuhauser@outlook.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +"""Test interpolation inkex module functionality""" +from inkex.tester import TestCase + +import inkex +import inkex.tween as tween +import pytest +import numpy as np + + +class TweenTest(TestCase): + """Unit tests for the Inkscape inkex tween library""" + + black = inkex.Color("#000000") + grey50 = inkex.Color("#080808") + white = inkex.Color("#111111") + + def test_interpcoord(self): + val = tween.interpcoord(0, 1, 0.5) + assert val == pytest.approx(0.5, 1e-3) + + def test_interppoints(self): + val = tween.interppoints((0, 0), (1, 1), 0.5) + assert val == pytest.approx((0.5, 0.5), (1e-3, 1e-3)) + + def initialize_gradient(self, lg, stoparray): + for key, value in stoparray.items(): + stop = inkex.Stop() + stop.style = inkex.Style() + stop.style["stop-color"] = value + stop.offset = key + lg.add(stop) + + def initialize_linear_gradient(self, bounding_box, stoparray): + lg = inkex.LinearGradient() + self.initialize_gradient(lg, stoparray) + lg.set("x1", bounding_box.left) + lg.set("x2", bounding_box.right) + lg.set("y1", bounding_box.center.y) + lg.set("y2", bounding_box.center.y) + return lg + + def initialize_radial_gradient(self, bounding_box, stoparray): + grad = inkex.RadialGradient() + self.initialize_gradient(grad, stoparray) + grad.set("cx", bounding_box.center.x) + grad.set("cy", bounding_box.center.y) + grad.set("fx", bounding_box.center.x) + grad.set("fy", bounding_box.center.y) + grad.set("r", bounding_box.right - bounding_box.center.x) + return grad + + def test_fill_interpolator(self): + svg = inkex.SvgDocumentElement() + p1 = inkex.PathElement( + d="M 5.23564,33.586285 46.410969,-0.94834 89.873815,35.045501 Z" + ) + p2 = inkex.PathElement( + d="m 136.32372,31.390088 c 0,0 -65.213764,-4.27631 18.17433,-22.4506304 83.38809,-18.17434 64.14469,35.2795704 64.14469,35.2795704 z" + ) + p3 = inkex.Rectangle() + svg.add(p1, p2, p3) + g1 = self.initialize_linear_gradient( + p1.bounding_box(), {0: "#ff0000", 0.5: "#00ff00", 1: "#0000ff"} + ) + g2 = self.initialize_linear_gradient( + p2.bounding_box(), + {0: "#ff0000", 0.25: "#ff0000", 0.75: "#0000ff", 1: "#0000ff"}, + ) + g3 = self.initialize_radial_gradient( + p2.bounding_box(), {0: "#ff0000", 0.5: "#00ff00", 1: "#0000ff"} + ) + grad1 = tween.GradientInterpolator.append_to_doc(svg, g1) + grad2 = tween.GradientInterpolator.append_to_doc(svg, g2) + grad3 = tween.GradientInterpolator.append_to_doc(svg, g3) + expected = [ + [ + {"fill": "#640000"}, + {"fill": "#320000"}, + {"fill": [75, 0, 0]}, + ], # both only fill + [ + {"fill": "none"}, + {"fill": "#320000"}, + {"fill": [50, 0, 0], "fill-opacity": 0.5}, + ], # interpolate via fill-opacity + [{"fill": "none"}, {}, {"fill": [0, 0, 0]}], # only one fill set to None + [ + {"fill": "#00ff00"}, + {"fill": grad1}, + { + "fill/grad/stops": [ + [0, "#7f7f00"], + [0.5, "#00ff00"], + [1, "#007f7f"], + ], + "fill/grad/x1": "5.23564px", + }, + ], + [ + {"fill": "#00ff00"}, + {"fill": grad3}, + { + "fill/grad/stops": [ + [0, "#7f7f00"], + [0.5, "#00ff00"], + [1, "#007f7f"], + ], + "fill/grad/cx": "106.932px", + }, + ], + [{"fill": grad2}, {"fill": grad3}, {"fill": grad2}], + [ + {"fill": grad1}, + {"fill": grad2}, + { + "fill/grad/stops": [ + [0, "#ff0000"], + [0.25, "#bf3f00"], + [0.5, "#3f7f3f"], + [0.75, "#003fbf"], + [1, "#0000ff"], + ] + }, + ], + [ + {"fill": "none"}, + {"fill": grad1}, + { + "fill/grad/stops": [ + [0, "#ff0000"], + [0.5, "#00ff00"], + [1, "#0000ff"], + ], + "fill/grad/x1": "5.23564px", + }, + ], + ] + + for sstyle, estyle, interpstyle in expected: + p1.style = inkex.Style() + p1.style.update(sstyle) + p2.style = inkex.Style() + p2.style.update(estyle) + + interpolator = tween.StyleInterpolator(p1, p2) + p3.style = interpolator.interpolate(0.5) + for key, value in interpstyle.items(): + keys = key.split("/") + if keys[0] == "fill": + newfill = p3.style("fill") + if key == "fill": + assert newfill == value + elif keys[1] == "grad": + assert isinstance( + newfill, (inkex.LinearGradient, inkex.RadialGradient) + ) + if keys[2] == "stops": + assert len(value) == len(newfill.stops) + for idx, _ in enumerate(value): + assert ( + newfill.stops[idx].style["stop-color"] + == value[idx][1] + ) + self.assertAlmostEqual( + float(newfill.stop_offsets[idx]), + value[idx][0], + 1e-3, + ) + else: + assert newfill.get(keys[2]) == value + else: + assert p3.style(key) == value + + def test_path_interpolation(self): + p1 = inkex.Path("M 5.23564,33.586285 46.410969,-0.94834 89.873815,35.045501 Z") + p2 = inkex.Path( + "m 136.32372,31.390088 c 0,0 -65.213764,-4.27631 18.17433,-22.4506304 83.38809,-18.17434 64.14469,35.2795704 64.14469,35.2795704 z" + ) + pel1 = inkex.PathElement() + pel2 = inkex.PathElement() + pel1.path = p1 + pel2.path = p2 + result_method_1 = "M 70.7798 32.4882 C 70.7798 32.4882 58.7606 13.0827 100.455 3.99558 C 142.149 -5.09157 154.258 39.6323 154.258 39.6323 Z" + result_method_2 = "M 70.7798 32.4882 C 70.7798 32.4882 59.6785 13.1429 98.726 4.37785 C 99.2875 4.25181 100.254 4.44741 101.52 4.87808 C 126.751 3.94755 151.064 21.8659 153.864 27.4179 C 156.66 32.9612 150.143 39.5613 144.479 39.4637 C 131.98 39.2482 70.7798 32.4882 70.7798 32.4882" + calls = [ + [None, result_method_1], + [tween.FirstNodesInterpolator, result_method_1], + [tween.EqualSubsegmentsInterpolator, result_method_2], + ] + + for arg, expected in calls: + interp = tween.AttributeInterpolator.create_from_attribute( + pel1, pel2, "d", method=arg + ) + result = interp.interpolate(0.5) + print(result) + assert np.allclose(result, inkex.CubicSuperPath(inkex.Path(expected))) -- cgit v1.2.3