Skip to main content

ferroui_base/media/immutable/
immutable_tile_brush.rs

1use crate::media::immutable::ImmutableTransform;
2use crate::media::{AlignmentX, AlignmentY, ITileBrush, ITransform, Stretch, TileMode, TransformExtensions};
3use crate::{RelativePoint, RelativeRect};
4use std::rc::Rc;
5
6/// The data shared by all immutable tile brushes.
7#[derive(Clone)]
8pub struct ImmutableTileBrush {
9    alignment_x: AlignmentX,
10    alignment_y: AlignmentY,
11    destination_rect: RelativeRect,
12    opacity: f64,
13    transform: Option<Rc<dyn ITransform>>,
14    transform_origin: RelativePoint,
15    source_rect: RelativeRect,
16    stretch: Stretch,
17    tile_mode: TileMode,
18    relative_transform: Option<Rc<dyn ITransform>>,
19    /// The form sent to the render thread, created on first use.
20    pub(crate) shared: std::sync::OnceLock<Option<crate::media::SharedBrush>>,
21}
22
23impl ImmutableTileBrush {
24    /// Creates the tile brush data.
25    #[allow(clippy::too_many_arguments)]
26    pub fn new(
27        alignment_x: AlignmentX,
28        alignment_y: AlignmentY,
29        destination_rect: RelativeRect,
30        opacity: f64,
31        transform: Option<Rc<ImmutableTransform>>,
32        transform_origin: RelativePoint,
33        source_rect: RelativeRect,
34        stretch: Stretch,
35        tile_mode: TileMode,
36        relative_transform: Option<Rc<ImmutableTransform>>,
37    ) -> Self {
38        Self {
39            alignment_x,
40            alignment_y,
41            destination_rect,
42            opacity,
43            transform: transform.map(|t| t as Rc<dyn ITransform>),
44            transform_origin,
45            source_rect,
46            stretch,
47            tile_mode,
48            relative_transform: relative_transform.map(|t| t as Rc<dyn ITransform>),
49            shared: std::sync::OnceLock::new(),
50        }
51    }
52
53    /// Creates an immutable copy of the tile brush data of `source`.
54    pub fn from_brush(source: &dyn ITileBrush) -> Self {
55        Self::new(
56            source.alignment_x(),
57            source.alignment_y(),
58            source.destination_rect(),
59            source.opacity(),
60            source.transform().map(|t| Rc::new(TransformExtensions::to_immutable(&*t))),
61            source.transform_origin(),
62            source.source_rect(),
63            source.stretch(),
64            source.tile_mode(),
65            source.relative_transform().map(|t| Rc::new(TransformExtensions::to_immutable(&*t))),
66        )
67    }
68
69    /// The horizontal alignment of a tile in the destination.
70    #[inline]
71    pub fn alignment_x(&self) -> AlignmentX {
72        self.alignment_x
73    }
74
75    /// The vertical alignment of a tile in the destination.
76    #[inline]
77    pub fn alignment_y(&self) -> AlignmentY {
78        self.alignment_y
79    }
80
81    /// The rectangle on the destination in which to paint a tile.
82    #[inline]
83    pub fn destination_rect(&self) -> RelativeRect {
84        self.destination_rect
85    }
86
87    /// The opacity of the brush.
88    #[inline]
89    pub fn opacity(&self) -> f64 {
90        self.opacity
91    }
92
93    /// The transform of the brush.
94    #[inline]
95    pub fn transform(&self) -> Option<Rc<dyn ITransform>> {
96        self.transform.clone()
97    }
98
99    /// The transform origin of the brush.
100    #[inline]
101    pub fn transform_origin(&self) -> RelativePoint {
102        self.transform_origin
103    }
104
105    /// The rectangle of the source image that will be displayed.
106    #[inline]
107    pub fn source_rect(&self) -> RelativeRect {
108        self.source_rect
109    }
110
111    /// A value controlling how the source rectangle will be stretched to
112    /// fill the destination rect.
113    #[inline]
114    pub fn stretch(&self) -> Stretch {
115        self.stretch
116    }
117
118    /// The brush's tile mode.
119    #[inline]
120    pub fn tile_mode(&self) -> TileMode {
121        self.tile_mode
122    }
123
124    /// The transform of the brush, relative to the bounds of the painted
125    /// area.
126    #[inline]
127    pub fn relative_transform(&self) -> Option<Rc<dyn ITransform>> {
128        self.relative_transform.clone()
129    }
130}
131
132/// Implements the brush interfaces of an immutable tile brush whose `base`
133/// field is an [`ImmutableTileBrush`]. The optional trailing tokens are
134/// further `IBrush` members (interface casts of the deriving type).
135macro_rules! immutable_tile_brush_interfaces {
136    ($name:ty $(, { $($extra:tt)* })?) => {
137        impl ::std::ops::Deref for $name {
138            type Target = $crate::media::immutable::ImmutableTileBrush;
139            #[inline]
140            fn deref(&self) -> &Self::Target {
141                &self.base
142            }
143        }
144
145        impl $crate::media::IBrush for $name {
146            #[inline]
147            fn opacity(&self) -> f64 {
148                self.base.opacity()
149            }
150
151            fn transform(&self) -> Option<::std::rc::Rc<dyn $crate::media::ITransform>> {
152                self.base.transform()
153            }
154
155            #[inline]
156            fn transform_origin(&self) -> $crate::RelativePoint {
157                self.base.transform_origin()
158            }
159
160            fn relative_transform(&self) -> Option<::std::rc::Rc<dyn $crate::media::ITransform>> {
161                self.base.relative_transform()
162            }
163
164            fn as_immutable_brush(&self) -> Option<&dyn $crate::media::IImmutableBrush> {
165                Some(self)
166            }
167
168            fn as_any(&self) -> &dyn ::std::any::Any {
169                self
170            }
171
172            fn as_tile_brush(&self) -> Option<&dyn $crate::media::ITileBrush> {
173                Some(self)
174            }
175
176            fn into_immutable_brush(
177                self: ::std::rc::Rc<Self>,
178            ) -> Option<::std::rc::Rc<dyn $crate::media::IImmutableBrush>> {
179                Some(self)
180            }
181
182            fn to_shared(&self) -> Option<$crate::media::SharedBrush> {
183                self.base.shared.get_or_init(|| $crate::media::SharedBrush::from_brush(self)).clone()
184            }
185
186            $($($extra)*)?
187        }
188
189        impl $crate::media::ITileBrush for $name {
190            #[inline]
191            fn alignment_x(&self) -> $crate::media::AlignmentX {
192                self.base.alignment_x()
193            }
194
195            #[inline]
196            fn alignment_y(&self) -> $crate::media::AlignmentY {
197                self.base.alignment_y()
198            }
199
200            #[inline]
201            fn destination_rect(&self) -> $crate::RelativeRect {
202                self.base.destination_rect()
203            }
204
205            #[inline]
206            fn source_rect(&self) -> $crate::RelativeRect {
207                self.base.source_rect()
208            }
209
210            #[inline]
211            fn stretch(&self) -> $crate::media::Stretch {
212                self.base.stretch()
213            }
214
215            #[inline]
216            fn tile_mode(&self) -> $crate::media::TileMode {
217                self.base.tile_mode()
218            }
219        }
220
221        impl $crate::media::IImmutableBrush for $name {}
222    };
223}
224
225pub(crate) use immutable_tile_brush_interfaces;