Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def text(surface, node, draw_as_text=False):
"""Draw a text ``node``."""
font_family = (
(node.get('font-family') or 'sans-serif').split(',')[0].strip('"\' '))
font_style = getattr(
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:
def use(surface, node):
"""Draw the content of another SVG node."""
surface.context.save()
surface.context.translate(
size(surface, node.get('x'), 'x'), size(surface, node.get('y'), 'y'))
if 'x' in node:
del node['x']
if 'y' in node:
del node['y']
if 'viewBox' in node:
del node['viewBox']
if 'mask' in node:
del node['mask']
href = parse_url(node.get_href()).geturl()
tree = Tree(
url=href, url_fetcher=node.url_fetcher, parent=node,
tree_cache=surface.tree_cache, unsafe=node.unsafe)
if not match_features(tree.xml_tree):
surface.context.restore()
return
if tree.tag in ('svg', 'symbol'):
# Explicitely specified
# http://www.w3.org/TR/SVG11/struct.html#UseElement
tree.tag = 'svg'
if 'width' in node and 'height' in node:
tree['width'], tree['height'] = node['width'], node['height']
surface.draw(tree)
def paint(value):
"""Extract from value an uri and a color.
See http://www.w3.org/TR/SVG/painting.html#SpecifyingPaint
"""
if not value:
return None, None
value = value.strip()
match = PAINT_URL.search(value)
if match:
source = parse_url(match.group(1)).fragment
color = match.group(2) or None
else:
source = None
color = value or None
return (source, color)
preserve = self.get(space) == 'preserve'
self.text = handle_white_spaces(element.etree_element.text, preserve)
if trailing_space and not preserve:
self.text = self.text.lstrip(' ')
original_rotate = rotations(self)
rotate = list(original_rotate)
if original_rotate:
pop_rotation(self, original_rotate, rotate)
if self.text:
trailing_space = self.text.endswith(' ')
for child_element in element.iter_children():
child = child_element.etree_element
if child.tag in ('{http://www.w3.org/2000/svg}tref', 'tref'):
href = child.get(
'{http://www.w3.org/1999/xlink}href', child.get('href'))
url = parse_url(href).geturl()
child_tree = Tree(
url=url, url_fetcher=self.url_fetcher, parent=self,
unsafe=self.unsafe)
child_tree.clear()
child_tree.update(self)
child_node = Node(
child_element, self.style, self.url_fetcher,
parent=child_tree, parent_children=True,
unsafe=self.unsafe)
child_node.tag = 'tspan'
# Retrieve the referenced node and get its flattened text
# and remove the node children.
child = child_tree.xml_tree
child.text = flatten(child)
child_element = cssselect2.ElementWrapper.from_xml_root(child)
else:
def draw_markers(surface, node):
"""Draw the markers attached to a path ``node``."""
if not getattr(node, 'vertices', None):
return
markers = {}
common_marker = parse_url(node.get('marker', '')).fragment
for position in ('start', 'mid', 'end'):
attribute = 'marker-{}'.format(position)
if attribute in node:
markers[position] = parse_url(node[attribute]).fragment
else:
markers[position] = common_marker
angle1, angle2 = None, None
position = 'start'
while node.vertices:
# Calculate position and angle
point = node.vertices.pop(0)
angles = node.vertices.pop(0) if node.vertices else None
if angles:
if position == 'start':
def __new__(cls, **kwargs):
tree_cache = kwargs.get('tree_cache')
if tree_cache and kwargs.get('url'):
parsed_url = parse_url(kwargs['url'])
element_id = parsed_url.fragment
parent = kwargs.get('parent')
unsafe = kwargs.get('unsafe')
if any(parsed_url[:-1]):
url = urlunparse(parsed_url[:-1] + ('',))
elif parent:
url = parent.url
else:
url = None
if url and (url, element_id) in tree_cache:
cached_tree = tree_cache[(url, element_id)]
new_tree = Node(
cached_tree.element, cached_tree.style,
cached_tree.url_fetcher, parent, unsafe=unsafe)
new_tree.xml_tree = cached_tree.xml_tree
new_tree.url = url
parent_children = kwargs.get('parent_children')
tree_cache = kwargs.get('tree_cache')
element_id = None
self.url_fetcher = kwargs.get('url_fetcher', fetch)
if bytestring is not None:
self.url = url
elif file_obj is not None:
bytestring = file_obj.read()
self.url = getattr(file_obj, 'name', None)
if self.url == '':
self.url = None
elif url is not None:
parent_url = parent.url if parent else None
parsed_url = parse_url(url, parent_url)
if parsed_url.fragment:
self.url = urlunparse(parsed_url[:-1] + ('',))
element_id = parsed_url.fragment
else:
self.url = parsed_url.geturl()
element_id = None
self.url = self.url or None
else:
raise TypeError(
'No input. Use one of bytestring, file_obj or url.')
self_is_parent = (
(parent and self.url == parent.url) or
(url and url.startswith('#') and not self.url))
if self_is_parent:
root_parent = parent
while root_parent.parent is not None:
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')
self.context.translate(x, y)
self.context.scale(width, height)
path.tag = 'g'
self.stroke_and_fill = False
self.draw(path)
self.stroke_and_fill = True
self.context.restore()
def draw_markers(surface, node):
"""Draw the markers attached to a path ``node``."""
if not getattr(node, 'vertices', None):
return
markers = {}
common_marker = parse_url(node.get('marker', '')).fragment
for position in ('start', 'mid', 'end'):
attribute = 'marker-{}'.format(position)
if attribute in node:
markers[position] = parse_url(node[attribute]).fragment
else:
markers[position] = common_marker
angle1, angle2 = None, None
position = 'start'
while node.vertices:
# Calculate position and angle
point = node.vertices.pop(0)
angles = node.vertices.pop(0) if node.vertices else None
if angles:
if position == 'start':
angle = pi - angles[0]
else:
angle = (angle2 + pi - angles[0]) / 2
angle1, angle2 = angles