cranpose_render_common/
layer_composition.rs1use cranpose_ui_graphics::{BlendMode, CompositingStrategy, GraphicsLayer, RenderEffect};
2
3#[derive(Clone)]
4pub struct LayerIsolation {
5 pub effect: Option<RenderEffect>,
6 pub blend_mode: BlendMode,
7 pub composite_alpha: f32,
8}
9
10pub fn layer_requires_isolation(layer: &GraphicsLayer) -> bool {
11 let has_effect = layer.render_effect.is_some();
12 let has_layer_blend = layer.blend_mode != BlendMode::SrcOver;
13 match layer.compositing_strategy {
14 CompositingStrategy::Offscreen => true,
15 CompositingStrategy::Auto => has_effect || has_layer_blend || layer.alpha < 1.0,
16 CompositingStrategy::ModulateAlpha => has_effect || has_layer_blend,
17 }
18}
19
20fn isolation_composite_alpha(layer: &GraphicsLayer) -> f32 {
21 if layer.compositing_strategy == CompositingStrategy::ModulateAlpha {
22 1.0
23 } else {
24 GraphicsLayer::composite_alpha_8bit(layer.alpha)
25 }
26}
27
28fn folded_layer_alpha(layer: &GraphicsLayer) -> f32 {
29 if layer.compositing_strategy != CompositingStrategy::ModulateAlpha
30 && layer_requires_isolation(layer)
31 {
32 GraphicsLayer::composite_alpha_8bit(layer.alpha)
33 } else {
34 layer.alpha
35 }
36}
37
38pub fn effective_layer_isolation(layer: &GraphicsLayer) -> Option<LayerIsolation> {
39 layer_requires_isolation(layer).then(|| LayerIsolation {
40 effect: layer.render_effect.clone(),
41 blend_mode: layer.blend_mode,
42 composite_alpha: isolation_composite_alpha(layer),
43 })
44}
45
46pub fn layer_composite_params(layer: &GraphicsLayer) -> Option<(f32, BlendMode)> {
50 layer_requires_isolation(layer).then(|| (isolation_composite_alpha(layer), layer.blend_mode))
51}
52
53pub fn layer_for_content(
54 layer: &GraphicsLayer,
55 isolation: Option<&LayerIsolation>,
56) -> GraphicsLayer {
57 let mut content = layer.clone();
58 if isolation.is_some() && layer.compositing_strategy != CompositingStrategy::ModulateAlpha {
59 content.alpha = 1.0;
60 }
61 content
62}
63
64pub fn local_content_layer(layer: &GraphicsLayer) -> GraphicsLayer {
65 GraphicsLayer {
66 alpha: folded_layer_alpha(layer),
67 color_filter: layer.color_filter,
68 ..GraphicsLayer::default()
69 }
70}
71
72pub fn local_content_layer_for(layer: &GraphicsLayer) -> GraphicsLayer {
78 let alpha = if layer.compositing_strategy != CompositingStrategy::ModulateAlpha
79 && layer_requires_isolation(layer)
80 {
81 1.0
82 } else {
83 layer.alpha
84 };
85 GraphicsLayer {
86 alpha,
87 color_filter: layer.color_filter,
88 ..GraphicsLayer::default()
89 }
90}
91
92#[cfg(test)]
93#[path = "tests/layer_composition_tests.rs"]
94mod tests;