4from xml.etree
import ElementTree
6from ...nvector
import NVector
7from .svgdata
import color_table, css_atrrs
8from .handler
import SvgHandler, NameMode
9from ...utils.ellipse
import Ellipse
10from ...utils.transform
import TransformMatrix
11from ...utils.color
import Color
14 from ...utils
import font
23 def __init__(self, name, comp, value, percent):
30 if self.
value is None:
37 return (bbox.x2 - bbox.x1) * self.
value
40 return bbox.x1 + (bbox.x2 - bbox.x1) * self.
value
42 return bbox.y1 + (bbox.y2 - bbox.y1) * self.
value
44 def parse(self, attr, default_percent):
47 if attr.endswith(
"%"):
49 self.
value = float(attr[:-1])/100
52 self.
value = float(attr)
62 self.
colors.append((offset, color[:4]))
66 @param gradient_shape Should be a GradientFill or GradientStroke
67 @param shape ShapeElement to apply the gradient to
68 @param time Time to fetch properties from @p shape
71 for off, col
in self.
colors:
72 gradient_shape.colors.add_color(off, col)
75 setattr(self, value.name, value)
79 relunits = attrib.get(
"gradientUnits",
"") !=
"userSpaceOnUse"
81 c.parse(attrib.get(c.name,
None), relunits)
93 bbox = shape.bounding_box(time)
95 self.x1.to_value(bbox),
96 self.y1.to_value(bbox),
99 self.x2.to_value(bbox),
100 self.y2.to_value(bbox),
102 gradient_shape.gradient_type = objects.GradientType.Linear
104 super().
to_lottie(gradient_shape, shape, time)
117 bbox = shape.bounding_box(time)
118 cx = self.cx.to_value(bbox)
119 cy = self.cy.to_value(bbox)
120 gradient_shape.start_point.value = self.
matrix.apply(
NVector(cx, cy))
121 r = self.r.to_value(bbox)
122 gradient_shape.end_point.value = self.
matrix.apply(
NVector(cx+r, cy))
124 fx = self.fx.to_value(bbox, cx) - cx
125 fy = self.fy.to_value(bbox, cy) - cy
126 gradient_shape.highlight_angle.value = math.atan2(fy, fx) * 180 / math.pi
127 gradient_shape.highlight_length.value = math.hypot(fx, fy)
129 gradient_shape.gradient_type = objects.GradientType.Radial
131 super().
to_lottie(gradient_shape, shape, time)
134def parse_color(color, current_color=Color(0, 0, 0, 1)):
137 @see https://www.w3.org/wiki/CSS/Properties/color
140 if re.match(
r"^#[0-9a-fA-F]{6}$", color):
141 return Color(int(color[1:3], 16) / 0xff, int(color[3:5], 16) / 0xff, int(color[5:7], 16) / 0xff, 1)
143 if re.match(
r"^#[0-9a-fA-F]{3}$", color):
144 return Color(int(color[1], 16) / 0xf, int(color[2], 16) / 0xf, int(color[3], 16) / 0xf, 1)
146 if re.match(
r"^#[0-9a-fA-F]{8}$", color):
148 int(color[1:3], 16) / 0xff,
149 int(color[3:5], 16) / 0xff,
150 int(color[5:7], 16) / 0xff,
151 int(color[7:9], 16) / 0xff
154 if re.match(
r"^#[0-9a-fA-F]{4}$", color):
155 return Color(int(color[1], 16) / 0xf, int(color[2], 16) / 0xf, int(color[3], 16) / 0xf, int(color[4], 16) / 0xf)
157 match = re.match(
r"^rgba\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9.eE]+)\s*\)$", color)
159 return Color(int(match[1])/255, int(match[2])/255, int(match[3])/255, float(match[4]))
161 match = re.match(
r"^rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)$", color)
163 return Color(int(match[1])/255, int(match[2])/255, int(match[3])/255, 1)
165 match = re.match(
r"^rgb\s*\(\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*\)$", color)
167 return Color(float(match[1])/100, float(match[2])/100, float(match[3])/100, 1)
169 match = re.match(
r"^rgba\s*\(\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)\s*\)$", color)
171 return Color(float(match[1])/100, float(match[2])/100, float(match[3])/100, float(match[4]))
173 if color ==
"transparent":
174 return Color(0, 0, 0, 0)
176 match = re.match(
r"^hsl\s*\(\s*([0-9.eE]+)\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*\)$", color)
178 return Color(*(colorsys.hls_to_rgb(float(match[1])/360, float(match[3])/100, float(match[2])/100) + (1,)))
180 match = re.match(
r"^hsla\s*\(\s*([0-9.eE]+)\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)%\s*,\s*([0-9.eE]+)\s*\)$", color)
182 return Color(*(colorsys.hls_to_rgb(float(match[1])/360, float(match[3])/100, float(match[2])/100) + (float(match[4]),)))
184 if color
in {
"currentColor",
"inherit"}:
185 return current_color.clone()
187 return Color(*color_table[color])
195 self.
items[shape.name] = shape
198 return self.
items[key]
201 self.
items[key] = value
204 return key
in self.
items
223 return element.attrib.get(inkscapequal, element.attrib.get(
"id"))
228 return element.attrib.get(
"id")
232 return map(float, attrib.replace(
",",
" ").split())
240 svg = etree.getroot()
244 if "width" in svg.attrib
and "height" in svg.attrib:
245 animation.width = int(round(self.
_parse_unit(svg.attrib[
"width"])))
246 animation.height = int(round(self.
_parse_unit(svg.attrib[
"height"])))
248 _, _, animation.width, animation.height = self.
_parse_viewbox(svg.attrib[
"viewBox"])
251 for defs
in svg.findall(
".//{*}defs") + svg.findall(
".//defs"):
259 animation.add_layer(layer)
269 self.
_fix_viewbox(svg, (layer
for layer
in animation.layers
if not layer.parent_index))
274 svg = etree.getroot()
281 self.
dpi = float(svg.attrib.get(self.
qualified(
"inkscape",
"export-xdpi"), self.
dpi))
286 animation.add_layer(layer)
294 if "viewBox" in svg.attrib:
296 if vbx != 0
or vby != 0
or vbw != self.
animation.width
or vbh != self.
animation.height:
298 layer.transform.position.value = -
NVector(vbx, vby)
302 if not isinstance(value, str):
307 if value.endswith(
"px"):
309 elif value.endswith(
"vw"):
312 elif value.endswith(
"vh"):
315 elif value.endswith(
"vmin"):
318 elif value.endswith(
"vmax"):
321 elif value.endswith(
"in"):
324 elif value.endswith(
"pc"):
327 elif value.endswith(
"pt"):
330 elif value.endswith(
"cm"):
332 mult = self.
dpi / cmin
333 elif value.endswith(
"mm"):
335 mult = self.
dpi / cmin / 10
336 elif value.endswith(
"Q"):
338 mult = self.
dpi / cmin / 40
340 return float(value) * mult
342 def parse_color(self, color):
346 bb = group.bounding_box()
348 itcx = self.
qualified(
"inkscape",
"transform-center-x")
349 if itcx
in element.attrib:
350 cx = float(element.attrib[itcx])
351 cy = float(element.attrib[self.
qualified(
"inkscape",
"transform-center-y")])
352 bbx, bby = bb.center()
355 dest_trans.anchor_point.value =
NVector(cx, cy)
356 dest_trans.position.value =
NVector(cx, cy)
362 if "transform" not in element.attrib:
368 for t
in re.finditer(
r"([a-zA-Z]+)\s*\(([^\)]*)\)", element.attrib[
"transform"]):
370 params = list(map(float, t[2].strip().replace(
",",
" ").split()))
371 if name ==
"translate":
372 dest_trans.position.value +=
NVector(
374 (params[1]
if len(params) > 1
else 0),
376 elif name ==
"scale":
378 dest_trans.scale.value[0] = (dest_trans.scale.value[0] / 100 * xfac) * 100
379 yfac = params[1]
if len(params) > 1
else xfac
380 dest_trans.scale.value[1] = (dest_trans.scale.value[1] / 100 * yfac) * 100
381 elif name ==
"rotate":
388 dap = ap - dest_trans.position.value
389 dest_trans.position.value += dap
390 dest_trans.anchor_point.value += dap
391 dest_trans.rotation.value = ang
397 dest_trans.position.value -= dest_trans.anchor_point.value
398 dest_trans.anchor_point.value =
NVector(0, 0)
399 trans = matrix.extract_transform()
400 dest_trans.skew_axis.value = math.degrees(trans[
"skew_axis"])
401 dest_trans.skew.value = -math.degrees(trans[
"skew_angle"])
402 dest_trans.position.value += trans[
"translation"]
403 dest_trans.rotation.value -= math.degrees(trans[
"angle"])
404 dest_trans.scale.value *= trans[
"scale"]
407 style = parent_style.copy()
408 for att
in css_atrrs & set(element.attrib.keys()):
409 if att
in element.attrib:
410 style[att] = element.attrib[att]
411 if "style" in element.attrib:
412 style.update(**dict(map(
413 lambda x: map(
lambda y: y.strip(), x.split(
":")),
414 filter(bool, element.attrib[
"style"].split(
";"))
419 opacity = float(style.get(
"opacity", 1))
420 transform.opacity.value = opacity * 100
423 if style.get(
"display",
"inline") ==
"none" or style.get(
"visibility",
"visible") ==
"hidden":
426 def add_shapes(self, element, shapes, shape_parent, parent_style):
434 shape_parent.shapes.insert(0, group)
436 group.add_shape(shape)
445 stroke_color = style.get(
"stroke",
"none")
446 if stroke_color
not in nocolor:
447 if stroke_color.startswith(
"url"):
455 stroke.color.value = color
457 group.add_shape(stroke)
459 stroke.opacity.value = opacity * float(style.get(
"stroke-opacity", 1)) * 100
461 stroke.width.value = self.
_parse_unit(style.get(
"stroke-width", 1))
463 linecap = style.get(
"stroke-linecap")
464 if linecap ==
"round":
465 stroke.line_cap = objects.shapes.LineCap.Round
466 elif linecap ==
"butt":
467 stroke.line_cap = objects.shapes.LineCap.Butt
468 elif linecap ==
"square":
469 stroke.line_cap = objects.shapes.LineCap.Square
471 linejoin = style.get(
"stroke-linejoin")
472 if linejoin ==
"round":
473 stroke.line_join = objects.shapes.LineJoin.Round
474 elif linejoin ==
"bevel":
475 stroke.line_join = objects.shapes.LineJoin.Bevel
476 elif linejoin
in {
"miter",
"arcs",
"miter-clip"}:
477 stroke.line_join = objects.shapes.LineJoin.Miter
479 stroke.miter_limit = self.
_parse_unit(style.get(
"stroke-miterlimit", 0))
481 dash_array = style.get(
"stroke-dasharray")
482 if dash_array
and dash_array !=
"none":
483 values = list(map(self.
_parse_unit, dash_array.replace(
",",
" ").split()))
488 for i
in range(0, len(values), 2):
492 fill_color = style.get(
"fill",
"inherit")
493 if fill_color
not in nocolor:
494 if fill_color.startswith(
"url"):
503 opacity *= float(style.get(
"fill-opacity", 1))
504 fill.opacity.value = opacity * 100
506 if style.get(
"fill-rule",
"") ==
"evenodd":
507 fill.fill_rule = objects.FillRule.EvenOdd
509 group.add_shape(fill)
512 link = element.attrib.get(self.
qualified(
"xlink",
"href"))
513 if link
and link.startswith(
"#"):
515 base_element = self.
document.find(
".//*[@id='%s']" % id)
516 use_style = self.
parse_style(element, parent_style)
518 shape_parent.add_shape(used)
520 used.transform.position.value.x = float(element.attrib.get(
"x", 0))
521 used.transform.position.value.y = float(element.attrib.get(
"y", 0))
528 shape_parent.shapes.insert(0, group)
536 group.transform.opacity.value = 0
541 ellipse.position.value =
NVector(
549 self.
add_shapes(element, [ellipse], shape_parent, parent_style)
560 ellipse.position.value =
NVector(
565 ellipse.size.value =
NVector(r, r)
566 self.
add_shapes(element, [ellipse], shape_parent, parent_style)
576 w = self.
_parse_unit(element.attrib.get(
"width", 0))
577 h = self.
_parse_unit(element.attrib.get(
"height", 0))
579 self.
_parse_unit(element.attrib.get(
"x", 0)) + w / 2,
580 self.
_parse_unit(element.attrib.get(
"y", 0)) + h / 2
582 rect.size.value =
NVector(w, h)
585 rect.rounded.value = (rx + ry) / 2
586 self.
add_shapes(element, [rect], shape_parent, parent_style)
593 self.
_merge_animations(element, animations,
"position",
"size",
"position",
lambda p, s: p + s / 2)
595 self.
_merge_animations(element, animations,
"rx",
"ry",
"rounded",
lambda x, y: (x + y) / 2)
600 line.shape.value.add_point(
NVector(
604 line.shape.value.add_point(
NVector(
608 return self.
add_shapes(element, [line], shape_parent, parent_style)
611 line = group.shapes[0]
627 coords = list(map(float, element.attrib[
"points"].replace(
",",
" ").split()))
628 for i
in range(0, len(coords), 2):
629 line.shape.value.add_point(
NVector(*coords[i:i+2]))
634 return self.
add_shapes(element, [line], shape_parent, parent_style)
638 line.shape.value.close()
639 return self.
add_shapes(element, [line], shape_parent, parent_style)
642 d_parser =
PathDParser(element.attrib.get(
"d",
""))
645 for path
in d_parser.paths:
651 return self.
add_shapes(element, paths, shape_parent, parent_style)
654 for child
in element:
656 if not self.
parse_shape(child, shape_parent, parent_style):
657 handler = getattr(self,
"_parse_" + tag,
None)
662 handler = getattr(self,
"_parseshape_" + self.
unqualified(element.tag),
None)
664 out = handler(element, shape_parent, parent_style)
666 if element.attrib.get(
"id"):
667 self.
defs.items[element.attrib[
"id"]] = out
676 params = list(map(float, t[2].strip().replace(
",",
" ").split()))
677 if name ==
"translate":
680 (params[1]
if len(params) > 1
else 0),
682 elif name ==
"scale":
684 yfac = params[1]
if len(params) > 1
else xfac
685 matrix.scale(xfac, yfac)
686 elif name ==
"rotate":
692 matrix.translate(-x, -y)
693 matrix.rotate(math.radians(ang))
694 matrix.translate(x, y)
696 matrix.rotate(math.radians(ang))
697 elif name ==
"skewX":
698 matrix.skew(math.radians(params[0]), 0)
699 elif name ==
"skewY":
700 matrix.skew(0, math.radians(params[0]))
701 elif name ==
"matrix":
703 m.a, m.b, m.c, m.d, m.tx, m.ty = params
709 for t
in re.finditer(
r"([a-zA-Z]+)\s*\(([^\)]*)\)", transform):
717 id = element.attrib[
"id"]
720 grad.parse_attrs(element.attrib)
721 href = element.attrib.get(self.
qualified(
"xlink",
"href"))
723 srcid = href.strip(
"#")
727 src = grad.__class__()
729 grad.colors = src.colors
731 for stop
in element.findall(
"./%s" % self.
qualified(
"svg",
"stop")):
732 offset = stop.attrib.get(
"offset",
"0")
733 off = float(offset.strip(
"%"))
734 if offset.endswith(
"%"):
737 color = self.
parse_color(style.get(
"stop-color",
"black"))
738 if "stop-opacity" in style:
739 color[3] = float(style[
"stop-opacity"])
740 grad.add_color(off, color)
750 match = re.match(
r"""url\(['"]?#([^)'"]+)['"]?\)""", color)
757 outgrad = gradientclass()
758 grad.to_lottie(outgrad, shape)
765 if "font-family" in style:
766 font_style.query.family(style[
"font-family"].strip(
"'\""))
768 if "font-style" in style:
769 if style[
"font-style"] ==
"oblique":
770 font_style.query.custom(
"slant", 110)
771 elif style[
"font-style"] ==
"italic":
772 font_style.query.custom(
"slant", 100)
774 if "font-weight" in style:
775 if style[
"font-weight"]
in {
"bold",
"bolder"}:
776 font_style.query.weight(200)
777 elif style[
"font-weight"] ==
"lighter":
778 font_style.query.weight(50)
779 elif style[
"font-weight"].isdigit():
780 font_style.query.css_weight(int(style[
"font-weight"]))
782 if "font-size" in style:
783 fz = style[
"font-size"]
794 font_style.size = fz_names[fz]
795 elif fz ==
"smaller":
799 elif fz.endswith(
"px"):
800 font_style.size = float(fz[:-2])
802 font_style.size = float(fz)
804 if "text-align" in style:
805 ta = style[
"text-align"]
806 if ta
in (
"left",
"start"):
807 font_style.justify = font.TextJustify.Left
809 font_style.justify = font.TextJustify.Center
810 elif ta
in (
"right",
"end"):
811 font_style.justify = font.TextJustify.Right
816 if "x" in element.attrib
or "y" in element.attrib:
818 float(element.attrib[
"x"]),
819 float(element.attrib[
"y"]),
822 childpos =
NVector(0, font_style.position.y)
825 fs = font.FontShape(element.text, font_style)
828 childpos.x = fs.wrapped.next_x
830 for child
in element:
831 if child.tag == self.
qualified(
"svg",
"tspan"):
832 child_style = font_style.clone()
833 child_style.position = childpos.clone()
835 childpos.x = fs.next_x
837 child_style = font_style.clone()
838 child_style.position = childpos.clone()
839 fs = font.FontShape(child.tail, child_style)
842 childpos.x = fs.wrapped.next_x
844 group.next_x = childpos.x
852 group.name = self.
_get_id(element)
855 if font_style
is None:
856 font_style = font.FontStyle(
"", 64)
859 style.setdefault(
"fill",
"none")
880 shape_parent.shapes.insert(0, group)
886 for child
in element:
888 att = child.attrib[
"attributeName"]
890 from_val = child.attrib[
"from"]
895 from_val = float(from_val)
896 if "to" in child.attrib:
897 to_val = float(child.attrib[
"to"])
898 elif "by" in child.attrib:
899 to_val = float(child.attrib[
"by"]) + from_val
902 if "dur" in child.attrib:
904 elif "end" in child.attrib:
909 if att
not in animations:
911 animations[att][begin] = from_val
912 animations[att][end] = to_val
917 handler = getattr(self,
"_parseshape_anim_" + tag,
None)
919 handler(lottie, element, animations)
923 @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#Clock-value
931 for elem
in reversed(value.split(
":")):
932 seconds += float(elem) * mult
934 elif value.endswith(
"s"):
935 seconds = float(value[:-1])
936 elif value.endswith(
"ms"):
937 seconds = float(value[:-2]) / 1000
938 elif value.endswith(
"min"):
939 seconds = float(value[:-3]) * 60
940 elif value.endswith(
"h"):
941 seconds = float(value[:-1]) * 60 * 60
943 seconds = float(value)
944 return seconds * self.
animation.frame_rate
950 if val1
not in animations
and val2
not in animations:
953 dict1 = list(sorted(animations.pop(val1, {}).items()))
954 dict2 = list(sorted(animations.pop(val2, {}).items()))
956 x = float(element.attrib[val1])
957 y = float(element.attrib[val2])
959 while dict1
or dict2:
960 if not dict1
or (dict2
and dict1[0][0] > dict2[0][0]):
962 elif not dict2
or dict1[0][0] < dict2[0][0]:
968 values[t] = merge(x, y)
970 animations[dest] = values
973 if name
in animations:
974 for t, v
in animations[name].items():
975 animatable.add_keyframe(t, transform(v))
979 _re = re.compile(
"|".join((
981 r"[-+]?[0-9]*\.?[0-9]*[eE][-+]?[0-9]+",
982 r"[-+]?[0-9]*\.?[0-9]+",
1003 if isinstance(self.
la, str):
1023 while self.
la is not None:
1025 parser =
"_parse_" + self.
la
1027 getattr(self, parser)()
1030 getattr(self, parser)()
1057 return (point - (rel
or self.
p))
if point
is not None else NVector(0, 0)
1065 rp = self.
path.vertices[-1]
1066 self.
path.out_tangents[-1] = self.
_rpoint(outp, rp)
1103 self.
p[0] += self.
la
1123 self.
p[1] += self.
la
1136 self.
path.add_point(
1152 self.
path.add_point(
1166 handle = self.
path.in_tangents[-1]
1167 self.
path.out_tangents[-1] = (-handle)
1169 self.
path.add_point(
1183 handle = self.
path.in_tangents[-1]
1184 self.
path.out_tangents[-1] = (-handle)
1186 self.
path.add_point(
1201 self.
path.add_point(
1216 self.
path.add_point(
1229 handle = self.
p - self.
path.in_tangents[-1]
1231 self.
path.add_point(
1244 handle = -self.
path.in_tangents[-1] + self.
p
1246 self.
path.add_point(
1263 self.
_do_arc(r[0], r[1], xrot, large, sweep, dest)
1267 def _do_arc(self, rx, ry, xrot, large, sweep, dest):
1272 if rx == 0
or ry == 0:
1275 self.
path.add_point(
1282 ellipse, theta1, deltatheta = Ellipse.from_svg_arc(self.
p, rx, ry, xrot, large, sweep, dest)
1283 points = ellipse.to_bezier_points(theta1, deltatheta)
1286 self.
path.out_tangents[-1] = points[0].out_tangent
1287 for point
in points[1:-1]:
1288 self.
path.add_point(
1293 self.
path.add_point(
1295 points[-1].in_tangent,
1309 self.
_do_arc(r[0], r[1], xrot, large, sweep, dest)
1314 if self.
path.vertices:
1315 self.
p = self.
path.vertices[0].clone()
1323def parse_svg_etree(etree, layer_frames=0, *args, **kwargs):
1325 return parser.parse_etree(etree, layer_frames, *args, **kwargs)
1328def parse_svg_file(file, layer_frames=0, *args, **kwargs):
1329 return parse_svg_etree(ElementTree.parse(file), layer_frames, *args, **kwargs)
Top level object, describing the animation.
Base class for all layers.
Layer containing ShapeElement objects.
ShapeElement that can contain other shapes.
A simple rectangle shape.
qualified(self, ns, name)
_do_arc(self, rx, ry, xrot, large, sweep, dest)
_do_add_p(self, outp=None)
_rpoint(self, point, rel=None)
insert(self, dummy, shape)
__setitem__(self, key, value)
parse(self, attr, default_percent)
to_value(self, bbox, default=None)
__init__(self, name, comp, value, percent)
to_lottie(self, gradient_shape, shape, time=0)
add_color(self, offset, color)
parse_attrs(self, attrib)
to_lottie(self, gradient_shape, shape, time=0)
_fix_viewbox(self, svg, layers)
_parseshape_circle(self, element, shape_parent, parent_style)
_parseshape_path(self, element, shape_parent, parent_style)
_parseshape_anim_rect(self, rect, element, animations)
_parseshape_anim_circle(self, ellipse, element, animations)
parse_children(self, element, shape_parent, parent_style)
_parseshape_text(self, element, shape_parent, parent_style, font_style=None)
etree_to_layer(self, animation, etree)
_parseshape_ellipse(self, element, shape_parent, parent_style)
parse_animation_time(self, value)
_parseshape_polyline(self, element, shape_parent, parent_style)
parse_transform(self, element, group, dest_trans)
_parseshape_anim_ellipse(self, ellipse, element, animations)
_parseshape_line(self, element, shape_parent, parent_style)
_add_style_shapes(self, style, group)
_apply_transform_element_to_matrix(self, matrix, t)
_parseshape_anim_line(self, group, element, animations)
_transform_to_matrix(self, transform)
_svg_to_layer(self, animation, svg)
parse_shape(self, element, shape_parent, parent_style)
get_color_url(self, color, gradientclass, shape)
_parse_text_style(self, style, font_style=None)
parse_defs(self, element)
_parse_viewbox(self, attrib)
parse_etree(self, etree, layer_frames=0, *args, **kwargs)
add_shapes(self, element, shapes, shape_parent, parent_style)
_parseshape_polygon(self, element, shape_parent, parent_style)
_merge_animations(self, element, animations, val1, val2, dest, merge=NVector)
apply_visibility(self, style, object)
apply_common_style(self, style, transform)
_gradient(self, element, grad)
_parse_linearGradient(self, element)
_apply_animations(self, animatable, name, animations, transform=lambda v:v)
parse_style(self, element, parent_style)
_parseshape_g(self, element, shape_parent, parent_style)
_parse_text_elem(self, element, style, group, parent_style, font_style)
_get_name(self, element, inkscapequal)
_parseshape_use(self, element, shape_parent, parent_style)
__init__(self, name_mode=NameMode.Inkscape)
_parseshape_rect(self, element, shape_parent, parent_style)
_parse_radialGradient(self, element)
parse_animations(self, lottie, element)
_handle_poly(self, element)
to_lottie(self, gradient_shape, shape, time=0)