Skip to main content

ferroui_base/rendering/composition/drawing/
composition_render_data_scene_brush_content.rs

1use super::ServerCompositionRenderData;
2use crate::media::{IBrush, IImmutableBrush, ISceneBrushContent, ITileBrush, ITransform};
3use crate::platform::IDrawingContextImpl;
4use crate::rendering::composition::server::{ServerCompositor, ServerObjectId};
5use crate::rendering::composition::transport::{BatchStreamReader, BatchStreamWriter};
6use crate::{Matrix, Rect, RelativePoint};
7use std::any::Any;
8use std::rc::Rc;
9
10/// What a scene brush sends to its server-side counterpart: the render data
11/// its content was recorded into, the bounds of the content (`None`: the
12/// bounds of what was drawn) and how the content is rasterized.
13#[derive(Clone)]
14pub struct CompositionRenderDataSceneBrushContentProperties {
15    pub render_data: Rc<ServerCompositionRenderData>,
16    pub rect: Option<Rect>,
17    pub use_scalable_rasterization: bool,
18}
19
20impl CompositionRenderDataSceneBrushContentProperties {
21    pub fn new(render_data: Rc<ServerCompositionRenderData>, rect: Option<Rect>, use_scalable_rasterization: bool) -> Self {
22        Self { render_data, rect, use_scalable_rasterization }
23    }
24
25    /// Writes the properties (or their absence) on the UI thread, where the
26    /// render data is known by the id of its server object.
27    pub fn serialize(writer: &mut BatchStreamWriter<'_>, properties: Option<(ServerObjectId, Option<Rect>, bool)>) {
28        match properties {
29            Some((render_data, rect, use_scalable_rasterization)) => {
30                writer.write_server_object(Some(render_data));
31                writer.write(rect);
32                writer.write(use_scalable_rasterization);
33            }
34            None => writer.write_server_object(None),
35        }
36    }
37
38    /// Reads what [`serialize`](Self::serialize) wrote, on the server.
39    ///
40    /// A scene brush creates the render data before its changes are
41    /// written, so the render data exists when they are read. Should it not
42    /// (or the compositor be gone), there are no properties: a brush
43    /// without content is valid and draws nothing.
44    pub fn deserialize(reader: &mut BatchStreamReader<'_>, compositor: Option<&Rc<ServerCompositor>>) -> Option<Self> {
45        let id = reader.read_server_object()?;
46        let rect = reader.read::<Option<Rect>>();
47        let use_scalable_rasterization = reader.read::<bool>();
48        let render_data = compositor?.get::<ServerCompositionRenderData>(id)?;
49        Some(Self { render_data, rect, use_scalable_rasterization })
50    }
51}
52
53/// The content of a scene brush on the server: the render data the UI
54/// thread recorded for it.
55pub struct CompositionRenderDataSceneBrushContent {
56    render_data: Rc<ServerCompositionRenderData>,
57    rect: Option<Rect>,
58    brush: Rc<dyn ITileBrush>,
59    use_scalable_rasterization: bool,
60}
61
62impl CompositionRenderDataSceneBrushContent {
63    pub fn new(brush: Rc<dyn ITileBrush>, properties: &CompositionRenderDataSceneBrushContentProperties) -> Self {
64        Self {
65            brush,
66            rect: properties.rect,
67            use_scalable_rasterization: properties.use_scalable_rasterization,
68            render_data: properties.render_data.clone(),
69        }
70    }
71
72    /// The render data that is replayed.
73    pub fn render_data(&self) -> &Rc<ServerCompositionRenderData> {
74        &self.render_data
75    }
76}
77
78impl IBrush for CompositionRenderDataSceneBrushContent {
79    fn as_immutable_brush(&self) -> Option<&dyn IImmutableBrush> {
80        Some(self)
81    }
82
83    fn opacity(&self) -> f64 {
84        self.brush.opacity()
85    }
86
87    fn transform(&self) -> Option<Rc<dyn ITransform>> {
88        self.brush.transform()
89    }
90
91    fn transform_origin(&self) -> RelativePoint {
92        self.brush.transform_origin()
93    }
94
95    fn relative_transform(&self) -> Option<Rc<dyn ITransform>> {
96        self.brush.relative_transform()
97    }
98
99    fn as_any(&self) -> &dyn Any {
100        self
101    }
102
103    fn into_immutable_brush(self: Rc<Self>) -> Option<Rc<dyn IImmutableBrush>> {
104        Some(self)
105    }
106}
107
108impl IImmutableBrush for CompositionRenderDataSceneBrushContent {}
109
110impl ISceneBrushContent for CompositionRenderDataSceneBrushContent {
111    fn brush(&self) -> Rc<dyn ITileBrush> {
112        self.brush.clone()
113    }
114
115    fn rect(&self) -> Rect {
116        self.rect.unwrap_or_else(|| self.render_data.bounds().map(|bounds| bounds.to_rect()).unwrap_or_default())
117    }
118
119    fn render(&self, context: &mut dyn IDrawingContextImpl, transform: Option<Matrix>) {
120        match transform {
121            Some(transform) => {
122                let old_transform = context.transform();
123                context.set_transform(transform * old_transform);
124                self.render_data.render(context);
125                context.set_transform(old_transform);
126            }
127            None => self.render_data.render(context),
128        }
129    }
130
131    fn use_scalable_rasterization(&self) -> bool {
132        self.use_scalable_rasterization
133    }
134
135    fn dispose(&self) {
136        // No-op on server
137    }
138}