Initial rudimentary Lottie parsing code
This commit is contained in:
parent
cd23d62f3d
commit
8c4f05ce39
|
@ -957,6 +957,13 @@ dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lottie_basic"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"pathfinder_lottie 0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lyon_geom"
|
name = "lyon_geom"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
@ -1256,6 +1263,14 @@ dependencies = [
|
||||||
"rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathfinder_lottie"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathfinder_magicleap_demo"
|
name = "pathfinder_magicleap_demo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1753,6 +1768,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.91"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
|
|
|
@ -8,9 +8,11 @@ members = [
|
||||||
"examples/canvas_minimal",
|
"examples/canvas_minimal",
|
||||||
"examples/canvas_moire",
|
"examples/canvas_moire",
|
||||||
"examples/canvas_text",
|
"examples/canvas_text",
|
||||||
|
"examples/lottie_basic",
|
||||||
"geometry",
|
"geometry",
|
||||||
"gl",
|
"gl",
|
||||||
"gpu",
|
"gpu",
|
||||||
|
"lottie",
|
||||||
"renderer",
|
"renderer",
|
||||||
"simd",
|
"simd",
|
||||||
"svg",
|
"svg",
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "lottie_basic"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[dependencies.pathfinder_lottie]
|
||||||
|
path = "../../lottie"
|
|
@ -0,0 +1,23 @@
|
||||||
|
// pathfinder/examples/lottie_basic/src/main.rs
|
||||||
|
//
|
||||||
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Experimental example for reading Lottie animations. This is very incomplete.
|
||||||
|
|
||||||
|
use pathfinder_lottie::Lottie;
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let path = env::args().skip(1).next().unwrap();
|
||||||
|
let file = BufReader::new(File::open(path).unwrap());
|
||||||
|
let lottie = Lottie::from_reader(file).unwrap();
|
||||||
|
println!("{:#?}", lottie);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "pathfinder_lottie"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1.0"
|
||||||
|
features = ["derive"]
|
|
@ -0,0 +1,313 @@
|
||||||
|
// pathfinder/lottie/src/lib.rs
|
||||||
|
//
|
||||||
|
// Copyright © 2019 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Experimental support for Lottie. This is very incomplete.
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Error as JSONError;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Lottie {
|
||||||
|
#[serde(rename = "v")]
|
||||||
|
pub version: String,
|
||||||
|
#[serde(rename = "fr")]
|
||||||
|
pub frame_rate: i64,
|
||||||
|
#[serde(rename = "ip")]
|
||||||
|
pub in_point: i64,
|
||||||
|
#[serde(rename = "op")]
|
||||||
|
pub out_point: i64,
|
||||||
|
#[serde(rename = "w")]
|
||||||
|
pub width: f64,
|
||||||
|
#[serde(rename = "h")]
|
||||||
|
pub height: f64,
|
||||||
|
#[serde(rename = "ddd")]
|
||||||
|
pub three_d: i64,
|
||||||
|
pub assets: Vec<Asset>,
|
||||||
|
pub layers: Vec<Layer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Asset {}
|
||||||
|
|
||||||
|
// FIXME(pcwalton): Using an untagged enum is a botch here. There actually is a tag: it's just an
|
||||||
|
// integer, which `serde_json` doesn't support natively.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Layer {
|
||||||
|
Shape {
|
||||||
|
#[serde(rename = "ddd")]
|
||||||
|
three_d: i64,
|
||||||
|
#[serde(rename = "ind")]
|
||||||
|
index: i64,
|
||||||
|
#[serde(rename = "nm")]
|
||||||
|
name: String,
|
||||||
|
#[serde(rename = "ks")]
|
||||||
|
transform: Transform,
|
||||||
|
#[serde(rename = "ao")]
|
||||||
|
auto_orient: i64,
|
||||||
|
#[serde(rename = "ip")]
|
||||||
|
in_point: i64,
|
||||||
|
#[serde(rename = "op")]
|
||||||
|
out_point: i64,
|
||||||
|
#[serde(rename = "st")]
|
||||||
|
start_time: i64,
|
||||||
|
#[serde(rename = "bm")]
|
||||||
|
blend_mode: i64,
|
||||||
|
#[serde(rename = "sr")]
|
||||||
|
stretch: i64,
|
||||||
|
#[serde(rename = "ln")]
|
||||||
|
#[serde(default)]
|
||||||
|
layer_id: Option<String>,
|
||||||
|
shapes: Vec<Shape>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Transform {
|
||||||
|
#[serde(rename = "p")]
|
||||||
|
pub position: MultidimensionalPropertyValue,
|
||||||
|
#[serde(rename = "a")]
|
||||||
|
pub anchor_point: MultidimensionalPropertyValue,
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
pub scale: MultidimensionalPropertyValue,
|
||||||
|
#[serde(rename = "r")]
|
||||||
|
pub rotation: PropertyValue,
|
||||||
|
#[serde(rename = "o")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub opacity: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "px")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub position_x: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "py")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub position_y: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "pz")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub position_z: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "sk")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub skew: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "sa")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub skew_axis: Option<PropertyValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum PropertyValue {
|
||||||
|
Value {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
value: f32,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
},
|
||||||
|
KeyframedValue {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
keyframes: Vec<KeyframeValue>,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct KeyframeValue {
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub start: Option<Vec<f32>>,
|
||||||
|
#[serde(rename = "t")]
|
||||||
|
pub time: i64,
|
||||||
|
#[serde(rename = "i")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub interpolation: Option<OffsetInterpolation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Interpolation {
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct OffsetInterpolation {
|
||||||
|
pub x: Vec<f32>,
|
||||||
|
pub y: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct OffsetKeyframe {
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub start: Option<Vec<f32>>,
|
||||||
|
#[serde(rename = "t")]
|
||||||
|
pub time: i64,
|
||||||
|
#[serde(rename = "i")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub in_value: Option<OffsetInterpolation>,
|
||||||
|
#[serde(rename = "o")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub out_value: Option<OffsetInterpolation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum MultidimensionalPropertyValue {
|
||||||
|
Value {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
value: Vec<f32>,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
},
|
||||||
|
KeyframedValue {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
keyframes: Vec<OffsetKeyframe>,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
#[serde(rename = "ti")]
|
||||||
|
#[serde(default)]
|
||||||
|
in_tangent: Option<i64>,
|
||||||
|
#[serde(rename = "to")]
|
||||||
|
#[serde(default)]
|
||||||
|
out_tangent: Option<i64>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "ty")]
|
||||||
|
pub enum Shape {
|
||||||
|
#[serde(rename = "gr")]
|
||||||
|
Group {
|
||||||
|
#[serde(rename = "it")]
|
||||||
|
items: Vec<Shape>,
|
||||||
|
#[serde(rename = "nm")]
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
#[serde(rename = "sh")]
|
||||||
|
Shape {
|
||||||
|
#[serde(rename = "ks")]
|
||||||
|
vertices: ShapeVertices,
|
||||||
|
#[serde(rename = "d")]
|
||||||
|
#[serde(default)]
|
||||||
|
direction: Option<i64>,
|
||||||
|
},
|
||||||
|
#[serde(rename = "fl")]
|
||||||
|
Fill {
|
||||||
|
#[serde(rename = "nm")]
|
||||||
|
#[serde(default)]
|
||||||
|
name: Option<String>,
|
||||||
|
#[serde(rename = "o")]
|
||||||
|
#[serde(default)]
|
||||||
|
opacity: Option<PropertyValue>,
|
||||||
|
#[serde(rename = "c")]
|
||||||
|
color: MultidimensionalPropertyValue,
|
||||||
|
},
|
||||||
|
#[serde(rename = "tr")]
|
||||||
|
Transform {
|
||||||
|
#[serde(rename = "r")]
|
||||||
|
rotation: PropertyValue,
|
||||||
|
#[serde(rename = "sk")]
|
||||||
|
skew: PropertyValue,
|
||||||
|
#[serde(rename = "sa")]
|
||||||
|
skew_axis: PropertyValue,
|
||||||
|
#[serde(rename = "p")]
|
||||||
|
position: MultidimensionalPropertyValue,
|
||||||
|
#[serde(rename = "a")]
|
||||||
|
anchor_point: MultidimensionalPropertyValue,
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
scale: MultidimensionalPropertyValue,
|
||||||
|
},
|
||||||
|
#[serde(other)]
|
||||||
|
Unimplemented,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ShapeVertices {
|
||||||
|
Shape {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
value: ShapeProperty,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
#[serde(rename = "a")]
|
||||||
|
animated: i64,
|
||||||
|
},
|
||||||
|
ShapeKeyframed {
|
||||||
|
#[serde(rename = "k")]
|
||||||
|
value: Vec<ShapeKeyframeProperty>,
|
||||||
|
#[serde(rename = "x")]
|
||||||
|
#[serde(default)]
|
||||||
|
expression: Option<String>,
|
||||||
|
#[serde(rename = "ix")]
|
||||||
|
#[serde(default)]
|
||||||
|
index: Option<i64>,
|
||||||
|
#[serde(rename = "a")]
|
||||||
|
animated: i64,
|
||||||
|
#[serde(rename = "ti")]
|
||||||
|
#[serde(default)]
|
||||||
|
in_tangent: Vec<i64>,
|
||||||
|
#[serde(rename = "to")]
|
||||||
|
#[serde(default)]
|
||||||
|
out_tangent: Vec<i64>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ShapeProperty {
|
||||||
|
#[serde(rename = "c")]
|
||||||
|
pub closed: bool,
|
||||||
|
#[serde(rename = "i")]
|
||||||
|
pub in_points: Vec<[f32; 2]>,
|
||||||
|
#[serde(rename = "o")]
|
||||||
|
pub out_points: Vec<[f32; 2]>,
|
||||||
|
#[serde(rename = "v")]
|
||||||
|
pub vertices: Vec<[f32; 2]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ShapeKeyframeProperty {
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub start: Vec<Option<ShapeProperty>>,
|
||||||
|
#[serde(rename = "t")]
|
||||||
|
pub time: i64,
|
||||||
|
#[serde(rename = "i")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub in_value: Option<OffsetInterpolation>,
|
||||||
|
#[serde(rename = "o")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub out_value: Option<OffsetInterpolation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Lottie {
|
||||||
|
#[inline]
|
||||||
|
pub fn from_reader<R>(reader: R) -> Result<Lottie, JSONError> where R: Read {
|
||||||
|
serde_json::from_reader(reader)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue