Skip to content

Commit 016bd81

Browse files
committed
Fix many different bugs with SVG markers
1 parent 9b7550e commit 016bd81

File tree

2 files changed

+173
-34
lines changed

2 files changed

+173
-34
lines changed

tests/draw/svg/test_markers.py

+166-16
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
def test_markers(assert_pixels):
88
assert_pixels('''
99
___________
10-
____RRR____
11-
____RRR____
12-
____RRR____
1310
___________
14-
____RRR____
15-
____RRR____
16-
____RRR____
11+
_____RRR___
12+
_____RRR___
13+
_____RRR___
1714
___________
18-
____RRR____
19-
____RRR____
20-
____RRR____
15+
_____RRR___
16+
_____RRR___
17+
_____RRR___
2118
___________
19+
_____RRR___
20+
_____RRR___
21+
_____RRR___
2222
''', '''
2323
<style>
2424
@page { size: 11px 13px }
@@ -27,7 +27,7 @@ def test_markers(assert_pixels):
2727
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
2828
<defs>
2929
<marker id="rectangle">
30-
<rect x="-1" y="-1" width="3" height="3" fill="red" />
30+
<rect width="3" height="3" fill="red" />
3131
</marker>
3232
</defs>
3333
<path
@@ -79,16 +79,16 @@ def test_markers_viewbox(assert_pixels):
7979
def test_markers_size(assert_pixels):
8080
assert_pixels('''
8181
___________
82-
____RRR____
83-
____RRR____
82+
____BBR____
83+
____BBR____
8484
____RRR____
8585
___________
86-
____RRR____
87-
____RRR____
86+
____BBR____
87+
____BBR____
8888
____RRR____
8989
___________
90-
____RRR____
91-
____RRR____
90+
____BBR____
91+
____BBR____
9292
____RRR____
9393
___________
9494
''', '''
@@ -101,6 +101,7 @@ def test_markers_size(assert_pixels):
101101
<marker id="rectangle"
102102
refX="1" refY="1" markerWidth="3" markerHeight="3">
103103
<rect width="6" height="6" fill="red" />
104+
<rect width="2" height="2" fill="blue" />
104105
</marker>
105106
</defs>
106107
<path
@@ -147,3 +148,152 @@ def test_markers_viewbox_size(assert_pixels):
147148
marker-end="url(#rectangle)" />
148149
</svg>
149150
''')
151+
152+
153+
def test_markers_overflow(assert_pixels):
154+
assert_pixels('''
155+
___________
156+
____BBRR___
157+
____BBRR___
158+
____RRRR___
159+
____RRRR___
160+
____BBRR___
161+
____BBRR___
162+
____RRRR___
163+
____RRRR___
164+
____BBRR___
165+
____BBRR___
166+
____RRRR___
167+
____RRRR___
168+
''', '''
169+
<style>
170+
@page { size: 11px 13px }
171+
svg { display: block }
172+
</style>
173+
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
174+
<defs>
175+
<marker id="rectangle" overflow="visible"
176+
refX="1" refY="1" markerWidth="3" markerHeight="3">
177+
<rect width="4" height="4" fill="red" />
178+
<rect width="2" height="2" fill="blue" />
179+
</marker>
180+
</defs>
181+
<path
182+
d="M 5 2 v 4 v 4"
183+
marker-start="url(#rectangle)"
184+
marker-mid="url(#rectangle)"
185+
marker-end="url(#rectangle)" />
186+
</svg>
187+
''')
188+
189+
190+
@assert_no_logs
191+
def test_markers_userspace(assert_pixels):
192+
assert_pixels('''
193+
___________
194+
___________
195+
_____R_____
196+
___________
197+
___________
198+
___________
199+
_____R_____
200+
___________
201+
___________
202+
___________
203+
_____R_____
204+
___________
205+
___________
206+
''', '''
207+
<style>
208+
@page { size: 11px 13px }
209+
svg { display: block }
210+
</style>
211+
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
212+
<defs>
213+
<marker id="rectangle" markerUnits="userSpaceOnUse">
214+
<rect width="1" height="1" fill="red" />
215+
</marker>
216+
</defs>
217+
<path
218+
d="M 5 2 v 4 v 4"
219+
stroke-width="10"
220+
marker-start="url(#rectangle)"
221+
marker-mid="url(#rectangle)"
222+
marker-end="url(#rectangle)" />
223+
</svg>
224+
''')
225+
226+
227+
@assert_no_logs
228+
def test_markers_stroke_width(assert_pixels):
229+
assert_pixels('''
230+
___________
231+
___________
232+
_____RRR___
233+
_____RRR___
234+
_____RRR___
235+
___________
236+
_____RRR___
237+
_____RRR___
238+
_____RRR___
239+
___________
240+
_____RRR___
241+
_____RRR___
242+
_____RRR___
243+
''', '''
244+
<style>
245+
@page { size: 11px 13px }
246+
svg { display: block }
247+
</style>
248+
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
249+
<defs>
250+
<marker id="rectangle">
251+
<rect width="1" height="1" fill="red" />
252+
</marker>
253+
</defs>
254+
<path
255+
d="M 5 2 v 4 v 4"
256+
stroke-width="3"
257+
marker-start="url(#rectangle)"
258+
marker-mid="url(#rectangle)"
259+
marker-end="url(#rectangle)" />
260+
</svg>
261+
''')
262+
263+
264+
@assert_no_logs
265+
def test_markers_viewbox_stroke_width(assert_pixels):
266+
assert_pixels('''
267+
___________
268+
____BRR____
269+
____RRR____
270+
____RRR____
271+
___________
272+
____BRR____
273+
____RRR____
274+
____RRR____
275+
___________
276+
____BRR____
277+
____RRR____
278+
____RRR____
279+
___________
280+
''', '''
281+
<style>
282+
@page { size: 11px 13px }
283+
svg { display: block }
284+
</style>
285+
<svg width="11px" height="13px" xmlns="http://www.w3.org/2000/svg">
286+
<defs>
287+
<marker id="rectangle" viewBox="-1 -1 3 3" markerWidth="1.5" markerHeight="1.5">
288+
<rect x="-10" y="-10" width="20" height="20" fill="red" />
289+
<rect x="-1" y="-1" width="1" height="1" fill="blue" />
290+
</marker>
291+
</defs>
292+
<path
293+
d="M 5 2 v 4 v 4"
294+
stroke-width="2"
295+
marker-start="url(#rectangle)"
296+
marker-mid="url(#rectangle)"
297+
marker-end="url(#rectangle)" />
298+
</svg>
299+
''')

weasyprint/svg/__init__.py

+7-18
Original file line numberDiff line numberDiff line change
@@ -569,11 +569,11 @@ def draw_markers(self, node, font_size, fill_stroke):
569569
translate_x, translate_y = self.point(
570570
marker_node.get('refX'), marker_node.get('refY'),
571571
font_size)
572+
marker_width, marker_height = self.point(
573+
marker_node.get('markerWidth', 3),
574+
marker_node.get('markerHeight', 3),
575+
font_size)
572576
if 'viewBox' in marker_node.attrib:
573-
marker_width, marker_height = self.point(
574-
marker_node.get('markerWidth', 3),
575-
marker_node.get('markerHeight', 3),
576-
font_size)
577577
scale_x, scale_y, _, _ = preserve_ratio(
578578
self, marker_node, font_size, marker_width, marker_height)
579579

@@ -603,19 +603,8 @@ def draw_markers(self, node, font_size, fill_stroke):
603603
clip_x, clip_y,
604604
marker_width / scale_x, marker_height / scale_y)
605605
else:
606-
marker_width, marker_height = self.point(
607-
marker_node.get('markerWidth', 3),
608-
marker_node.get('markerHeight', 3),
609-
font_size)
610-
box = self.calculate_bounding_box(marker_node, font_size)
611-
if is_valid_bounding_box(box):
612-
scale_x = scale_y = min(
613-
marker_width / box[2], marker_height / box[3])
614-
translate_x /= scale_x
615-
translate_y /= scale_y
616-
else:
617-
scale_x = scale_y = 1
618-
clip_box = None
606+
scale_x = scale_y = 1
607+
clip_box = (0, 0, marker_width, marker_height)
619608

620609
# Scale
621610
if marker_node.get('markerUnits') != 'userSpaceOnUse':
@@ -641,7 +630,7 @@ def draw_markers(self, node, font_size, fill_stroke):
641630
self.stream.transform(e=-translate_x, f=-translate_y)
642631

643632
overflow = marker_node.get('overflow', 'hidden')
644-
if clip_box and overflow in ('hidden', 'scroll'):
633+
if overflow in ('hidden', 'scroll'):
645634
self.stream.rectangle(*clip_box)
646635
self.stream.clip()
647636
self.stream.end()

0 commit comments

Comments
 (0)