rasterlottie 0.1.0

Pure Rust, headless Lottie rasterizer for deterministic server-side rendering
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
use std::collections::BTreeMap;

use serde::Deserialize;
use serde_json::Value;

/// Root Lottie animation document.
#[derive(Debug, Clone, Deserialize)]
pub struct Animation {
    #[serde(default, rename = "v")]
    /// Lottie format version string.
    pub version: String,
    #[serde(rename = "fr")]
    /// Animation frame rate in frames per second.
    pub frame_rate: f32,
    #[serde(rename = "ip")]
    /// Inclusive start frame.
    pub in_point: f32,
    #[serde(rename = "op")]
    /// Exclusive end frame.
    pub out_point: f32,
    #[serde(rename = "w")]
    /// Canvas width in pixels.
    pub width: u32,
    #[serde(rename = "h")]
    /// Canvas height in pixels.
    pub height: u32,
    #[serde(default)]
    /// Top-level layers in stacking order.
    pub layers: Vec<Layer>,
    #[serde(default)]
    /// External assets and precompositions referenced by the animation.
    pub assets: Vec<Asset>,
    #[serde(default)]
    /// Embedded font metadata.
    pub fonts: FontList,
    #[serde(default)]
    /// Embedded glyph outlines.
    pub chars: Vec<FontCharacter>,
}

/// Font metadata table embedded in a Lottie document.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct FontList {
    #[serde(default, rename = "list")]
    /// Registered fonts.
    pub list: Vec<Font>,
}

/// One font definition from the Lottie font list.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Font {
    #[serde(default, rename = "fName")]
    /// Lottie font name used by text documents.
    pub name: String,
    #[serde(default, rename = "fFamily")]
    /// Font family name.
    pub family: String,
    #[serde(default, rename = "fStyle")]
    /// Font style name.
    pub style: String,
    #[serde(default)]
    /// Font ascent in Lottie units.
    pub ascent: f32,
}

/// One embedded glyph outline.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct FontCharacter {
    #[serde(default, rename = "ch")]
    /// Grapheme represented by this glyph.
    pub character: String,
    #[serde(default, rename = "size")]
    /// Design size used by the exported glyph.
    pub size: f32,
    #[serde(default, rename = "style")]
    /// Font style associated with the glyph.
    pub style: String,
    #[serde(default, rename = "w")]
    /// Advance width at the design size.
    pub width: f32,
    #[serde(default, rename = "data")]
    /// Vector shapes that describe the glyph outline.
    pub data: FontCharacterData,
    #[serde(default, rename = "fFamily")]
    /// Optional font family override for the glyph.
    pub family: Option<String>,
}

/// Shape data attached to one embedded glyph.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct FontCharacterData {
    #[serde(default, rename = "shapes")]
    /// Shape items that draw the glyph outline.
    pub shapes: Vec<ShapeItem>,
}

/// An image asset or precomposition entry.
#[derive(Debug, Clone, Deserialize)]
pub struct Asset {
    #[serde(default, rename = "id")]
    /// Asset identifier referenced by layers.
    pub id: String,
    #[serde(default, rename = "nm")]
    /// Optional asset display name.
    pub name: Option<String>,
    #[serde(default, rename = "w")]
    /// Pixel width for image assets.
    pub width: Option<u32>,
    #[serde(default, rename = "h")]
    /// Pixel height for image assets.
    pub height: Option<u32>,
    #[serde(default, rename = "u")]
    /// Base path for external image assets.
    pub base_path: Option<String>,
    #[serde(default, rename = "p")]
    /// Relative path or embedded data URL for image assets.
    pub path: Option<String>,
    #[serde(default, rename = "e")]
    /// Embedded-image flag from the Lottie schema.
    pub embedded: Option<u8>,
    #[serde(default)]
    /// Child layers when this asset is a precomposition.
    pub layers: Vec<Layer>,
}

