use super::converters::{conv_blend_mode, conv_scalar, conv_shape_geometry, conv_transform};
use super::defaults::FLOAT_VALUE_ONE_HUNDRED;
use crate::runtime::model::Layer;
use crate::schema::helpers::int_boolean::BoolInt;
use crate::{runtime, schema};
use peniko::{self, BlendMode, Compose, Mix};
pub struct LayerSetupParams {
pub layer_index: usize,
pub matte_mode: Option<BlendMode>,
pub matte_layer_index: Option<usize>,
}
pub fn setup_precomp_layer(
source: &schema::layers::precomposition::PrecompositionLayer,
target: &mut Layer,
) -> LayerSetupParams {
target.name = source
.visual_layer
.layer
.visual_object
.name
.clone()
.unwrap_or_default();
target.parent = source.visual_layer.layer.parent_index;
let (transform, opacity) = conv_transform(&source.visual_layer.transform);
target.transform = transform;
target.opacity = opacity;
target.width = source.width;
target.height = source.height;
target.is_mask = source
.visual_layer
.matte_target
.as_ref()
.is_some_and(|td| *td == BoolInt::True);
let matte_mode = source
.visual_layer
.matte_mode
.as_ref()
.map(|mode| match mode {
schema::constants::matte_mode::MatteMode::Normal => Mix::Normal.into(),
schema::constants::matte_mode::MatteMode::Alpha
| schema::constants::matte_mode::MatteMode::Luma => Compose::SrcIn.into(),
schema::constants::matte_mode::MatteMode::InvertedAlpha
| schema::constants::matte_mode::MatteMode::InvertedLuma => Compose::SrcOut.into(),
});
let matte_layer_index = source
.visual_layer
.matte_layer_index
.map(|idx| idx as usize);
target.blend_mode = conv_blend_mode(
source
.visual_layer
.blend_mode
.as_ref()
.unwrap_or(&crate::schema::constants::blend_mode::BlendMode::Normal),
);
if target.blend_mode == Some(peniko::Mix::Normal.into()) {
target.blend_mode = None;
}
target.stretch = source.visual_layer.layer.time_stretch.unwrap_or(1.0);
target.frames = source.visual_layer.layer.in_point..source.visual_layer.layer.out_point;
target.start_frame = source.start_time;
for mask_source in source
.visual_layer
.masks_properties
.as_ref()
.unwrap_or(&Vec::default())
{
if let Some(shape) = &mask_source.shape
&& let Some(geometry) = conv_shape_geometry(shape)
{
let mode = peniko::BlendMode::default();
let opacity = conv_scalar(
mask_source
.opacity
.as_ref()
.unwrap_or(&FLOAT_VALUE_ONE_HUNDRED),
);
target.masks.push(runtime::model::Mask {
mode,
geometry,
opacity,
});
}
}
LayerSetupParams {
layer_index: source.visual_layer.layer.index.unwrap_or(0),
matte_mode,
matte_layer_index,
}
}
pub fn setup_shape_layer(
source: &schema::layers::shape::ShapeLayer,
target: &mut Layer,
) -> LayerSetupParams {
target.name = source
.visual_layer
.layer
.visual_object
.name
.clone()
.unwrap_or_default();
target.parent = source.visual_layer.layer.parent_index;
let (transform, opacity) = conv_transform(&source.visual_layer.transform);
target.transform = transform;
target.opacity = opacity;
target.is_mask = source
.visual_layer
.matte_target
.as_ref()
.is_some_and(|td| *td == BoolInt::True);
let matte_mode = source
.visual_layer
.matte_mode
.as_ref()
.map(|mode| match mode {
schema::constants::matte_mode::MatteMode::Normal => Mix::Normal.into(),
schema::constants::matte_mode::MatteMode::Alpha
| schema::constants::matte_mode::MatteMode::Luma => Compose::SrcIn.into(),
schema::constants::matte_mode::MatteMode::InvertedAlpha
| schema::constants::matte_mode::MatteMode::InvertedLuma => Compose::SrcOut.into(),
});
let matte_layer_index = source
.visual_layer
.matte_layer_index
.map(|idx| idx as usize);
target.blend_mode = conv_blend_mode(
source
.visual_layer
.blend_mode
.as_ref()
.unwrap_or(&crate::schema::constants::blend_mode::BlendMode::Normal),
);
if target.blend_mode == Some(peniko::Mix::Normal.into()) {
target.blend_mode = None;
}
target.stretch = source.visual_layer.layer.time_stretch.unwrap_or(1.0);
target.frames = source.visual_layer.layer.in_point..source.visual_layer.layer.out_point;
target.start_frame = source.visual_layer.layer.start_time.unwrap_or(0.0);
for mask_source in source
.visual_layer
.masks_properties
.as_ref()
.unwrap_or(&Vec::default())
{
if let Some(shape) = &mask_source.shape
&& let Some(geometry) = conv_shape_geometry(shape)
{
let mode = peniko::BlendMode::default();
let opacity = conv_scalar(
mask_source
.opacity
.as_ref()
.unwrap_or(&FLOAT_VALUE_ONE_HUNDRED),
);
target.masks.push(runtime::model::Mask {
mode,
geometry,
opacity,
});
}
}
LayerSetupParams {
layer_index: source.visual_layer.layer.index.unwrap_or(0),
matte_mode,
matte_layer_index,
}
}
pub fn setup_layer_base(
source: &schema::layers::visual::VisualLayer,
target: &mut Layer,
) -> LayerSetupParams {
target.name = source.layer.visual_object.name.clone().unwrap_or_default();
target.parent = source.layer.parent_index;
let (transform, opacity) = conv_transform(&source.transform);
target.transform = transform;
target.opacity = opacity;
target.is_mask = source
.matte_target
.as_ref()
.is_some_and(|td| *td == BoolInt::True);
let matte_mode = source.matte_mode.as_ref().map(|mode| match mode {
schema::constants::matte_mode::MatteMode::Normal => Mix::Normal.into(),
schema::constants::matte_mode::MatteMode::Alpha
| schema::constants::matte_mode::MatteMode::Luma => Compose::SrcIn.into(),
schema::constants::matte_mode::MatteMode::InvertedAlpha
| schema::constants::matte_mode::MatteMode::InvertedLuma => Compose::SrcOut.into(),
});
let matte_layer_index = source.matte_layer_index.map(|idx| idx as usize);
target.blend_mode = conv_blend_mode(
source
.blend_mode
.as_ref()
.unwrap_or(&crate::schema::constants::blend_mode::BlendMode::Normal),
);
if target.blend_mode == Some(peniko::Mix::Normal.into()) {
target.blend_mode = None;
}
target.stretch = source.layer.time_stretch.unwrap_or(1.0);
target.frames = source.layer.in_point..source.layer.out_point;
target.start_frame = source.layer.start_time.unwrap_or(0.0);
for mask_source in source.masks_properties.as_ref().unwrap_or(&Vec::default()) {
if let Some(shape) = &mask_source.shape
&& let Some(geometry) = conv_shape_geometry(shape)
{
let mode = peniko::BlendMode::default();
let opacity = conv_scalar(
mask_source
.opacity
.as_ref()
.unwrap_or(&FLOAT_VALUE_ONE_HUNDRED),
);
target.masks.push(runtime::model::Mask {
mode,
geometry,
opacity,
});
}
}
LayerSetupParams {
layer_index: source.layer.index.unwrap_or(0),
matte_mode,
matte_layer_index,
}
}