Handle bounding boxes for use tags

Fix #2332.
This commit is contained in:
Guillaume Ayoub
2024-12-29 23:53:55 +01:00
parent 6fb413811c
commit 93a14096c8
3 changed files with 42 additions and 8 deletions
+16
View File
@@ -145,3 +145,19 @@ def test_translate_opacity(assert_same_renderings):
fill="blue" opacity="50%" />
''',
)
@assert_no_logs
def test_translate_use_opacity(assert_same_renderings):
# Regression test for https://github.com/Kozea/WeasyPrint/issues/1976
assert_same_renderings(
opacity_source % '''
<defs>
<rect id="rect" x="-10" y="-10" width="5" height="5" fill="blue" />
</defs>
<use href="#rect" transform="translate(12, 12)" opacity="0.5" />
''',
opacity_source % '''
<rect x="2" y="2" width="5" height="5" fill="blue" opacity="50%" />
''',
)
+11
View File
@@ -222,6 +222,16 @@ def bounding_box_g(svg, node, font_size):
return bounding_box
def bounding_box_use(svg, node, font_size):
"""Bounding box for use node."""
from .defs import get_use_tree
if (tree := get_use_tree(svg, node, font_size)) is None:
return EMPTY_BOUNDING_BOX
else:
return bounding_box(svg, tree, font_size, True)
def _bounding_box_elliptical_arc(x1, y1, rx, ry, phi, large, sweep, x, y):
"""Bounding box of an elliptical arc in path node."""
rx, ry = abs(rx), abs(ry)
@@ -349,6 +359,7 @@ BOUNDING_BOX_METHODS = {
'polygon': bounding_box_polyline,
'path': bounding_box_path,
'g': bounding_box_g,
'use': bounding_box_use,
'marker': bounding_box_g,
'text': bounding_box_text,
'tspan': bounding_box_text,
+15 -8
View File
@@ -8,16 +8,9 @@ from .bounding_box import bounding_box, is_valid_bounding_box
from .utils import alpha_value, color, parse_url, size, transform
def use(svg, node, font_size):
"""Draw use tags."""
def get_use_tree(svg, node, font_size):
from . import SVG
x, y = svg.point(node.get('x'), node.get('y'), font_size)
for attribute in ('x', 'y', 'viewBox', 'mask'):
if attribute in node.attrib:
del node.attrib[attribute]
parsed_url = parse_url(node.get_href(svg.url))
svg_url = parse_url(svg.url)
if svg_url.scheme == 'data':
@@ -46,6 +39,20 @@ def use(svg, node, font_size):
use_svg.get_intrinsic_size(font_size)
tree = use_svg.tree
return tree
def use(svg, node, font_size):
"""Draw use tags."""
x, y = svg.point(node.get('x'), node.get('y'), font_size)
for attribute in ('x', 'y', 'viewBox', 'mask'):
if attribute in node.attrib:
del node.attrib[attribute]
if (tree := get_use_tree(svg, node, font_size)) is None:
return
if tree.tag in ('svg', 'symbol'):
# Explicitely specified
# https://www.w3.org/TR/SVG11/struct.html#UseElement