/// One Lottie layer.
#[derive(Debug, Clone, Deserialize)]
pub struct Layer {
    #[serde(default, rename = "nm")]
    /// Layer name.
    pub name: String,
    #[serde(rename = "ty")]
    /// Layer type tag.
    pub layer_type: LayerType,
    #[serde(default, rename = "ind")]
    /// Unique layer index used for parenting and matte lookup.
    pub index: Option<i64>,
    #[serde(default, rename = "parent")]
    /// Parent layer index, if any.
    pub parent: Option<i64>,
    #[serde(default, rename = "hd")]
    /// Whether the layer is hidden.
    pub hidden: bool,
    #[serde(default, rename = "ip")]
    /// Layer in-point in frames.
    pub in_point: Option<f32>,
    #[serde(default, rename = "op")]
    /// Layer out-point in frames.
    pub out_point: Option<f32>,
    #[serde(default, rename = "refId")]
    /// Referenced asset identifier for image and precomp layers.
    pub ref_id: Option<String>,
    #[serde(default, rename = "st")]
    /// Layer start time in frames.
    pub start_time: f32,
    #[serde(default = "default_stretch", rename = "sr")]
    /// Playback stretch factor.
    pub stretch: f32,
    #[serde(default, rename = "ks")]
    /// Layer transform block.
    pub transform: Option<Transform>,
    #[serde(default, rename = "tm")]
    /// Optional time-remap property.
    pub time_remap: Option<AnimatedValue>,
    #[serde(default, rename = "shapes")]
    /// Shape list for shape layers.
    pub shapes: Vec<ShapeItem>,
    #[serde(default, rename = "masksProperties")]
    /// Layer masks.
    pub masks: Vec<Mask>,
    #[serde(default, rename = "tt")]
    /// Track matte mode tag.
    pub track_matte: Option<u8>,
    #[serde(default, rename = "tp")]
    /// Explicit matte parent index.
    pub matte_parent: Option<i64>,
    #[serde(default, rename = "td")]
    /// Matte source marker.
    pub matte_source: Option<u8>,
    #[serde(default, rename = "ef")]
    /// Raw layer effect payloads.
    pub effects: Vec<Value>,
    #[serde(default, rename = "t")]
    /// Text payload for text layers.
    pub text: Option<TextData>,
}

/// Numeric Lottie layer type tag.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[serde(transparent)]
pub struct LayerType(#[doc = "Raw Lottie layer type tag."] pub u8);

/// Supported track matte modes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum TrackMatteMode {
    /// Standard alpha matte.
    Alpha,
    /// Inverted alpha matte.
    AlphaInverted,
    /// Standard luma matte.
    Luma,
    /// Inverted luma matte.
    LumaInverted,
}

/// Text payload attached to a text layer.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct TextData {
    #[serde(default, rename = "d")]
    /// Animated text document collection.
    pub document: TextDocumentCollection,
    #[serde(default, rename = "a")]
    /// Raw text animator definitions.
    pub animators: Vec<Value>,
    #[serde(default, rename = "p")]
    /// Raw text path definition.
    pub path: Value,
}

/// Animated collection of text documents.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct TextDocumentCollection {
    #[serde(default, rename = "k")]
    /// Text document keyframes.
    pub keyframes: Vec<TextDocumentKeyframe>,
}

/// One keyframed text document.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct TextDocumentKeyframe {
    #[serde(default, rename = "s")]
    /// Text document value.
    pub document: TextDocument,
    #[serde(default, rename = "t")]
    /// Keyframe time in frames.
    pub time: f32,
}

/// Resolved text styling and layout data.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct TextDocument {
    #[serde(default, rename = "t")]
    /// Text content.
    pub text: String,
    #[serde(default, rename = "f")]
    /// Font name.
    pub font: String,
    #[serde(default, rename = "s")]
    /// Font size.
    pub size: f32,
    #[serde(default, rename = "j")]
    /// Justification mode.
    pub justify: u8,
    #[serde(default, rename = "tr")]
    /// Tracking adjustment.
    pub tracking: f32,
    #[serde(default, rename = "lh")]
    /// Line height.
    pub line_height: f32,
    #[serde(default, rename = "ls")]
    /// Baseline shift.
    pub baseline_shift: f32,
    #[serde(default, rename = "fc")]
    /// Fill color as normalized RGB or RGBA components.
    pub fill_color: Vec<f32>,
    #[serde(default, rename = "sc")]
    /// Stroke color as normalized RGB or RGBA components.
    pub stroke_color: Vec<f32>,
    #[serde(default, rename = "sw")]
    /// Stroke width.
    pub stroke_width: f32,
    #[serde(default, rename = "ps")]
    /// Text box position.
    pub position: Option<[f32; 2]>,
    #[serde(default, rename = "sz")]
    /// Text box size.
    pub box_size: Option<[f32; 2]>,
}

