ferroui_base/rendering/composition/server/server_composition_visual/
computed_properties.rs1use super::ServerCompositionVisual;
2use crate::platform::LtrbRect;
3use crate::rendering::composition::MatrixUtils;
4use crate::Matrix;
5
6impl ServerCompositionVisual {
7 pub fn own_transform(&self) -> Option<Matrix> {
8 self.own_transform.get()
9 }
10
11 pub fn sub_tree_bounds(&self) -> Option<LtrbRect> {
12 self.sub_tree_bounds.get()
13 }
14
15 pub fn transformed_sub_tree_bounds(&self) -> Option<LtrbRect> {
16 self.transformed_sub_tree_bounds.get()
17 }
18
19 pub fn compute_own_content_bounds(&self) -> Option<LtrbRect> {
20 self.content.compute_own_content_bounds(self)
21 }
22
23 pub fn combined_transform_matrix(&self) -> Matrix {
24 self.combined_transform_matrix.get()
25 }
26
27 pub(super) fn propagate_flags(
57 &self,
58 needs_bounding_box_update: bool,
59 dirty_for_render: bool,
60 additional_dirty_region: bool,
61 ) {
62 if let Some(root) = self.root() {
63 root.request_update();
64 }
65
66 let mut parent = self.parent();
67 let set_is_dirty_for_render_in_subgraph = additional_dirty_region || dirty_for_render;
68 while let Some(p) = parent {
69 if !((needs_bounding_box_update && !p.needs_bounding_box_update.get())
70 || (set_is_dirty_for_render_in_subgraph && !p.is_dirty_for_render_in_subgraph.get()))
71 {
72 break;
73 }
74 p.needs_bounding_box_update.set(p.needs_bounding_box_update.get() | needs_bounding_box_update);
75 p.is_dirty_for_render_in_subgraph
76 .set(p.is_dirty_for_render_in_subgraph.get() | set_is_dirty_for_render_in_subgraph);
77 parent = p.parent();
78 }
79
80 self.needs_bounding_box_update.set(self.needs_bounding_box_update.get() | needs_bounding_box_update);
81 self.is_dirty_for_render.set(self.is_dirty_for_render.get() | dirty_for_render);
82
83 self.needs_to_add_extra_dirty_rect_to_dirty_region.set(
85 !dirty_for_render && (self.needs_to_add_extra_dirty_rect_to_dirty_region.get() || additional_dirty_region),
86 );
87 }
88
89 pub fn recompute_own_properties(&self) {
90 let mut set_dirty_bounds = self.content_changed.get() || self.delay_propagate_needs_bounds_update.get();
91 let mut set_dirty_for_render = self.content_changed.get() || self.delay_propagate_is_dirty_for_render.get();
92 let set_has_extra_dirty_rect = self.delay_propagate_has_extra_dirty_rects.get();
93
94 self.delay_propagate_is_dirty_for_render.set(false);
96 self.delay_propagate_has_extra_dirty_rects.set(false);
97
98 self.enqueued_for_own_properties_recompute.set(false);
99 if self.own_bounds_dirty.get() {
100 self.own_content_bounds
101 .set(self.compute_own_content_bounds().and_then(LtrbRect::null_if_zero_size));
102 set_dirty_for_render = true;
103 set_dirty_bounds = true;
104 }
105
106 if self.clip_size_dirty.get() {
107 let mut clip: Option<LtrbRect> = None;
108 if let Some(geometry) = self.clip() {
109 clip = Some(LtrbRect::from_rect(geometry.bounds()));
110 }
111 if self.clip_to_bounds() {
112 let size = self.size();
113 let bounds = LtrbRect::new(0.0, 0.0, size.x, size.y);
114 clip = Some(match clip {
115 Some(clip) => clip.intersect_or_empty(bounds),
116 None => bounds,
117 });
118 }
119
120 if self.own_clip_rect.get() != clip {
121 self.own_clip_rect.set(clip);
122 set_dirty_for_render = true;
123 set_dirty_bounds = true;
124 }
125 }
126
127 if self.combined_transform_dirty.get() {
128 self.own_transform.set(MatrixUtils::compute_transform(
129 self.size(),
130 self.anchor_point(),
131 self.center_point(),
132 self.transform_matrix(),
133 self.scale(),
134 self.rotation_angle(),
135 self.orientation(),
136 self.offset() + self.translation(),
137 ));
138
139 set_dirty_for_render = true;
140 set_dirty_bounds = true;
141
142 self.att_helper_combined_transform_changed();
143 }
144
145 set_dirty_for_render |= self.composition_fields_dirty.get();
146
147 self.own_bounds_dirty.set(false);
148 self.clip_size_dirty.set(false);
149 self.combined_transform_dirty.set(false);
150 self.composition_fields_dirty.set(false);
151 self.propagate_flags(set_dirty_bounds, set_dirty_for_render, set_has_extra_dirty_rect);
152 }
153}