cranpose_render_common/
layer_composition.rs1use std::borrow::Cow;
2
3use cranpose_ui_graphics::{BlendMode, CompositingStrategy, GraphicsLayer, RenderEffect};
4
5#[derive(Clone)]
7pub struct LayerIsolation {
8 pub effect: Option<RenderEffect>,
10 pub blend_mode: BlendMode,
12 pub composite_alpha: f32,
15}
16
17#[inline]
20pub fn layer_requires_isolation(layer: &GraphicsLayer) -> bool {
21 let has_effect = layer.render_effect.is_some();
22 let has_layer_blend = layer.blend_mode != BlendMode::SrcOver;
23 match layer.compositing_strategy {
24 CompositingStrategy::Offscreen => true,
25 CompositingStrategy::Auto => has_effect || has_layer_blend || layer.alpha < 1.0,
26 CompositingStrategy::ModulateAlpha => has_effect || has_layer_blend,
27 }
28}
29
30fn isolation_composite_alpha(layer: &GraphicsLayer) -> f32 {
31 if layer.compositing_strategy == CompositingStrategy::ModulateAlpha {
32 1.0
33 } else {
34 GraphicsLayer::composite_alpha_8bit(layer.alpha)
35 }
36}
37
38pub fn folded_layer_alpha(layer: &GraphicsLayer) -> f32 {
41 if layer.compositing_strategy != CompositingStrategy::ModulateAlpha
42 && layer_requires_isolation(layer)
43 {
44 GraphicsLayer::composite_alpha_8bit(layer.alpha)
45 } else {
46 layer.alpha
47 }
48}
49
50pub fn effective_layer_isolation(layer: &GraphicsLayer) -> Option<LayerIsolation> {
53 layer_requires_isolation(layer).then(|| LayerIsolation {
54 effect: layer.render_effect.clone(),
55 blend_mode: layer.blend_mode,
56 composite_alpha: isolation_composite_alpha(layer),
57 })
58}
59
60#[inline]
64pub fn layer_composite_params(layer: &GraphicsLayer) -> Option<(f32, BlendMode)> {
65 layer_requires_isolation(layer).then(|| (isolation_composite_alpha(layer), layer.blend_mode))
66}
67
68pub fn layer_for_content(
71 layer: &GraphicsLayer,
72 isolation: Option<&LayerIsolation>,
73) -> GraphicsLayer {
74 let mut content = layer.clone();
75 if isolation.is_some() && layer.compositing_strategy != CompositingStrategy::ModulateAlpha {
76 content.alpha = 1.0;
77 }
78 content
79}
80
81#[inline]
89pub fn local_content_layer_for(layer: &GraphicsLayer) -> Cow<'static, GraphicsLayer> {
90 let alpha = if layer.compositing_strategy != CompositingStrategy::ModulateAlpha
91 && layer_requires_isolation(layer)
92 {
93 1.0
94 } else {
95 layer.alpha
96 };
97 if alpha == 1.0 && layer.color_filter.is_none() {
98 return Cow::Borrowed(&GraphicsLayer::DEFAULT);
99 }
100 Cow::Owned(GraphicsLayer {
101 alpha,
102 color_filter: layer.color_filter.clone(),
103 ..GraphicsLayer::default()
104 })
105}
106
107#[cfg(test)]
108#[path = "tests/layer_composition_tests.rs"]
109mod tests;