From d0ad5c1f286ec182ad82b697059673df80dfafae Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sat, 29 Apr 2023 16:30:41 +0200 Subject: [PATCH] Override use tag children instead of drawing their references This change fixes cases when use tags are not supposed to be really drawn, for example when used to clip paths. --- weasyprint/svg/__init__.py | 13 ++++++++----- weasyprint/svg/defs.py | 4 +--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/weasyprint/svg/__init__.py b/weasyprint/svg/__init__.py index a6108fa46..ae9ed6250 100644 --- a/weasyprint/svg/__init__.py +++ b/weasyprint/svg/__init__.py @@ -284,6 +284,13 @@ def pop_rotation(self, original_rotate, rotate): str(rotate.pop(0) if rotate else original_rotate[-1]) for i in range(len(self.text))) + def override_iter(self, iterator): + """Override node’s children iterator.""" + # As special methods are bound to classes and not instances, we have to + # create and assign a new type. + self.__class__ = type( + 'Node', (Node,), {'__iter__': lambda _: iterator}) + class SVG: """An SVG document.""" @@ -737,11 +744,7 @@ def inherit_element(self, element, defs): if key not in element.attrib: element.attrib[key] = value if next(iter(element), None) is None: - # Override element’s __iter__ with parent’s __iter__. As special - # methods are bound to classes and not instances, we have to create - # and assign a new type. - element.__class__ = type( - 'Node', (Node,), {'__iter__': lambda self: parent.__iter__()}) + element.override_iter(parent.__iter__()) def calculate_bounding_box(self, node, font_size, stroke=True): """Calculate the bounding box of a node.""" diff --git a/weasyprint/svg/defs.py b/weasyprint/svg/defs.py index dc6f76275..10ee0d54e 100644 --- a/weasyprint/svg/defs.py +++ b/weasyprint/svg/defs.py @@ -60,10 +60,8 @@ def use(svg, node, font_size): if key not in tree.attrib: tree.attrib[key] = value - svg.stream.push_state() + node.override_iter(iter((tree,))) svg.stream.transform(e=x, f=y) - svg.draw_node(tree, font_size) - svg.stream.pop_state() def draw_gradient_or_pattern(svg, node, name, font_size, opacity, stroke):