1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-09-11 20:47:56 +03:00

Fix SVG markers size, position and drawing

Fix #1982.
This commit is contained in:
Guillaume Ayoub 2023-10-11 21:50:02 +02:00
parent 4dfe6079c2
commit ff3b417e91
2 changed files with 156 additions and 6 deletions

View File

@ -0,0 +1,149 @@
"""Test how SVG markers are drawn."""
from ...testing_utils import assert_no_logs
@assert_no_logs
def test_markers(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
''', '''
<style>
@page { size: 11px 13px }
svg { display: block }
</style>
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="rectangle">
<rect x="-1" y="-1" width="3" height="3" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')
@assert_no_logs
def test_markers_viewbox(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
''', '''
<style>
@page { size: 11px 13px }
svg { display: block }
</style>
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="rectangle" viewBox="-1 -1 3 3">
<rect x="-10" y="-10" width="20" height="20" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')
@assert_no_logs
def test_markers_size(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
''', '''
<style>
@page { size: 11px 13px }
svg { display: block }
</style>
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="rectangle"
refX="1" refY="1" markerWidth="3" markerHeight="3">
<rect width="6" height="6" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')
@assert_no_logs
def test_markers_viewbox_size(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
___________
''', '''
<style>
@page { size: 11px 13px }
svg { display: block }
</style>
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="rectangle" viewBox="-10 -10 6 6"
refX="-8" refY="-8" markerWidth="3" markerHeight="3">
<rect x="-10" y="-10" width="6" height="6" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')

View File

@ -511,12 +511,15 @@ class SVG:
marker_node = self.markers.get(marker)
# Calculate position, scale and clipping
translate_x, translate_y = self.point(
marker_node.get('refX'), marker_node.get('refY'),
font_size)
if 'viewBox' in marker_node.attrib:
marker_width, marker_height = self.point(
marker_node.get('markerWidth', 3),
marker_node.get('markerHeight', 3),
font_size)
scale_x, scale_y, translate_x, translate_y = preserve_ratio(
scale_x, scale_y, _, _ = preserve_ratio(
self, marker_node, font_size, marker_width, marker_height)
clip_x, clip_y, viewbox_width, viewbox_height = (
@ -553,11 +556,10 @@ class SVG:
if is_valid_bounding_box(box):
scale_x = scale_y = min(
marker_width / box[2], marker_height / box[3])
translate_x /= scale_x
translate_y /= scale_y
else:
scale_x = scale_y = 1
translate_x, translate_y = self.point(
marker_node.get('refX'), marker_node.get('refY'),
font_size)
clip_box = None
# Scale
@ -585,10 +587,9 @@ class SVG:
overflow = marker_node.get('overflow', 'hidden')
if clip_box and overflow in ('hidden', 'scroll'):
self.stream.push_state()
self.stream.rectangle(*clip_box)
self.stream.pop_state()
self.stream.clip()
self.stream.end()
self.draw_node(child, font_size, fill_stroke)
self.stream.pop_state()