use super::effect_graph::EffectGraph;
use super::{CanvasComposite, GraphicsEffect};
use crate::rendering::composition::{
CompositionBackdropBrush, CompositionEffectBrush, CompositionHostBackdropBrush, Compositor,
};
use std::rc::Rc;
use std::sync::Arc;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum CompositionEffectFactoryLoadStatus {
#[default]
Success = 0,
EffectTooComplex = 1,
Pending = 2,
Other = -1,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CompositionEffectFactoryError {
EffectTypeNotSupported(&'static str),
CompositeModeNotSupported(CanvasComposite),
MissingSource {
effect: &'static str,
name: String,
},
InvalidAnimatableProperty(String),
EffectTooComplex,
}
impl std::fmt::Display for CompositionEffectFactoryError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CompositionEffectFactoryError::EffectTypeNotSupported(effect) => {
write!(f, "the effect type {effect} is not supported")
}
CompositionEffectFactoryError::CompositeModeNotSupported(mode) => {
write!(f, "the composite mode {mode:?} is not supported")
}
CompositionEffectFactoryError::MissingSource { effect, name } => {
write!(f, "the {effect} '{name}' has an input that is not set")
}
CompositionEffectFactoryError::InvalidAnimatableProperty(key) => {
write!(f, "'{key}' is not an animatable property of the effect")
}
CompositionEffectFactoryError::EffectTooComplex => f.write_str("the effect graph is too complex"),
}
}
}
impl std::error::Error for CompositionEffectFactoryError {}
pub struct CompositionEffectFactory {
compositor: Rc<Compositor>,
graph: Arc<EffectGraph>,
load_status: CompositionEffectFactoryLoadStatus,
extended_error: Option<CompositionEffectFactoryError>,
}
impl CompositionEffectFactory {
fn new(compositor: Rc<Compositor>, effect: &GraphicsEffect, animatable_properties: &[&str]) -> Rc<Self> {
let (graph, load_status, extended_error) = match EffectGraph::load(effect, animatable_properties) {
Ok(graph) => (graph, CompositionEffectFactoryLoadStatus::Success, None),
Err((status, error)) => (EffectGraph::failed(), status, Some(error)),
};
Rc::new(Self { compositor, graph: Arc::new(graph), load_status, extended_error })
}
pub fn compositor(&self) -> &Rc<Compositor> {
&self.compositor
}
pub fn create_brush(&self) -> CompositionEffectBrush {
CompositionEffectBrush::new(&self.compositor, self.graph.clone())
}
pub fn load_status(&self) -> CompositionEffectFactoryLoadStatus {
self.load_status
}
pub fn extended_error(&self) -> Option<&CompositionEffectFactoryError> {
self.extended_error.as_ref()
}
}
impl Compositor {
pub fn create_effect_factory(&self, effect: impl Into<GraphicsEffect>) -> Rc<CompositionEffectFactory> {
self.create_effect_factory_with_properties(effect, &[])
}
pub fn create_effect_factory_with_properties(
&self,
effect: impl Into<GraphicsEffect>,
animatable_properties: &[&str],
) -> Rc<CompositionEffectFactory> {
CompositionEffectFactory::new(self.this_handle(), &effect.into(), animatable_properties)
}
pub fn create_backdrop_brush(&self) -> CompositionBackdropBrush {
CompositionBackdropBrush::new(&self.this_handle())
}
pub fn create_host_backdrop_brush(&self) -> CompositionHostBackdropBrush {
CompositionHostBackdropBrush::new(&self.this_handle())
}
}