Skip to main content

ferroui_base/rendering/composition/drawing/
immediate_render_data_scene_brush_content.rs

1use super::{RenderDataStream, ServerCompositionRenderData};
2use crate::media::{IBrush, IImmutableBrush, ISceneBrushContent, ITileBrush, ITransform};
3use crate::platform::IDrawingContextImpl;
4use crate::{Matrix, Rect, RelativePoint};
5use std::any::Any;
6use std::cell::RefCell;
7use std::rc::Rc;
8
9/// The content of a scene brush recorded without a compositor: a render
10/// data stream that refers to the drawn objects directly and is replayed on
11/// the thread that recorded it.
12pub struct ImmediateRenderDataSceneBrushContent {
13    stream: RefCell<Option<RenderDataStream>>,
14    brush: Rc<dyn ITileBrush>,
15    rect: Rect,
16    use_scalable_rasterization: bool,
17}
18
19impl ImmediateRenderDataSceneBrushContent {
20    /// Creates the content of `brush` from a recorded stream. Without an
21    /// explicit `rect` the bounds of the content are the bounds of what the
22    /// stream draws, rounded outwards to whole units.
23    pub fn new(
24        brush: Rc<dyn ITileBrush>,
25        stream: RenderDataStream,
26        rect: Option<Rect>,
27        use_scalable_rasterization: bool,
28    ) -> Self {
29        let rect = rect
30            .or_else(|| ServerCompositionRenderData::apply_render_bounds_rounding_rect(stream.calculate_bounds()))
31            .unwrap_or_default();
32        Self { stream: RefCell::new(Some(stream)), brush, rect, use_scalable_rasterization }
33    }
34
35    fn render_stream(&self, context: &mut dyn IDrawingContextImpl) {
36        if let Some(stream) = self.stream.borrow().as_ref() {
37            stream.replay(context);
38        }
39    }
40
41    /// Runs `f` on the recorded stream; `None` once the content has been
42    /// disposed.
43    #[cfg(test)]
44    pub(crate) fn with_stream<R>(&self, f: impl FnOnce(&RenderDataStream) -> R) -> Option<R> {
45        self.stream.borrow().as_ref().map(f)
46    }
47}
48
49impl IBrush for ImmediateRenderDataSceneBrushContent {
50    fn as_immutable_brush(&self) -> Option<&dyn IImmutableBrush> {
51        Some(self)
52    }
53
54    fn opacity(&self) -> f64 {
55        self.brush.opacity()
56    }
57
58    fn transform(&self) -> Option<Rc<dyn ITransform>> {
59        self.brush.transform()
60    }
61
62    fn transform_origin(&self) -> RelativePoint {
63        self.brush.transform_origin()
64    }
65
66    fn relative_transform(&self) -> Option<Rc<dyn ITransform>> {
67        self.brush.relative_transform()
68    }
69
70    fn as_any(&self) -> &dyn Any {
71        self
72    }
73
74    fn into_immutable_brush(self: Rc<Self>) -> Option<Rc<dyn IImmutableBrush>> {
75        Some(self)
76    }
77}
78
79impl IImmutableBrush for ImmediateRenderDataSceneBrushContent {}
80
81impl ISceneBrushContent for ImmediateRenderDataSceneBrushContent {
82    fn brush(&self) -> Rc<dyn ITileBrush> {
83        self.brush.clone()
84    }
85
86    fn rect(&self) -> Rect {
87        self.rect
88    }
89
90    fn render(&self, context: &mut dyn IDrawingContextImpl, transform: Option<Matrix>) {
91        match transform {
92            Some(transform) => {
93                let old_transform = context.transform();
94                context.set_transform(transform * old_transform);
95                self.render_stream(context);
96                context.set_transform(old_transform);
97            }
98            None => self.render_stream(context),
99        }
100    }
101
102    fn use_scalable_rasterization(&self) -> bool {
103        self.use_scalable_rasterization
104    }
105
106    fn dispose(&self) {
107        let Some(mut stream) = self.stream.borrow_mut().take() else { return };
108        stream.dispose_resources();
109        stream.dispose();
110    }
111}