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)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lottie_basic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pathfinder_lottie 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_geom"
|
||||
version = "0.12.4"
|
||||
|
@ -1256,6 +1263,14 @@ dependencies = [
|
|||
"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]]
|
||||
name = "pathfinder_magicleap_demo"
|
||||
version = "0.1.0"
|
||||
|
@ -1753,6 +1768,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "serde"
|
||||
version = "1.0.91"
|
||||
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]]
|
||||
name = "serde_derive"
|
||||
|
|
|
@ -8,9 +8,11 @@ members = [
|
|||
"examples/canvas_minimal",
|
||||
"examples/canvas_moire",
|
||||
"examples/canvas_text",
|
||||
"examples/lottie_basic",
|
||||
"geometry",
|
||||
"gl",
|
||||
"gpu",
|
||||
"lottie",
|
||||
"renderer",
|
||||
"simd",
|
||||
"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