mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-09-11 20:47:56 +03:00
More fixes around SVG gradients
This commit is contained in:
parent
1e6424d54c
commit
c4c23fca73
@ -173,6 +173,42 @@ def test_linear_gradient_transform(assert_pixels):
|
||||
''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_linear_gradient_transform_userspace(assert_pixels):
|
||||
assert_pixels('''
|
||||
__________
|
||||
BBBBBBBBBB
|
||||
BBBBBBBBBB
|
||||
BBBBBBBBBB
|
||||
BBBBBBBBBB
|
||||
BBBBBBBBBB
|
||||
RRRRRRRRRR
|
||||
GGGGGGGGGG
|
||||
vvvvvvvvvv
|
||||
__________
|
||||
''', '''
|
||||
<style>
|
||||
@page { size: 10px 10px}
|
||||
svg { display: block }
|
||||
</style>
|
||||
<svg width="10px" height="10px" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="grad" x1="0" y1="0" x2="0" y2="8"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.5, 0, 0, 0.5, 0, 5)">
|
||||
<stop stop-color="blue" offset="25%"></stop>
|
||||
<stop stop-color="red" offset="25%"></stop>
|
||||
<stop stop-color="red" offset="50%"></stop>
|
||||
<stop stop-color="lime" offset="50%"></stop>
|
||||
<stop stop-color="lime" offset="75%"></stop>
|
||||
<stop stop-color="rgb(128,0,128)" offset="75%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="0" y="1" width="10" height="8" fill="url(#grad)" />
|
||||
</svg>
|
||||
''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_linear_gradient_repeat(assert_pixels):
|
||||
assert_pixels('''
|
||||
|
@ -110,7 +110,7 @@ def draw_stacking_context(stream, stacking_context):
|
||||
|
||||
if box.style['opacity'] < 1:
|
||||
original_stream = stream
|
||||
stream = stream.add_group(stream.page_rectangle)
|
||||
stream = stream.add_group(*stream.page_rectangle)
|
||||
|
||||
if box.transformation_matrix:
|
||||
if box.transformation_matrix.determinant:
|
||||
@ -391,7 +391,7 @@ def draw_background_image(stream, layer, image_rendering):
|
||||
matrix @= stream.ctm
|
||||
pattern = stream.add_pattern(
|
||||
0, 0, image_width, image_height, repeat_width, repeat_height, matrix)
|
||||
group = pattern.add_group([0, 0, repeat_width, repeat_height])
|
||||
group = pattern.add_group(0, 0, repeat_width, repeat_height)
|
||||
|
||||
with stacked(stream):
|
||||
layer.image.draw(group, image_width, image_height, image_rendering)
|
||||
|
@ -297,7 +297,7 @@ class Stream(pydyf.Stream):
|
||||
super().set_state(key)
|
||||
|
||||
def set_alpha_state(self, x, y, width, height):
|
||||
alpha_stream = self.add_group((x, y, width, height))
|
||||
alpha_stream = self.add_group(x, y, width, height)
|
||||
alpha_state = pydyf.Dictionary({
|
||||
'Type': '/ExtGState',
|
||||
'SMask': pydyf.Dictionary({
|
||||
@ -330,7 +330,7 @@ class Stream(pydyf.Stream):
|
||||
self._fonts[key] = Font(pango_font)
|
||||
return self._fonts[key]
|
||||
|
||||
def add_group(self, bounding_box):
|
||||
def add_group(self, x, y, width, height):
|
||||
states = pydyf.Dictionary()
|
||||
x_objects = pydyf.Dictionary()
|
||||
patterns = pydyf.Dictionary()
|
||||
@ -345,7 +345,7 @@ class Stream(pydyf.Stream):
|
||||
extra = pydyf.Dictionary({
|
||||
'Type': '/XObject',
|
||||
'Subtype': '/Form',
|
||||
'BBox': pydyf.Array(bounding_box),
|
||||
'BBox': pydyf.Array((x, y, x + width, y + height)),
|
||||
'Resources': resources,
|
||||
'Group': pydyf.Dictionary({
|
||||
'Type': '/Group',
|
||||
@ -482,7 +482,7 @@ class Stream(pydyf.Stream):
|
||||
extra = pydyf.Dictionary({
|
||||
'Type': '/Pattern',
|
||||
'PatternType': 1,
|
||||
'BBox': pydyf.Array([x, y, width, height]),
|
||||
'BBox': pydyf.Array([x, y, x + width, y + height]),
|
||||
'XStep': repeat_width,
|
||||
'YStep': repeat_height,
|
||||
'TilingType': 1,
|
||||
|
@ -395,7 +395,7 @@ class SVG:
|
||||
coords = (box[0], box[1], box[0] + box[2], box[1] + box[3])
|
||||
else:
|
||||
coords = (0, 0, self.inner_width, self.inner_height)
|
||||
self.stream = self.stream.add_group(coords)
|
||||
self.stream = self.stream.add_group(*coords)
|
||||
|
||||
# Apply transform attribute
|
||||
self.transform(node.get('transform'), font_size)
|
||||
|
@ -106,8 +106,11 @@ def draw_gradient(svg, node, gradient, font_size, opacity, stroke):
|
||||
return False
|
||||
if gradient.get('gradientUnits') == 'userSpaceOnUse':
|
||||
width, height = svg.inner_width, svg.inner_height
|
||||
matrix = Matrix()
|
||||
else:
|
||||
width, height = bounding_box[2], bounding_box[3]
|
||||
width, height = 1, 1
|
||||
e, f, a, d = bounding_box
|
||||
matrix = Matrix(a=a, d=d, e=e, f=f)
|
||||
|
||||
spread = gradient.get('spreadMethod', 'pad')
|
||||
if spread in ('repeat', 'reflect'):
|
||||
@ -131,39 +134,31 @@ def draw_gradient(svg, node, gradient, font_size, opacity, stroke):
|
||||
positions.append(positions[-1] + 1)
|
||||
colors.append(colors[-1])
|
||||
|
||||
if gradient.get('gradientUnits') == 'userSpaceOnUse':
|
||||
matrix = Matrix()
|
||||
else:
|
||||
matrix = Matrix(a=width, d=height)
|
||||
if gradient.tag == 'linearGradient':
|
||||
shading_type = 2
|
||||
x1, y1 = (
|
||||
size(gradient.get('x1', 0), font_size, 1),
|
||||
size(gradient.get('y1', 0), font_size, 1))
|
||||
size(gradient.get('x1', 0), font_size, width),
|
||||
size(gradient.get('y1', 0), font_size, height))
|
||||
x2, y2 = (
|
||||
size(gradient.get('x2', '100%'), font_size, 1),
|
||||
size(gradient.get('y2', 0), font_size, 1))
|
||||
size(gradient.get('x2', '100%'), font_size, width),
|
||||
size(gradient.get('y2', 0), font_size, height))
|
||||
positions, colors, coords = spread_linear_gradient(
|
||||
spread, positions, colors, x1, y1, x2, y2, matrix)
|
||||
else:
|
||||
assert gradient.tag == 'radialGradient'
|
||||
shading_type = 3
|
||||
cx, cy = (
|
||||
size(gradient.get('cx', '50%'), font_size, 1),
|
||||
size(gradient.get('cy', '50%'), font_size, 1))
|
||||
r = size(gradient.get('r', '50%'), font_size, 1)
|
||||
size(gradient.get('cx', '50%'), font_size, width),
|
||||
size(gradient.get('cy', '50%'), font_size, height))
|
||||
r = size(gradient.get('r', '50%'), font_size, hypot(width, height))
|
||||
fx, fy = (
|
||||
size(gradient.get('fx', cx), font_size, width),
|
||||
size(gradient.get('fy', cy), font_size, height))
|
||||
fr = size(gradient.get('fr', 0), font_size, 1)
|
||||
fr = size(gradient.get('fr', 0), font_size, hypot(width, height))
|
||||
positions, colors, coords = spread_radial_gradient(
|
||||
spread, positions, colors, fx, fy, fr, cx, cy, r, width, height,
|
||||
matrix)
|
||||
|
||||
if gradient.get('gradientUnits') != 'userSpaceOnUse':
|
||||
matrix @= Matrix(e=bounding_box[0], f=bounding_box[1])
|
||||
matrix @= svg.stream.ctm
|
||||
|
||||
alphas = [color[3] for color in colors]
|
||||
alpha_couples = [
|
||||
(alphas[i], alphas[i + 1])
|
||||
@ -183,18 +178,19 @@ def draw_gradient(svg, node, gradient, font_size, opacity, stroke):
|
||||
if 0 not in (a0, a1) and (a0, a1) != (1, 1):
|
||||
color_couples[i][2] = a0 / a1
|
||||
|
||||
x, y = 0, 0
|
||||
x1, y1 = 0, 0
|
||||
if 'gradientTransform' in gradient.attrib:
|
||||
transform_matrix = transform(
|
||||
gradient.get('gradientTransform'), font_size,
|
||||
svg.normalized_diagonal)
|
||||
x, y = transform_matrix.invert.transform_point(x, y)
|
||||
width, height = transform_matrix.invert.transform_point(width, height)
|
||||
matrix = transform_matrix @ matrix
|
||||
x1, y1 = transform_matrix.invert.transform_point(x1, y1)
|
||||
x2, y2 = transform_matrix.invert.transform_point(width, height)
|
||||
width, height = x2 - x1, y2 - y1
|
||||
|
||||
pattern = svg.stream.add_pattern(
|
||||
x, y, width, height, width, height, matrix)
|
||||
group = pattern.add_group([x, y, width, height])
|
||||
x1, y1, width, height, width, height, matrix @ svg.stream.ctm)
|
||||
group = pattern.add_group(x1, y1, width, height)
|
||||
|
||||
domain = (positions[0], positions[-1])
|
||||
extend = spread not in ('repeat', 'reflect')
|
||||
@ -209,7 +205,7 @@ def draw_gradient(svg, node, gradient, font_size, opacity, stroke):
|
||||
shading_type, 'RGB', domain, coords, extend, function)
|
||||
|
||||
if any(alpha != 1 for alpha in alphas):
|
||||
alpha_stream = group.set_alpha_state(x, y, width, height)
|
||||
alpha_stream = group.set_alpha_state(x1, y1, width, height)
|
||||
domain = (positions[0], positions[-1])
|
||||
extend = spread not in ('repeat', 'reflect')
|
||||
encode = (len(colors) - 1) * (0, 1)
|
||||
@ -447,7 +443,7 @@ def draw_pattern(svg, node, pattern, font_size, opacity, stroke):
|
||||
matrix)
|
||||
stream_pattern.set_alpha(opacity)
|
||||
|
||||
group = stream_pattern.add_group([0, 0, pattern_width, pattern_height])
|
||||
group = stream_pattern.add_group(0, 0, pattern_width, pattern_height)
|
||||
Pattern(pattern, svg).draw(
|
||||
group, pattern_width, pattern_height, svg.base_url,
|
||||
svg.url_fetcher, svg.context)
|
||||
|
Loading…
Reference in New Issue
Block a user