From 00dda6a284bd88be7ecf10d409ca3456b52f47e3 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Thu, 6 Feb 2025 15:33:51 +0100 Subject: [PATCH] Ensure that we handle text-anchor only on text content elements As asked by the SVG specification. Fix #2375. --- tests/draw/svg/test_text.py | 20 ++++++++++++++++++++ weasyprint/svg/__init__.py | 20 ++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tests/draw/svg/test_text.py b/tests/draw/svg/test_text.py index 40c328354..5ab0c7ebe 100644 --- a/tests/draw/svg/test_text.py +++ b/tests/draw/svg/test_text.py @@ -364,6 +364,26 @@ def test_text_anchor_middle_end_tspan(assert_pixels): ''') +@assert_no_logs +def test_text_tspan_anchor_non_text(assert_pixels): + # Regression test for https://github.com/Kozea/WeasyPrint/issues/2375 + assert_pixels(''' + _______BBBBBB_______ + _______BBBBBB_______ + ''', ''' + + + + ABC + + + ''') + + @assert_no_logs def test_text_rotate(assert_pixels): assert_pixels(''' diff --git a/weasyprint/svg/__init__.py b/weasyprint/svg/__init__.py index 7dfd6e9d3..4381e35ac 100644 --- a/weasyprint/svg/__init__.py +++ b/weasyprint/svg/__init__.py @@ -444,14 +444,14 @@ def draw_node(self, node, font_size, fill_stroke=True): if new_ctm.determinant: self.stream.transform(*(old_ctm @ new_ctm.invert).values) - # Handle text anchor - if (text_anchor := node.get('text-anchor')) in ('middle', 'end'): - group = self.stream.add_group(0, 0, 0, 0) # BBox set after drawing - original_streams.append(self.stream) - self.stream = group - - # Set text bounding box + # Handle text anchor and set text bounding box + text_anchor_shift = False if node.display and TAGS.get(node.tag) == text: + if (text_anchor := node.get('text-anchor')) in ('middle', 'end'): + text_anchor_shift = True + group = self.stream.add_group(0, 0, 0, 0) # BBox set after drawing + original_streams.append(self.stream) + self.stream = group node.text_bounding_box = EMPTY_BOUNDING_BOX # Save concrete size of root svg tag @@ -467,11 +467,11 @@ def draw_node(self, node, font_size, fill_stroke=True): # Draw node children if node.display and node.tag not in DEF_TYPES: for child in node: - if text_anchor in ('middle', 'end'): + if text_anchor_shift: new_stream = self.stream self.stream = original_streams[-1] self.draw_node(child, font_size, fill_stroke) - if text_anchor in ('middle', 'end'): + if text_anchor_shift: self.stream = new_stream visible_text_child = ( TAGS.get(node.tag) == text and @@ -491,7 +491,7 @@ def draw_node(self, node, font_size, fill_stroke=True): self.tree.set_svg_size(svg, concrete_width, concrete_height) # Handle text anchor - if text_anchor in ('middle', 'end'): + if text_anchor_shift: group_id = self.stream.id self.stream = original_streams.pop() self.stream.push_state()