Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def bounding_box_path(surface, node):
"""Get the bounding box of a ``path`` node."""
path_data = node.get('d', '')
# Normalize path data for correct parsing
for letter in PATH_LETTERS:
path_data = path_data.replace(letter, ' {} '.format(letter))
path_data = normalize(path_data)
bounding_box = EMPTY_BOUNDING_BOX
previous_x = 0
previous_y = 0
letter = 'M' # Move as default
while path_data:
path_data = path_data.strip()
if path_data.split(' ', 1)[0] in PATH_LETTERS:
letter, path_data = (path_data + ' ').split(' ', 1)
if letter in 'aA':
# Elliptical arc curve
rx, ry, path_data = point(None, path_data)
rotation, path_data = path_data.split(' ', 1)
rotation = radians(float(rotation))
size(self, node.get('y'), 'y'))
# Set node's drawing informations if the ``node.tag`` method exists
line_cap = node.get('stroke-linecap')
if line_cap == 'square':
self.context.set_line_cap(cairo.LINE_CAP_SQUARE)
if line_cap == 'round':
self.context.set_line_cap(cairo.LINE_CAP_ROUND)
join_cap = node.get('stroke-linejoin')
if join_cap == 'round':
self.context.set_line_join(cairo.LINE_JOIN_ROUND)
if join_cap == 'bevel':
self.context.set_line_join(cairo.LINE_JOIN_BEVEL)
dash_array = normalize(node.get('stroke-dasharray', '')).split()
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')
def path(surface, node):
"""Draw a path ``node``."""
string = node.get('d', '')
node.vertices = []
for letter in PATH_LETTERS:
string = string.replace(letter, ' {} '.format(letter))
last_letter = None
string = normalize(string)
# Keep the current point because Cairo's get_current_point is not accurate
# enough. See https://github.com/Kozea/CairoSVG/issues/111.
if surface.context.has_current_point():
current_point = surface.context.get_current_point()
else:
surface.context.move_to(0, 0)
current_point = 0, 0
while string:
string = string.strip()
if string.split(' ', 1)[0] in PATH_LETTERS:
letter, string = (string + ' ').split(' ', 1)
if last_letter in (None, 'z', 'Z') and letter not in 'mM':
node.vertices.append(current_point)
first_path_point = current_point
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(' ')]
if 'rotate' in node:
rotate = [radians(float(i)) if i else 0
for i in normalize(node['rotate']).strip().split(' ')]
last_r = rotate[-1]
letters_positions = zip_letters(x, y, dx, dy, rotate, node.text)
x_align = 0
y_align = 0
text_anchor = node.get('text-anchor')
if text_anchor == 'middle':
x_align = width / 2. + x_bearing
elif text_anchor == 'end':
x_align = width + x_bearing
# TODO: This is a hack. The rest of the baseline alignment tags of the SVG
# 1.1 spec (section 10.9.2) are not supported. We only try to align things
# that look like Western horizontal fonts.
# Finally, we add a "display-anchor" attribute for aligning the specific
def polyline(surface, node):
"""Draw a polyline ``node``."""
points = normalize(node.get('points', ''))
if points:
x, y, points = point(surface, points)
surface.context.move_to(x, y)
node.vertices = [(x, y)]
while points:
x_old, y_old = x, y
x, y, points = point(surface, points)
angle = point_angle(x_old, y_old, x, y)
node.vertices.append((pi - angle, angle))
surface.context.line_to(x, y)
node.vertices.append((x, y))
def bounding_box_polyline(surface, node):
"""Get the bounding box of a ``polyline`` or ``polygon`` node."""
bounding_box = EMPTY_BOUNDING_BOX
points = []
normalized_points = normalize(node.get('points', ''))
while normalized_points:
x, y, normalized_points = point(surface, normalized_points)
points.append((x, y))
return extend_bounding_box(bounding_box, points)