gioser

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 124Markdown 82TOML 78Shell 12149 Definiciones

⎇ main shared/foreign-lottie/src/schema/shapes/mod.rs Rust · 262 líneas · 7.8 KB Historia Quién tocó qué crudo

chore: refresco desde el monorepo — 27 crates nuevos (anim, lottie, svg, mesh, image, layer, test, wire-view, widgets rag-sidebar/router/lazy-list/rive-button) y sync de los 95 existentes 93253cc22 · Sergio ·

1// Copyright 2024 the Velato Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4pub mod base_gradient;
5pub mod base_stroke;
6pub mod ellipse;
7pub mod fill;
8pub mod gradient_fill;
9pub mod gradient_stroke;
10pub mod graphic_element;
11pub mod group;
12pub mod merge;
13pub mod modifier;
14pub mod offset_path;
15pub mod path;
16pub mod polystar;
17pub mod pucker_bloat;
18pub mod rectangle;
19pub mod repeater;
20pub mod repeater_transform;
21pub mod rounded_corners;
22pub mod shape;
23pub mod shape_style;
24pub mod stroke;
25pub mod stroke_dash;
26pub mod transform;
27pub mod trim_path;
28pub mod twist;
29// todo pub mod shape_list;
30// todo pub mod zig_zag;
31// todo pub mod no_style;
32
33use crate::schema::shapes::{rounded_corners::RoundedCornersShape, twist::TwistShape};
34
35use self::fill::FillShape;
36use self::gradient_fill::GradientFillShape;
37use self::gradient_stroke::GradientStrokeShape;
38use self::merge::MergeShape;
39use self::offset_path::OffsetPathShape;
40use self::path::PathShape;
41use self::pucker_bloat::PuckerBloatShape;
42use self::rectangle::RectangleShape;
43use self::repeater::RepeaterShape;
44use self::stroke::StrokeShape;
45use self::transform::TransformShape;
46use self::trim_path::TrimPathShape;
47use super::animated_properties::value::FloatValue;
48use ellipse::EllipseShape;
49use group::GroupShape;
50use serde::{Deserialize, Serialize};
51
52/// Lottie considers everything related to vector data as a "shape". All shapes
53/// share the properties in `shapes::common::Properties`.
54#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
55#[serde(tag = "ty")]
56#[expect(
57    clippy::large_enum_variant,
58    reason = "Shapes have inherently different sizes based on the Lottie spec"
59)]
60pub enum AnyShape {
61    /// A group is a shape that can contain other shapes (including other
62    /// groups)
63    #[serde(rename = "gr")]
64    Group(GroupShape),
65    /// A rectangle, defined by its center point and size.
66    #[serde(rename = "rc")]
67    Rectangle(RectangleShape),
68    /// An ellipse, defined by its center point and width and height.
69    #[serde(rename = "el")]
70    Ellipse(EllipseShape),
71    #[serde(rename = "tr")]
72    Transform(TransformShape),
73    #[serde(rename = "st")]
74    Stroke(StrokeShape),
75    #[serde(rename = "pb")]
76    PuckerBloat(PuckerBloatShape),
77    #[serde(rename = "mm")]
78    Merge(MergeShape),
79    #[serde(rename = "rp")]
80    Repeater(RepeaterShape),
81    #[serde(rename = "op")]
82    OffsetPath(OffsetPathShape),
83    #[serde(rename = "fl")]
84    Fill(FillShape),
85    #[serde(rename = "tm")]
86    Trim(TrimPathShape),
87    #[serde(rename = "sh")]
88    Path(PathShape),
89    #[serde(rename = "gf")]
90    GradientFill(GradientFillShape),
91    #[serde(rename = "gs")]
92    GradientStroke(GradientStrokeShape),
93    #[serde(rename = "tw")]
94    Twist(TwistShape),
95    #[serde(rename = "rd")]
96    RoundedCorners(RoundedCornersShape),
97    // TODO: model other shapes
98    // todo ZigZag(zig_zag),
99    // todo no_style(no_style),
100}
101
102#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
103pub enum ShapeType {
104    #[serde(rename = "rc")]
105    Rectangle,
106    #[serde(rename = "el")]
107    Ellipse,
108    #[serde(rename = "sr")]
109    PolyStar,
110    #[serde(rename = "sh")]
111    Path,
112    #[serde(rename = "fl")]
113    Fill,
114    #[serde(rename = "st")]
115    Stroke,
116    #[serde(rename = "gf")]
117    GradientFill,
118    #[serde(rename = "gs")]
119    GradientStroke,
120    #[serde(rename = "no")]
121    NoStyle,
122    #[serde(rename = "gr")]
123    Group,
124    #[serde(rename = "tr")]
125    Transform,
126    #[serde(rename = "rp")]
127    Repeater,
128    #[serde(rename = "tm")]
129    Trim,
130    #[serde(rename = "rd")]
131    RoundedCorners,
132    #[serde(rename = "pb")]
133    PuckerBloat,
134    #[serde(rename = "mm")]
135    Merge,
136    #[serde(rename = "tw")]
137    Twist,
138    #[serde(rename = "op")]
139    OffsetPath,
140    #[serde(rename = "zz")]
141    ZigZag,
142}
143
144#[cfg(test)]
145mod tests {
146    use super::{
147        AnyShape, ellipse::EllipseShape, graphic_element::GraphicElementShape, group::GroupShape,
148    };
149    use crate::schema::{
150        animated_properties::{
151            animated_property::{AnimatedProperty, AnimatedPropertyK},
152            multi_dimensional::MultiDimensional,
153            position::{Position, PositionValueK},
154        },
155        helpers::{int_boolean::BoolInt, visual_object::VisualObject},
156        shapes::shape::Shape,
157    };
158    use serde_json::json;
159    use std::sync::LazyLock;
160
161    static JSON: LazyLock<serde_json::Value> = LazyLock::new(|| {
162        json!(
163            {
164                "ty": "gr",
165                "nm": "Group",
166                "mn": "{f1becc2a-49f0-4f0c-918f-bdffe4c6870f}",
167                "it": [
168                    {
169                        "ty": "el",
170                        "nm": "Ellipse",
171                        "mn": "{2aabac6e-1dd8-41b0-b60b-baf75ccb6318}",
172                        "p": {
173                            "a": 0,
174                            "k": [
175                                303.9044776119403,
176                                324.9671641791045
177                            ]
178                        },
179                        "s": {
180                            "a": 0,
181                            "k": [
182                                205.46865671641788,
183                                204.6089552238806
184                            ]
185                        }
186                    }
187                ]
188            }
189        )
190    });
191
192    static LAYER: LazyLock<AnyShape> = LazyLock::new(|| {
193        AnyShape::Group(GroupShape {
194            graphic_element: GraphicElementShape {
195                visual_object: VisualObject {
196                    name: Some("Group".to_string()),
197                    match_name: Some("{f1becc2a-49f0-4f0c-918f-bdffe4c6870f}".to_string()),
198                },
199                index: None,
200                hidden: None,
201                blend_mode: None,
202                property_index: None,
203                css_class: None,
204                xml_id: None,
205            },
206            num_properties: None,
207            property_index: None,
208            shapes: vec![AnyShape::Ellipse(EllipseShape {
209                shape: Shape {
210                    graphic_element: GraphicElementShape {
211                        visual_object: VisualObject {
212                            name: Some("Ellipse".to_string()),
213                            match_name: Some("{2aabac6e-1dd8-41b0-b60b-baf75ccb6318}".to_string()),
214                        },
215                        index: None,
216                        hidden: None,
217                        blend_mode: None,
218                        property_index: None,
219                        css_class: None,
220                        xml_id: None,
221                    },
222                    direction: None,
223                },
224                position: Position {
225                    property_index: None,
226                    animated: Some(BoolInt::False),
227                    expression: None,
228                    length: None,
229                    value: PositionValueK::Static(vec![303.9044776119403, 324.9671641791045]),
230                },
231                size: MultiDimensional {
232                    animated_property: AnimatedProperty {
233                        animated: Some(BoolInt::False),
234                        property_index: None,
235                        expression: None,
236                        slot_id: None,
237                        value: AnimatedPropertyK::Static(vec![
238                            205.46865671641788,
239                            204.6089552238806,
240                        ]),
241                    },
242                    length: None,
243                },
244            })],
245        })
246    });
247
248    #[test]
249    fn test_deserialize() {
250        let actual: Result<AnyShape, serde_json::Error> = serde_json::from_value(JSON.to_owned());
251
252        match actual {
253            Ok(actual) => assert_eq!(*LAYER, actual),
254            Err(e) => panic!("{e}"),
255        }
256    }
257
258    #[test]
259    fn test_can_serialize() {
260        serde_json::to_value(&*LAYER).unwrap();
261    }
262}