Skip to content

Commit

Permalink
Prep release (linebender#15)
Browse files Browse the repository at this point in the history
Prepare for release

---------

Co-authored-by: Daniel McNab <[email protected]>
Co-authored-by: Kaur Kuut <[email protected]>
  • Loading branch information
3 people authored Mar 26, 2024
1 parent da8abdf commit 5e1f5e5
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 73 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog

<!-- Instructions
This changelog follows the patterns described here: <https://keepachangelog.com/en/1.0.0/>.
Subheadings to categorize changes are `added, changed, deprecated, removed, fixed, security`.
-->

## Unreleased

## 0.1.0 (2024-03-26)

- Initial release
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition = "2021"
version = "0.1.0"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/linebender/velato"
publish = false
[package]
name = "velato"
description = "A Lottie integration for vello."
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ Several Lottie features are not yet supported, including:
- Split rotations
- Split positions

## Usage

Velato makes it simple to encode Lottie as a [`vello::Scene`](https://docs.rs/vello/*/vello/struct.Scene.html).

```rust
// Parse your lottie file
let lottie = include_str!("../lottie.json");
let composition = velato::Composition::from_str(lottie).expect("valid file");

// Render to a scene
let mut new_scene = vello::Scene::new();

// Render to a scene!
let mut renderer = velato::Renderer::new();
let frame = 0.0; // Arbitrary number chosen. Ensure it's a valid frame!
let transform = vello::kurbo::Affine::IDENTITY;
let alpha = 1.0;
renderer.render(&composition, frame, transform, alpha, &mut new_scene);
```

## Examples

### Cross platform (Winit)
Expand Down
15 changes: 12 additions & 3 deletions examples/scenes/src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl Download {
println!(
"Would you like to download a set of default lottie files? These files are:"
);
let mut total_bytes = 0;
for download in &downloads {
let builtin = download.builtin.as_ref().unwrap();
println!(
Expand All @@ -68,12 +69,11 @@ impl Download {
builtin.license,
builtin.info
);
total_bytes += builtin.expected_size;
}

// For rustfmt, split prompt into its own line
const PROMPT: &str =
"Would you like to download a set of default lottie files, as explained above?";
accepted = Confirm::new(PROMPT).with_default(false).prompt()?;
accepted = download_prompt(total_bytes)?;
} else {
println!("Nothing to download! All default downloads already created");
}
Expand Down Expand Up @@ -148,6 +148,15 @@ impl Download {
}
}

fn download_prompt(total_bytes: u64) -> Result<bool> {
let prompt = format!(
"Would you like to download a set of default lottie files, as explained above? ({})",
byte_unit::Byte::from_bytes(total_bytes.into()).get_appropriate_unit(false)
);
let accepted = Confirm::new(&prompt).with_default(false).prompt()?;
Ok(accepted)
}

struct LottieDownload {
name: String,
url: String,
Expand Down
67 changes: 62 additions & 5 deletions src/import/converters.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Copyright 2024 the Velato Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::collections::HashMap;

use super::builders::{setup_layer_base, setup_precomp_layer, setup_shape_layer};
use super::defaults::{FLOAT_VALUE_ONE_HUNDRED, FLOAT_VALUE_ZERO, MULTIDIM_ONE, POSITION_ZERO};
use crate::import::util::calc_stops;
use crate::runtime::model::animated::{self, Position};
use crate::runtime::model::Easing;
use crate::runtime::model::{
self, Content, Draw, EasingHandle, GroupTransform, Layer, SplineToPath, Time, Tween, Value,
};
Expand All @@ -19,6 +17,7 @@ use crate::schema::animated_properties::split_vector::SplitVector;
use crate::schema::constants::gradient_type::GradientType;
use crate::schema::helpers::int_boolean::BoolInt;
use crate::{schema, Composition};
use std::collections::HashMap;
use vello::kurbo::{Cap, Join, Point, Size, Vec2};
use vello::peniko::{BlendMode, Color, Mix};

Expand Down Expand Up @@ -333,7 +332,7 @@ fn conv_gradient_colors(
match &value.colors.animated_property.value {
Static(value) => runtime::model::ColorStops::Fixed({
let mut stops = runtime::model::fixed::ColorStops::new();
let raw = calc_stops(value, count);
let raw = conv_stops(value, count);
for values in raw {
stops.push(
(
Expand Down Expand Up @@ -364,7 +363,7 @@ fn conv_gradient_colors(
hold,
});

let stops = calc_stops(&value.value, count)
let stops = conv_stops(&value.value, count)
.into_iter()
.flatten()
.collect::<Vec<_>>();
Expand Down Expand Up @@ -776,3 +775,61 @@ pub fn conv_size(value: &MultiDimensional) -> Value<Size> {
)
})
}

pub fn conv_stops(value: &[f64], count: usize) -> Vec<[f64; 5]> {
let mut stops: Vec<[f64; 5]> = Vec::new();
let mut alpha_stops: Vec<(f64, f64)> = Vec::new();
for chunk in value.chunks_exact(4) {
stops.push([chunk[0], chunk[1], chunk[2], chunk[3], 1.0]);
if stops.len() >= count {
// there is alpha data at the end of the list, which is a sequence
// of (offset, alpha) pairs
for chunk in value.chunks_exact(2).skip(count * 2) {
let offset = chunk[0];
let alpha = chunk[1];
alpha_stops.push((offset, alpha));
}

for stop in stops.iter_mut() {
let mut last: Option<(f64, f64)> = None;
for &(b, alpha_b) in alpha_stops.iter() {
if let Some((a, alpha_a)) = last.take() {
let x = stop[0];
let t = normalize_to_range(a, b, x);

let alpha_interp = alpha_a.tween(&alpha_b, t, &Easing::LERP);
let alpha_interp = if (x >= a && x <= b) && (t <= 0.25) && (x <= 0.1) {
alpha_a
} else {
alpha_interp
}; // todo: this is a hack to get alpha rendering with a
// falloff similar to lottiefiles'

let alpha_interp = if (x >= a && x <= b) && (t >= 0.75) && (x >= 0.9) {
alpha_b
} else {
alpha_interp
}; // todo: this is a hack to get alpha rendering with a
// falloff similar to lottiefiles'

stop[4] = stop[4].min(alpha_interp);
}
last = Some((b, alpha_b));
}
}
break;
}
}

stops
}

pub fn normalize_to_range(a: f64, b: f64, x: f64) -> f64 {
if a == b {
// Avoid division by zero if a and b are the same
return 0.0;
}

// Calculate the normalized value
(x - a) / (b - a)
}
1 change: 0 additions & 1 deletion src/import/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
mod builders;
mod converters;
mod defaults;
mod util;

pub use converters::conv_animation;
62 changes: 0 additions & 62 deletions src/import/util.rs

This file was deleted.

47 changes: 46 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,53 @@
// Copyright 2024 the Velato Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! Render a Lottie animation to a Vello [`Scene`](crate::vello::Scene).
//!
//! However, this is also intended to be the preferred integration between Vello and [Lottie](https://lottie.github.io/lottie-spec/), so [consider
//! contributing](https://github.com/linebender/velato) if you need a feature which is missing.
//!
//! This crate also re-exports [`vello`], to make handling dependency versions easier.
//!
//! ## Usage
//!
//! ```no_run
//! # use std::str::FromStr;
//! use velato::vello;
//!
//! // Parse your lottie file
//! let lottie = include_str!("../examples/assets/google_fonts/Tiger.json");
//! let composition = velato::Composition::from_str(lottie).expect("valid file");
//!
//! // Render to a scene
//! let mut new_scene = vello::Scene::new();
//!
//! // Render to a scene!
//! let mut renderer = velato::Renderer::new();
//! let frame = 0.0; // Arbitrary number chosen. Ensure it's a valid frame!
//! let transform = vello::kurbo::Affine::IDENTITY;
//! let alpha = 1.0;
//! renderer.render(&composition, frame, transform, alpha, &mut new_scene);
//! ```
//!
//! # Unsupported features
//!
//! Missing features include:
//! - Non-linear easings
//! - Position keyframe (`ti`, `to`) easing
//! - Time remapping (`tm`)
//! - Text
//! - Image embedding
//! - Advanced shapes (stroke dash, zig-zag, etc.)
//! - Advanced effects (motion blur, drop shadows, etc.)
//! - Correct color stop handling
//! - Split rotations
//! - Split positions
pub(crate) mod import;
pub(crate) mod runtime;
pub(crate) mod schema;

pub use runtime::{Composition, Renderer};
// Re-export vello
pub use vello;

pub use runtime::{model, Composition, Renderer};

0 comments on commit 5e1f5e5

Please sign in to comment.