/// Standard Lottie transform block.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Transform {
    #[serde(default, rename = "a")]
    /// Anchor point.
    pub anchor: Option<AnimatedValue>,
    #[serde(default, rename = "p")]
    /// Position property.
    pub position: Option<PositionValue>,
    #[serde(default, rename = "s")]
    /// Scale property.
    pub scale: Option<AnimatedValue>,
    #[serde(default, rename = "r")]
    /// Rotation property.
    pub rotation: Option<AnimatedValue>,
    #[serde(default, rename = "o")]
    /// Opacity property.
    pub opacity: Option<AnimatedValue>,
    #[serde(default, rename = "sk")]
    /// Skew property.
    pub skew: Option<AnimatedValue>,
    #[serde(default, rename = "sa")]
    /// Skew-axis property.
    pub skew_axis: Option<AnimatedValue>,
}

/// One layer mask definition.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Mask {
    #[serde(default, rename = "mode")]
    /// Raw mask mode tag.
    pub mode: Option<String>,
    #[serde(default, rename = "pt")]
    /// Mask path.
    pub path: Option<ShapePathValue>,
    #[serde(default, rename = "o")]
    /// Mask opacity.
    pub opacity: Option<AnimatedValue>,
    #[serde(default, rename = "inv")]
    /// Whether the mask is inverted.
    pub inverted: bool,
}

/// Supported mask modes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum MaskMode {
    /// Additive mask.
    Add,
    /// Subtractive mask.
    Subtract,
    /// Intersection mask.
    Intersect,
    /// Disabled mask.
    None,
}

/// Generic scalar or vector animated property.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct AnimatedValue {
    #[serde(default, rename = "a")]
    /// Lottie animated flag.
    pub animated: Option<u8>,
    #[serde(default, rename = "k")]
    /// Raw keyframe payload.
    pub keyframes: Option<Value>,
    #[serde(default, rename = "x")]
    /// Optional expression payload.
    pub expression: Option<Value>,
}

/// Position property that may be stored as one combined vector or split axes.
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
#[non_exhaustive]
pub enum PositionValue {
    /// Split-axis position.
    Split(SplitPosition),
    /// Combined vector position.
    Combined(AnimatedValue),
}

/// Split-axis position property.
#[derive(Debug, Clone, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct SplitPosition {
    #[serde(default, rename = "s")]
    /// Split-position flag.
    pub split: Option<u8>,
    #[serde(default, rename = "x")]
    /// X component.
    pub x: Option<AnimatedValue>,
    #[serde(default, rename = "y")]
    /// Y component.
    pub y: Option<AnimatedValue>,
    #[serde(default, rename = "z")]
    /// Optional Z component.
    pub z: Option<AnimatedValue>,
}

/// A static cubic Bezier path.
#[derive(Debug, Clone, PartialEq)]
pub struct BezierPath {
    /// Whether the path is closed.
    pub closed: bool,
    /// Ordered vertices with relative tangents.
    pub vertices: Vec<BezierVertex>,
}

/// One cubic Bezier vertex.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BezierVertex {
    /// Anchor point.
    pub vertex: [f32; 2],
    /// Incoming tangent, stored relative to `vertex`.
    pub in_tangent: [f32; 2],
    /// Outgoing tangent, stored relative to `vertex`.
    pub out_tangent: [f32; 2],
}

/// Animated property that stores a shape path.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct ShapePathValue {
    #[serde(default, rename = "a")]
    /// Lottie animated flag.
    pub animated: Option<u8>,
    #[serde(default, rename = "k")]
    /// Raw keyframe payload.
    pub keyframes: Option<Value>,
    #[serde(default, rename = "x")]
    /// Optional expression payload.
    pub expression: Option<Value>,
}

