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

Fix many different bugs with SVG markers

This commit is contained in:
Guillaume Ayoub 2024-03-25 11:18:24 +01:00
parent 9b7550e128
commit 016bd81519
2 changed files with 173 additions and 34 deletions

View File

@ -7,18 +7,18 @@ from ...testing_utils import assert_no_logs
def test_markers(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____RRR____
___________
____RRR____
____RRR____
____RRR____
_____RRR___
_____RRR___
_____RRR___
___________
____RRR____
____RRR____
____RRR____
_____RRR___
_____RRR___
_____RRR___
___________
_____RRR___
_____RRR___
_____RRR___
''', '''
<style>
@page { size: 11px 13px }
@ -27,7 +27,7 @@ def test_markers(assert_pixels):
<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" />
<rect width="3" height="3" fill="red" />
</marker>
</defs>
<path
@ -79,16 +79,16 @@ def test_markers_viewbox(assert_pixels):
def test_markers_size(assert_pixels):
assert_pixels('''
___________
____RRR____
____RRR____
____BBR____
____BBR____
____RRR____
___________
____RRR____
____RRR____
____BBR____
____BBR____
____RRR____
___________
____RRR____
____RRR____
____BBR____
____BBR____
____RRR____
___________
''', '''
@ -101,6 +101,7 @@ def test_markers_size(assert_pixels):
<marker id="rectangle"
refX="1" refY="1" markerWidth="3" markerHeight="3">
<rect width="6" height="6" fill="red" />
<rect width="2" height="2" fill="blue" />
</marker>
</defs>
<path
@ -147,3 +148,152 @@ def test_markers_viewbox_size(assert_pixels):
marker-end="url(#rectangle)" />
</svg>
''')
def test_markers_overflow(assert_pixels):
assert_pixels('''
___________
____BBRR___
____BBRR___
____RRRR___
____RRRR___
____BBRR___
____BBRR___
____RRRR___
____RRRR___
____BBRR___
____BBRR___
____RRRR___
____RRRR___
''', '''
<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" overflow="visible"
refX="1" refY="1" markerWidth="3" markerHeight="3">
<rect width="4" height="4" fill="red" />
<rect width="2" height="2" fill="blue" />
</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_userspace(assert_pixels):
assert_pixels('''
___________
___________
_____R_____
___________
___________
___________
_____R_____
___________
___________
___________
_____R_____
___________
___________
''', '''
<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" markerUnits="userSpaceOnUse">
<rect width="1" height="1" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
stroke-width="10"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')
@assert_no_logs
def test_markers_stroke_width(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 width="1" height="1" fill="red" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
stroke-width="3"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')
@assert_no_logs
def test_markers_viewbox_stroke_width(assert_pixels):
assert_pixels('''
___________
____BRR____
____RRR____
____RRR____
___________
____BRR____
____RRR____
____RRR____
___________
____BRR____
____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" markerWidth="1.5" markerHeight="1.5">
<rect x="-10" y="-10" width="20" height="20" fill="red" />
<rect x="-1" y="-1" width="1" height="1" fill="blue" />
</marker>
</defs>
<path
d="M 5 2 v 4 v 4"
stroke-width="2"
marker-start="url(#rectangle)"
marker-mid="url(#rectangle)"
marker-end="url(#rectangle)" />
</svg>
''')

View File

@ -569,11 +569,11 @@ class SVG:
translate_x, translate_y = self.point(
marker_node.get('refX'), marker_node.get('refY'),
font_size)
marker_width, marker_height = self.point(
marker_node.get('markerWidth', 3),
marker_node.get('markerHeight', 3),
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, _, _ = preserve_ratio(
self, marker_node, font_size, marker_width, marker_height)
@ -603,19 +603,8 @@ class SVG:
clip_x, clip_y,
marker_width / scale_x, marker_height / scale_y)
else:
marker_width, marker_height = self.point(
marker_node.get('markerWidth', 3),
marker_node.get('markerHeight', 3),
font_size)
box = self.calculate_bounding_box(marker_node, font_size)
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
clip_box = None
scale_x = scale_y = 1
clip_box = (0, 0, marker_width, marker_height)
# Scale
if marker_node.get('markerUnits') != 'userSpaceOnUse':
@ -641,7 +630,7 @@ class SVG:
self.stream.transform(e=-translate_x, f=-translate_y)
overflow = marker_node.get('overflow', 'hidden')
if clip_box and overflow in ('hidden', 'scroll'):
if overflow in ('hidden', 'scroll'):
self.stream.rectangle(*clip_box)
self.stream.clip()
self.stream.end()