python-lottie  0.6.10+dev42a5126
A framework to work with lottie files and telegram animated stickers (tgs)
restructure.py
Go to the documentation of this file.
1 from .. import objects
2 
3 
5  def __init__(self, lottie):
6  self.lottie = lottie
7  self.children_pre = []
8  self.children_post = []
9  self.structured = False
10  self.shapegroup = None
11  self.matte_target = False
12  self.matte_source = None
13  self.matte_id = None
14 
15  def add(self, child):
16  c = self.children_pre if self.structured else self.children_post
17  c.insert(0, child)
18 
19 
21  def __init__(self, lottie):
22  self.lottie = lottie
23  self.children = []
24  self.fill = None
25  self.stroke = None
26  self.layer = False
27  self.paths = None
28  self.stroke_above = False
29 
30  def empty(self):
31  return not self.children
32 
33  def finalize(self, thresh=6):
34  for g in self.subgroups:
35  if g.layer:
36  self.layer = True
37  for gg in self.subgroups:
38  gg.layer = True
39  return
40  nchild = len(self.children)
41  self.layer = nchild > thresh and self.lottie.name
42 
43  @property
44  def subgroups(self):
45  for g in self.children:
46  if isinstance(g, RestructuredShapeGroup):
47  yield g
48 
49  def add(self, child):
50  self.children.insert(0, child)
51 
52 
54  def __init__(self, lottie, child):
55  self.child = child
56  self.lottie = lottie
57 
58 
60  def __init__(self):
61  self.paths = []
62 
63  def append(self, path):
64  self.paths.append(path)
65 
66 
68  def __init__(self):
69  self.layers = []
70  self.precomp = {}
71 
72 
74  merge_paths = False
75 
76  def _on_animation(self, animation):
77  raise NotImplementedError()
78 
79  def _on_shapegroup(self, shapegroup, out_parent):
80  raise NotImplementedError()
81 
82  def _on_shape(self, shape, shapegroup, out_parent):
83  raise NotImplementedError()
84 
85  def _on_merged_path(self, shape, shapegroup, out_parent):
86  raise NotImplementedError()
87 
88  def _on_shape_modifier(self, shape, shapegroup, out_parent):
89  raise NotImplementedError()
90 
91  def process(self, animation: objects.Animation):
92  out_parent = self._on_animation(animation)
93 
94  restructured = self.restructure_animation(animation, self.merge_paths)
95  for id, layers in restructured.precomp.items():
96  self._on_precomp(id, out_parent, layers)
97 
98  for asset in animation.assets or []:
99  self._on_asset(asset)
100 
101  if animation.fonts and animation.fonts.list:
102  for font in animation.fonts.list:
103  self._on_font(font)
104 
105  for layer_builder in restructured.layers:
106  self.process_layer(layer_builder, out_parent)
107 
108  def _on_layer(self, layer_builder, out_parent):
109  raise NotImplementedError()
110 
111  def _on_precomp(self, id, out_parent, layers):
112  raise NotImplementedError()
113 
114  def _on_asset(self, asset):
115  pass
116 
117  def _on_font(self, font):
118  pass
119 
120  def process_layer(self, layer_builder, out_parent):
121  out_layer = self._on_layer(layer_builder, out_parent)
122 
123  if out_layer is None:
124  return
125 
126  for c in layer_builder.children_pre:
127  self.process_layer(c, out_layer)
128 
129  shapegroup = getattr(layer_builder, "shapegroup", None)
130  if shapegroup:
131  self.shapegroup_process_children(shapegroup, out_layer)
132 
133  for c in layer_builder.children_post:
134  self.process_layer(c, out_layer)
135 
136  self._on_layer_end(out_layer)
137 
138  def _on_layer_end(self, out_layer):
139  pass
140 
141  def shapegroup_process_child(self, shape, shapegroup, out_parent):
142  if isinstance(shape, RestructuredShapeGroup):
143  return self._on_shapegroup(shape, out_parent)
144  elif isinstance(shape, RestructuredPathMerger):
145  return self._on_merged_path(shape, shapegroup, out_parent)
146  elif isinstance(shape, RestructuredModifier):
147  return self._on_shape_modifier(shape, shapegroup, out_parent)
148  else:
149  return self._on_shape(shape, shapegroup, out_parent)
150 
151  def shapegroup_process_children(self, shapegroup, out_parent):
152  for shape in shapegroup.children:
153  self.shapegroup_process_child(shape, shapegroup, out_parent)
154 
155  def restructure_animation(self, animation, merge_paths):
156  restr = RestructuredAnimation()
157  restr.layers = self.restructure_layer_list(animation.layers, merge_paths)
158  if animation.assets:
159  for asset in animation.assets:
160  if isinstance(asset, objects.Precomp):
161  restr.precomp[asset.id] = self.restructure_layer_list(asset.layers, merge_paths)
162  return restr
163 
164  def restructure_layer_list(self, layer_list, merge_paths):
165  layers = {}
166  flat_layers = []
167  prev = None
168  for layer in layer_list:
169  laybuilder = RestructuredLayer(layer)
170  flat_layers.append(laybuilder)
171 
172  if layer.index is not None:
173  layers[layer.index] = laybuilder
174 
175  if isinstance(layer, objects.ShapeLayer):
176  laybuilder.shapegroup = RestructuredShapeGroup(layer)
177  laybuilder.layer = True
178  for shape in layer.shapes:
179  self.restructure_shapegroup(shape, laybuilder.shapegroup, merge_paths)
180  laybuilder.shapegroup.finalize()
181 
182  if layer.matte_mode not in {None, objects.MatteMode.Normal}:
183  laybuilder.matte_source = prev
184  if prev:
185  prev.matte_target = laybuilder
186 
187  prev = laybuilder
188 
189  top_layers = []
190  for layer in flat_layers:
191  layer.structured = True
192  if layer.lottie.parent_index is not None:
193  layers[layer.lottie.parent_index].add(layer)
194  else:
195  top_layers.insert(0, layer)
196 
197  return top_layers
198 
199  def restructure_shapegroup(self, shape, shape_group, merge_paths):
200  if isinstance(shape, (objects.Fill, objects.GradientFill)):
201  if not shape_group.fill:
202  shape_group.fill = shape
203  elif isinstance(shape, objects.BaseStroke):
204  if not shape_group.stroke or shape_group.stroke.width.get_value(0) < shape.width.get_value(0):
205  shape_group.stroke = shape
206  if not shape_group.fill:
207  shape_group.stroke_above = True
208  elif isinstance(shape, (objects.Path)):
209  if merge_paths:
210  if not shape_group.paths:
211  shape_group.paths = RestructuredPathMerger()
212  shape_group.add(shape_group.paths)
213  shape_group.paths.append(shape)
214  else:
215  shape_group.add(shape)
216  elif isinstance(shape, (objects.Group)):
217  subgroup = RestructuredShapeGroup(shape)
218  shape_group.add(subgroup)
219  merge_paths = self.merge_paths and not any(isinstance(p, objects.Group) for p in shape.shapes)
220  for subshape in shape.shapes:
221  self.restructure_shapegroup(subshape, subgroup, merge_paths)
222  subgroup.finalize()
223  elif isinstance(shape, (objects.Modifier)):
224  if shape_group.children:
225  ch = shape_group.children.pop(0)
226  shape_group.add(RestructuredModifier(shape, ch))
227  elif isinstance(shape, (objects.ShapeElement)):
228  shape_group.add(shape)
229  elif isinstance(shape, (objects.base.CustomObject)):
230  if self._custom_object_supported(shape):
231  shape_group.add(shape)
232  else:
233  self.restructure_shapegroup(shape.wrapped, shape_group, self.merge_paths)
234 
235  def _custom_object_supported(self, shape):
236  return False
lottie.objects.shapes.Group
ShapeElement that can contain other shapes.
Definition: shapes.py:430
lottie.objects.assets.Precomp
Definition: assets.py:143
lottie.utils.restructure.AbstractBuilder._on_precomp
def _on_precomp(self, id, out_parent, layers)
Definition: restructure.py:111
lottie.utils.restructure.RestructuredPathMerger.paths
paths
Definition: restructure.py:61
lottie.utils.restructure.RestructuredModifier.__init__
def __init__(self, lottie, child)
Definition: restructure.py:54
lottie.utils.restructure.RestructuredModifier
Definition: restructure.py:53
lottie.utils.restructure.RestructuredShapeGroup.fill
fill
Definition: restructure.py:24
lottie.utils.restructure.RestructuredShapeGroup.children
children
Definition: restructure.py:23
lottie.utils.restructure.AbstractBuilder._custom_object_supported
def _custom_object_supported(self, shape)
Definition: restructure.py:235
lottie.utils.restructure.RestructuredShapeGroup.lottie
lottie
Definition: restructure.py:22
lottie.utils.restructure.RestructuredShapeGroup.paths
paths
Definition: restructure.py:27
lottie.utils.restructure.RestructuredLayer.matte_id
matte_id
Definition: restructure.py:13
lottie.utils.restructure.RestructuredShapeGroup.add
def add(self, child)
Definition: restructure.py:49
lottie.utils.restructure.RestructuredLayer.lottie
lottie
Definition: restructure.py:6
lottie.utils.restructure.RestructuredLayer.shapegroup
shapegroup
Definition: restructure.py:10
lottie.utils.restructure.AbstractBuilder.shapegroup_process_children
def shapegroup_process_children(self, shapegroup, out_parent)
Definition: restructure.py:151
lottie.utils.restructure.RestructuredAnimation.layers
layers
Definition: restructure.py:69
lottie.utils.restructure.AbstractBuilder._on_animation
def _on_animation(self, animation)
Definition: restructure.py:76
lottie.utils.restructure.RestructuredAnimation
Definition: restructure.py:67
lottie.utils.restructure.AbstractBuilder
Definition: restructure.py:73
lottie.objects.shapes.Path
Animatable Bezier curve.
Definition: shapes.py:398
lottie.utils.restructure.AbstractBuilder.restructure_animation
def restructure_animation(self, animation, merge_paths)
Definition: restructure.py:155
lottie.utils.restructure.RestructuredModifier.child
child
Definition: restructure.py:55
lottie.utils.restructure.RestructuredLayer
Definition: restructure.py:4
lottie.objects.shapes.Modifier
Definition: shapes.py:716
lottie.utils.restructure.RestructuredLayer.matte_target
matte_target
Definition: restructure.py:11
lottie.utils.restructure.AbstractBuilder.process
def process(self, objects.Animation animation)
Definition: restructure.py:91
lottie.objects.shapes.Fill
Solid fill color.
Definition: shapes.py:506
lottie.utils.restructure.RestructuredShapeGroup.finalize
def finalize(self, thresh=6)
Definition: restructure.py:33
lottie.objects.base.CustomObject
Allows extending the Lottie shapes with custom Python classes.
Definition: base.py:326
lottie.utils.restructure.RestructuredLayer.structured
structured
Definition: restructure.py:9
lottie.utils.restructure.RestructuredLayer.__init__
def __init__(self, lottie)
Definition: restructure.py:5
lottie.utils.restructure.RestructuredShapeGroup.empty
def empty(self)
Definition: restructure.py:30
lottie.utils.restructure.RestructuredLayer.children_post
children_post
Definition: restructure.py:8
lottie.utils.restructure.RestructuredShapeGroup.stroke_above
stroke_above
Definition: restructure.py:28
lottie.utils.restructure.RestructuredPathMerger.append
def append(self, path)
Definition: restructure.py:63
lottie.utils.restructure.AbstractBuilder.process_layer
def process_layer(self, layer_builder, out_parent)
Definition: restructure.py:120
lottie.utils.restructure.RestructuredModifier.lottie
lottie
Definition: restructure.py:56
lottie.objects.shapes.GradientFill
Gradient fill.
Definition: shapes.py:563
lottie.utils.restructure.RestructuredLayer.matte_source
matte_source
Definition: restructure.py:12
lottie.utils.restructure.RestructuredShapeGroup.stroke
stroke
Definition: restructure.py:25
lottie.utils.restructure.RestructuredShapeGroup.subgroups
def subgroups(self)
Definition: restructure.py:44
lottie.utils.restructure.AbstractBuilder._on_asset
def _on_asset(self, asset)
Definition: restructure.py:114
lottie.utils.restructure.RestructuredLayer.children_pre
children_pre
Definition: restructure.py:7
lottie.utils.restructure.AbstractBuilder.restructure_layer_list
def restructure_layer_list(self, layer_list, merge_paths)
Definition: restructure.py:164
lottie.utils.restructure.RestructuredPathMerger.__init__
def __init__(self)
Definition: restructure.py:60
lottie.utils.restructure.RestructuredPathMerger
Definition: restructure.py:59
lottie.utils.restructure.AbstractBuilder.shapegroup_process_child
def shapegroup_process_child(self, shape, shapegroup, out_parent)
Definition: restructure.py:141
lottie.utils.restructure.RestructuredShapeGroup
Definition: restructure.py:20
lottie.utils.restructure.AbstractBuilder.restructure_shapegroup
def restructure_shapegroup(self, shape, shape_group, merge_paths)
Definition: restructure.py:199
lottie.objects.shapes.ShapeElement
Base class for all elements of ShapeLayer and Group.
Definition: shapes.py:72
lottie.utils.restructure.RestructuredAnimation.precomp
precomp
Definition: restructure.py:70
lottie.utils.restructure.RestructuredShapeGroup.__init__
def __init__(self, lottie)
Definition: restructure.py:21
lottie.utils.restructure.RestructuredAnimation.__init__
def __init__(self)
Definition: restructure.py:68
lottie.utils.restructure.AbstractBuilder._on_font
def _on_font(self, font)
Definition: restructure.py:117
lottie.utils.restructure.RestructuredLayer.add
def add(self, child)
Definition: restructure.py:15
lottie.utils.restructure.RestructuredShapeGroup.layer
layer
Definition: restructure.py:26
lottie.objects.shapes.BaseStroke
Definition: shapes.py:622
lottie.utils.restructure.AbstractBuilder.merge_paths
bool merge_paths
Definition: restructure.py:74
lottie.objects.layers.ShapeLayer
Layer containing ShapeElement objects.
Definition: layers.py:192