ferroui_base/rendering/composition/server/
server_composition_surface_visual.rs1use super::{IServerCompositionSurface, IServerVisualContent, ServerCompositionTarget, ServerCompositionVisual, ServerSizeDependantVisual, ServerVisualRenderContext};
2use crate::platform::LtrbRect;
3use crate::rendering::composition::generated::{
4 ServerCompositionSurfaceVisualHooks, ServerCompositionSurfaceVisualProps,
5};
6use crate::rendering::composition::transport::BatchStreamReader;
7use crate::{Rect, Size};
8use std::any::{Any, TypeId};
9use std::rc::Rc;
10use std::time::Duration;
11
12#[derive(Default)]
14pub struct ServerCompositionSurfaceVisual {
15 props: ServerCompositionSurfaceVisualProps,
16}
17
18impl ServerCompositionSurfaceVisual {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn surface(&self) -> Option<Rc<dyn IServerCompositionSurface>> {
24 self.props.surface().and_then(|surface| surface.as_surface())
25 }
26
27 fn subscribe(&self, visual: &ServerCompositionVisual) {
28 if let Some(surface) = self.surface() {
29 let weak = visual.weak();
30 surface.changed().add(
31 weak.as_ptr() as usize,
32 Rc::new(move || {
33 if let Some(visual) = weak.upgrade() {
35 visual.invalidate_content();
36 }
37 }),
38 );
39 }
40 }
41
42 fn unsubscribe(&self, visual: &ServerCompositionVisual) {
43 if let Some(surface) = self.surface() {
44 surface.changed().remove(visual.weak().as_ptr() as usize);
45 }
46 }
47}
48
49impl ServerCompositionSurfaceVisualHooks for ServerCompositionVisual {
50 fn base_deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration) {
51 ServerCompositionVisual::base_deserialize_changes_core(self, reader, committed_at);
52 }
53
54 fn on_surface_changed(&self) {
55 if let Some(content) = self.content_as::<ServerCompositionSurfaceVisual>() {
56 content.subscribe(self);
57 }
58 }
59
60 fn on_surface_changing(&self) {
61 if let Some(content) = self.content_as::<ServerCompositionSurfaceVisual>() {
62 content.unsubscribe(self);
63 }
64 }
65}
66
67impl IServerVisualContent for ServerCompositionSurfaceVisual {
68 fn deserialize_changes_core(
69 &self,
70 visual: &ServerCompositionVisual,
71 reader: &mut BatchStreamReader<'_>,
72 committed_at: Duration,
73 ) {
74 self.props.deserialize_changes_core(visual, reader, committed_at);
75 }
76
77 fn compute_own_content_bounds(&self, visual: &ServerCompositionVisual) -> Option<LtrbRect> {
78 ServerSizeDependantVisual::compute_own_content_bounds(visual)
79 }
80
81 fn size_changed(&self, visual: &ServerCompositionVisual) {
82 ServerSizeDependantVisual::size_changed(visual);
83 }
84
85 fn render_core(
86 &self,
87 visual: &ServerCompositionVisual,
88 context: &mut ServerVisualRenderContext<'_>,
89 _current_transformed_clip: LtrbRect,
90 ) {
91 let Some(surface) = self.surface() else { return };
92 let Some(bmp) = surface.bitmap() else { return };
93
94 let size = visual.size();
96 context.canvas().draw_bitmap(
97 &*bmp,
98 1.0,
99 Rect::from_size(bmp.pixel_size().to_size(1.0)),
100 Rect::from_size(Size::new(size.x, size.y)),
101 );
102 }
103
104 fn on_attached_to_root(&self, visual: &ServerCompositionVisual, _target: &Rc<ServerCompositionTarget>) {
105 self.subscribe(visual);
106 }
107
108 fn on_detached_from_root(&self, visual: &ServerCompositionVisual, _target: &Rc<ServerCompositionTarget>) {
109 self.unsubscribe(visual);
110 }
111
112 fn dispose(&self, visual: &ServerCompositionVisual) {
113 self.unsubscribe(visual);
114 }
115
116 fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
117 self.props.find_props(type_id)
118 }
119
120 fn as_any(&self) -> &dyn Any {
121 self
122 }
123}