Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if dash_array:
dashes = [size(self, dash) for dash in dash_array]
if sum(dashes):
offset = size(self, node.get('stroke-dashoffset'))
self.context.set_dash(dashes, offset)
miter_limit = float(node.get('stroke-miterlimit', 4))
self.context.set_miter_limit(miter_limit)
# Clip
rect_values = clip_rect(node.get('clip'))
if len(rect_values) == 4:
top = size(self, rect_values[0], 'y')
right = size(self, rect_values[1], 'x')
bottom = size(self, rect_values[2], 'y')
left = size(self, rect_values[3], 'x')
x = size(self, node.get('x'), 'x')
y = size(self, node.get('y'), 'y')
width = size(self, node.get('width'), 'x')
height = size(self, node.get('height'), 'y')
self.context.save()
self.context.translate(x, y)
self.context.rectangle(
left, top, width - left - right, height - top - bottom)
self.context.restore()
self.context.clip()
clip_path = parse_url(node.get('clip-path')).fragment
if clip_path:
path = self.paths.get(clip_path)
if path:
self.context.save()
if path.get('clipPathUnits') == 'objectBoundingBox':
self.context.set_dash(dashes, offset)
miter_limit = float(node.get('stroke-miterlimit', 4))
self.context.set_miter_limit(miter_limit)
# Clip
rect_values = clip_rect(node.get('clip'))
if len(rect_values) == 4:
top = size(self, rect_values[0], 'y')
right = size(self, rect_values[1], 'x')
bottom = size(self, rect_values[2], 'y')
left = size(self, rect_values[3], 'x')
x = size(self, node.get('x'), 'x')
y = size(self, node.get('y'), 'y')
width = size(self, node.get('width'), 'x')
height = size(self, node.get('height'), 'y')
self.context.save()
self.context.translate(x, y)
self.context.rectangle(
left, top, width - left - right, height - top - bottom)
self.context.restore()
self.context.clip()
clip_path = parse_url(node.get('clip-path')).fragment
if clip_path:
path = self.paths.get(clip_path)
if path:
self.context.save()
if path.get('clipPathUnits') == 'objectBoundingBox':
x = size(self, node.get('x'), 'x')
y = size(self, node.get('y'), 'y')
width = size(self, node.get('width'), 'x')
height = size(self, node.get('height'), 'y')
cairo, ('font_slant_{}'.format(node.get('font-style')).upper()),
cairo.FONT_SLANT_NORMAL)
font_weight = getattr(
cairo, ('font_weight_{}'.format(node.get('font-weight')).upper()),
cairo.FONT_WEIGHT_NORMAL)
surface.context.select_font_face(font_family, font_style, font_weight)
surface.context.set_font_size(surface.font_size)
ascent, descent, _, max_x_advance, max_y_advance = (
surface.context.font_extents())
text_path_href = parse_url(node.get_href() or node.parent.get_href() or '')
if text_path_href.fragment:
text_path = surface.paths.get(text_path_href.fragment)
else:
text_path = None
letter_spacing = size(surface, node.get('letter-spacing'))
x_bearing, y_bearing, width, height = (
surface.context.text_extents(node.text)[:4])
x, y, dx, dy, rotate = [], [], [], [], [0]
if 'x' in node:
x = [size(surface, i, 'x')
for i in normalize(node['x']).strip().split(' ')]
if 'y' in node:
y = [size(surface, i, 'y')
for i in normalize(node['y']).strip().split(' ')]
if 'dx' in node:
dx = [size(surface, i, 'x')
for i in normalize(node['dx']).strip().split(' ')]
if 'dy' in node:
dy = [size(surface, i, 'y')
for i in normalize(node['dy']).strip().split(' ')]
def prepare_filter(surface, node, name):
"""Apply a filter transforming the context."""
if 'id' in node and node['id'] in surface.masks:
return
if name in surface.filters:
filter_node = surface.filters[name]
for child in filter_node.children:
# Offset
if child.tag == 'feOffset':
if filter_node.get('primitiveUnits') == 'objectBoundingBox':
width = size(surface, node.get('width'), 'x')
height = size(surface, node.get('height'), 'y')
dx = size(surface, child.get('dx', 0), 1) * width
dy = size(surface, child.get('dy', 0), 1) * height
else:
dx = size(surface, child.get('dx', 0), 1)
dy = size(surface, child.get('dy', 0), 1)
surface.context.translate(dx, dy)
def draw_pattern(surface, node, name):
"""Draw a pattern image."""
pattern_node = surface.patterns[name]
pattern_node.tag = 'g'
transform(surface, pattern_node.get('patternTransform'))
if pattern_node.get('viewBox'):
if not (size(surface, pattern_node.get('width', 1), 1) and
size(surface, pattern_node.get('height', 1), 1)):
return False
else:
if not (size(surface, pattern_node.get('width', 0), 1) and
size(surface, pattern_node.get('height', 0), 1)):
return False
if pattern_node.get('patternUnits') == 'userSpaceOnUse':
x = size(surface, pattern_node.get('x'), 'x')
y = size(surface, pattern_node.get('y'), 'y')
pattern_width = size(surface, pattern_node.get('width', 0), 1)
pattern_height = size(surface, pattern_node.get('height', 0), 1)
else:
width = size(surface, node.get('width'), 'x')
height = size(surface, node.get('height'), 'y')
x = size(surface, pattern_node.get('x'), 1) * width
y = size(surface, pattern_node.get('y'), 1) * height
pattern_width = (
size(surface, pattern_node.pop('width', '1'), 1) * width)
pattern_height = (
def paint_mask(surface, node, name, opacity):
"""Paint the mask of the current surface."""
mask_node = surface.masks[name]
mask_node.tag = 'g'
mask_node['opacity'] = opacity
if mask_node.get('maskUnits') == 'userSpaceOnUse':
width_ref, height_ref = 'x', 'y'
else:
x = size(surface, node.get('x'), 'x')
y = size(surface, node.get('y'), 'y')
width = size(surface, node.get('width'), 'x')
height = size(surface, node.get('height'), 'y')
width_ref = width or surface.width
height_ref = height or surface.height
mask_node['x'] = size(surface, mask_node.get('x', '-10%'), width_ref)
mask_node['y'] = size(surface, mask_node.get('y', '-10%'), height_ref)
mask_node['height'] = size(
surface, mask_node.get('height', '120%'), height_ref)
mask_node['width'] = size(
surface, mask_node.get('width', '120%'), width_ref)
if mask_node.get('maskUnits') == 'userSpaceOnUse':
x = mask_node['x']
y = mask_node['y']
mask_node['viewBox'] = '{} {} {} {}'.format(
mask_node['x'], mask_node['y'],
mask_node['width'], mask_node['height'])
def circle(surface, node):
"""Draw a circle ``node`` on ``surface``."""
r = size(surface, node.get('r'))
if not r:
return
cx = size(surface, node.get('cx'), 'x')
cy = size(surface, node.get('cy'), 'y')
surface.context.new_sub_path()
surface.context.arc(cx, cy, r, 0, 2 * pi)
def image(surface, node):
"""Draw an image ``node``."""
base_url = node.get('{http://www.w3.org/XML/1998/namespace}base')
if not base_url and node.url:
base_url = os.path.dirname(node.url) + '/'
url = parse_url(node.get('{http://www.w3.org/1999/xlink}href'), base_url)
if "href" in node and node["href"].startswith("data:image/"): # gif, etc
image_bytes = uri2image_bytes(node["href"])
else:
image_bytes = node.fetch_url(url, 'image/*')
if len(image_bytes) < 5:
return
x, y = size(surface, node.get('x'), 'x'), size(surface, node.get('y'), 'y')
width = size(surface, node.get('width'), 'x')
height = size(surface, node.get('height'), 'y')
if image_bytes[:4] == b'\x89PNG':
png_file = BytesIO(image_bytes)
elif (image_bytes[:5] in (b'
viewbox = node_format(surface, marker_node)[2]
if viewbox:
scale_x, scale_y, translate_x, translate_y = preserve_ratio(
surface, marker_node)
clip_box = clip_marker_box(
surface, marker_node, scale_x, scale_y)
else:
# Calculate sizes
marker_width = size(surface,
marker_node.get('markerWidth', '3'), 'x')
marker_height = size(surface,
marker_node.get('markerHeight', '3'), 'y')
bounding_box = calculate_bounding_box(surface, marker_node)
# Calculate position and scale (preserve aspect ratio)
translate_x = -size(surface, marker_node.get('refX', '0'), 'x')
translate_y = -size(surface, marker_node.get('refY', '0'), 'y')
scale_x = scale_y = min(
marker_width / bounding_box[2],
marker_height / bounding_box[3])
# No clipping since viewbox is not present
clip_box = None
# Add extra path for marker
temp_path = surface.context.copy_path()
surface.context.new_path()
# Override angle (if requested)
node_angle = marker_node.get('orient', '0')
if node_angle != 'auto':
angle = radians(float(node_angle))
def prepare_filter(surface, node, name):
"""Apply a filter transforming the context."""
if 'id' in node and node['id'] in surface.masks:
return
if name in surface.filters:
filter_node = surface.filters[name]
for child in filter_node.children:
# Offset
if child.tag == 'feOffset':
if filter_node.get('primitiveUnits') == 'objectBoundingBox':
width = size(surface, node.get('width'), 'x')
height = size(surface, node.get('height'), 'y')
dx = size(surface, child.get('dx', 0), 1) * width
dy = size(surface, child.get('dy', 0), 1) * height
else:
dx = size(surface, child.get('dx', 0), 1)
dy = size(surface, child.get('dy', 0), 1)
surface.context.translate(dx, dy)