/// Generic Lottie shape item.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct ShapeItem {
    #[serde(default, rename = "nm")]
    /// Item name.
    pub name: String,
    #[serde(default, rename = "ty")]
    /// Shape item type tag.
    pub item_type: String,
    #[serde(default, rename = "it")]
    /// Nested shape items for groups.
    pub items: Vec<Self>,
    #[serde(default, rename = "hd")]
    /// Whether the item is hidden.
    pub hidden: bool,
    #[serde(default, rename = "x")]
    /// Optional expression payload.
    pub expression: Option<Value>,
    #[serde(default, rename = "ks")]
    /// Path property for `sh` items.
    pub path: Option<ShapePathValue>,
    #[serde(default, rename = "p")]
    /// Position-like property used by several item kinds.
    pub position: Option<PositionValue>,
    #[serde(default, rename = "s")]
    /// Size-like property used by several item kinds.
    pub size: Option<AnimatedValue>,
    #[serde(default, rename = "c")]
    /// Color-like property used by several item kinds.
    pub color: Option<AnimatedValue>,
    #[serde(default, rename = "o")]
    /// Opacity-like property used by several item kinds.
    pub opacity: Option<AnimatedValue>,
    #[serde(default, rename = "w")]
    /// Width-like property used by several item kinds.
    pub width: Option<AnimatedValue>,
    #[serde(default, rename = "a")]
    /// Anchor-like property used by several item kinds.
    pub anchor: Option<AnimatedValue>,
    #[serde(default, rename = "sk")]
    /// Skew property for transform items.
    pub skew: Option<AnimatedValue>,
    #[serde(default, rename = "sa")]
    /// Skew-axis property for transform items.
    pub skew_axis: Option<AnimatedValue>,
    #[serde(default, rename = "lc")]
    /// Stroke line-cap tag.
    pub line_cap: Option<u8>,
    #[serde(default, rename = "lj")]
    /// Stroke line-join tag.
    pub line_join: Option<u8>,
    #[serde(default, rename = "ml")]
    /// Static miter limit.
    pub miter_limit: Option<f32>,
    #[serde(default, rename = "ml2")]
    /// Animated miter limit.
    pub miter_limit_value: Option<AnimatedValue>,
    #[serde(flatten)]
    /// Unmodeled per-item fields retained in raw JSON form.
    pub extra: BTreeMap<String, Value>,
}

/// Gradient definition attached to a fill or stroke item.
#[derive(Debug, Clone, Deserialize)]
pub struct GradientData {
    #[serde(rename = "p")]
    /// Number of color stops.
    pub point_count: usize,
    #[serde(rename = "k")]
    /// Encoded color-stop data.
    pub colors: AnimatedValue,
}

/// Dash pattern entry for a stroked shape.
#[derive(Debug, Clone, Deserialize)]
pub struct DashPatternEntry {
    #[serde(default, rename = "n")]
    /// Entry kind, such as dash, gap, or offset.
    pub name: String,
    #[serde(default, rename = "v")]
    /// Entry value.
    pub value: AnimatedValue,
}

/// Transform block used by repeater items.
#[derive(Debug, Clone, Deserialize, Default)]
pub struct RepeaterTransform {
    #[serde(default, rename = "a")]
    /// Anchor point.
    pub anchor: Option<AnimatedValue>,
    #[serde(default, rename = "p")]
    /// Position property.
    pub position: Option<PositionValue>,
    #[serde(default, rename = "s")]
    /// Scale property.
    pub scale: Option<AnimatedValue>,
    #[serde(default, rename = "r")]
    /// Rotation property.
    pub rotation: Option<AnimatedValue>,
    #[serde(default, rename = "o")]
    /// Overall opacity property.
    pub opacity: Option<AnimatedValue>,
    #[serde(default, rename = "so")]
    /// Opacity at the start of the repeated range.
    pub start_opacity: Option<AnimatedValue>,
    #[serde(default, rename = "eo")]
    /// Opacity at the end of the repeated range.
    pub end_opacity: Option<AnimatedValue>,
}

const fn default_stretch() -> f32 {
    1.0
}