// pathfinder/lottie/src/lib.rs // // Copyright © 2019 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , 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, pub layers: Vec, } #[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, shapes: Vec, }, } #[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, #[serde(rename = "px")] #[serde(default)] pub position_x: Option, #[serde(rename = "py")] #[serde(default)] pub position_y: Option, #[serde(rename = "pz")] #[serde(default)] pub position_z: Option, #[serde(rename = "sk")] #[serde(default)] pub skew: Option, #[serde(rename = "sa")] #[serde(default)] pub skew_axis: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(untagged)] pub enum PropertyValue { Value { #[serde(rename = "k")] value: f32, #[serde(rename = "x")] #[serde(default)] expression: Option, #[serde(rename = "ix")] #[serde(default)] index: Option, }, KeyframedValue { #[serde(rename = "k")] keyframes: Vec, #[serde(rename = "x")] #[serde(default)] expression: Option, #[serde(rename = "ix")] #[serde(default)] index: Option, }, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeyframeValue { #[serde(rename = "s")] #[serde(default)] pub start: Option>, #[serde(rename = "t")] pub time: i64, #[serde(rename = "i")] #[serde(default)] pub interpolation: Option, } #[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, pub y: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct OffsetKeyframe { #[serde(rename = "s")] #[serde(default)] pub start: Option>, #[serde(rename = "t")] pub time: i64, #[serde(rename = "i")] #[serde(default)] pub in_value: Option, #[serde(rename = "o")] #[serde(default)] pub out_value: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(untagged)] pub enum MultidimensionalPropertyValue { Value { #[serde(rename = "k")] value: Vec, #[serde(rename = "x")] #[serde(default)] expression: Option, #[serde(rename = "ix")] #[serde(default)] index: Option, }, KeyframedValue { #[serde(rename = "k")] keyframes: Vec, #[serde(rename = "x")] #[serde(default)] expression: Option, #[serde(rename = "ix")] #[serde(default)] index: Option, #[serde(rename = "ti")] #[serde(default)] in_tangent: Option, #[serde(rename = "to")] #[serde(default)] out_tangent: Option, }, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(tag = "ty")] pub enum Shape { #[serde(rename = "gr")] Group { #[serde(rename = "it")] items: Vec, #[serde(rename = "nm")] name: String, }, #[serde(rename = "sh")] Shape { #[serde(rename = "ks")] vertices: ShapeVertices, #[serde(rename = "d")] #[serde(default)] direction: Option, }, #[serde(rename = "fl")] Fill { #[serde(rename = "nm")] #[serde(default)] name: Option, #[serde(rename = "o")] #[serde(default)] opacity: Option, #[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, #[serde(rename = "ix")] #[serde(default)] index: Option, #[serde(rename = "a")] animated: i64, }, ShapeKeyframed { #[serde(rename = "k")] value: Vec, #[serde(rename = "x")] #[serde(default)] expression: Option, #[serde(rename = "ix")] #[serde(default)] index: Option, #[serde(rename = "a")] animated: i64, #[serde(rename = "ti")] #[serde(default)] in_tangent: Vec, #[serde(rename = "to")] #[serde(default)] out_tangent: Vec, }, } #[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>, #[serde(rename = "t")] pub time: i64, #[serde(rename = "i")] #[serde(default)] pub in_value: Option, #[serde(rename = "o")] #[serde(default)] pub out_value: Option, } impl Lottie { #[inline] pub fn from_reader(reader: R) -> Result where R: Read { serde_json::from_reader(reader) } }