forma_render/composition/layer.rs
1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{math::GeomPresTransform, styling::Props, utils::SmallBitSet, GeomId, Order, Path};
16
17use super::{Interned, LayerSharedState};
18
19/// Small, compact version of a [`Layer`] that implements [`Send`] and is used by the
20/// [`SegmentBuffer`].
21///
22/// This type should be as small as possible since it gets copied on use and thus
23/// should only contain information needed by the [`SegmentBuffer`].
24///
25/// [`SegmentBuffer`]: crate::segment::SegmentBuffer
26#[derive(Clone, Debug)]
27pub struct InnerLayer {
28 pub is_enabled: bool,
29 pub affine_transform: Option<GeomPresTransform>,
30 pub order: Option<Order>,
31}
32
33impl Default for InnerLayer {
34 fn default() -> Self {
35 Self {
36 is_enabled: true,
37 affine_transform: None,
38 order: None,
39 }
40 }
41}
42
43/// A layer is a *reusable* collection of geometry (i.e. [`Path`]s) with common properties and
44/// order in the paint stack.
45///
46/// They are created by calling [`Composition::create_layer`] or
47/// [`Composition::get_mut_or_insert_default`].
48///
49/// [`Composition::create_layer`]: crate::Composition::create_layer
50/// [`Composition::get_mut_or_insert_default`]: crate::Composition::get_mut_or_insert_default
51///
52/// # Examples
53///
54/// ```
55/// # use forma_render::prelude::*;
56/// let mut composition = Composition::new();
57///
58/// let _layer = composition.get_mut_or_insert_default(Order::new(0).unwrap());
59/// ```
60#[derive(Debug)]
61pub struct Layer {
62 pub(crate) inner: InnerLayer,
63 pub(crate) shared_state: LayerSharedState,
64 pub(crate) geom_id: GeomId,
65 pub(crate) props: Interned<Props>,
66 pub(crate) is_unchanged: SmallBitSet,
67 pub(crate) lines_count: usize,
68}
69
70impl Layer {
71 /// Inserts `path` into the geometry of the layer.
72 ///
73 /// The inserted paths basically contribute to a single internal path containing the geometry
74 /// of all the paths.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// # use forma_render::prelude::*;
80 /// let mut composition = Composition::new();
81 ///
82 /// let line0 = PathBuilder::new().line_to(Point::new(10.0, 10.0)).build();
83 /// let line1 = PathBuilder::new().line_to(Point::new(10.0, 0.0)).build();
84 ///
85 /// composition
86 /// .get_mut_or_insert_default(Order::new(0).unwrap())
87 /// .insert(&line0)
88 /// .insert(&line1);
89 /// ```
90 pub fn insert(&mut self, path: &Path) -> &mut Self {
91 {
92 let mut state = self.shared_state.inner();
93 let builder = state
94 .segment_buffer
95 .as_mut()
96 .expect("lines_builder should not be None");
97
98 let old_len = builder.len();
99 builder.push_path(self.geom_id, path);
100 let len = builder.len() - old_len;
101
102 state
103 .geom_id_to_order
104 .insert(self.geom_id, self.inner.order);
105
106 self.lines_count += len;
107 }
108
109 self.is_unchanged.clear();
110 self
111 }
112
113 /// Clears the geometry stored in the layer and resets its [geometry ID](Self::geom_id).
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// # use forma_render::prelude::*;
119 /// let mut composition = Composition::new();
120 ///
121 /// let mut layer = composition.create_layer();
122 ///
123 /// let initial_id = layer.geom_id();
124 ///
125 /// layer.clear();
126 ///
127 /// assert_ne!(layer.geom_id(), initial_id);
128 /// ```
129 pub fn clear(&mut self) -> &mut Self {
130 {
131 let mut state = self.shared_state.inner();
132
133 state.geom_id_to_order.remove(&self.geom_id);
134
135 self.geom_id = state.new_geom_id();
136 state
137 .geom_id_to_order
138 .insert(self.geom_id, self.inner.order);
139 }
140
141 self.lines_count = 0;
142
143 self.is_unchanged.clear();
144 self
145 }
146
147 pub(crate) fn set_order(&mut self, order: Option<Order>) {
148 if order.is_some() && self.inner.order != order {
149 self.inner.order = order;
150 self.is_unchanged.clear();
151 }
152
153 self.shared_state
154 .inner()
155 .geom_id_to_order
156 .insert(self.geom_id, order);
157 }
158
159 /// Returns the layer's geometry ID.
160 ///
161 /// Used to retrieve the layer's [`Order`] if stored in a [`Composition`](crate::Composition).
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// # use forma_render::prelude::*;
167 /// let mut composition = Composition::new();
168 ///
169 /// let order = Order::new(0).unwrap();
170 /// let layer = composition.get_mut_or_insert_default(order);
171 /// let id = layer.geom_id();
172 ///
173 /// assert_eq!(composition.get_order_if_stored(id), Some(order));
174 /// ```
175 pub fn geom_id(&self) -> GeomId {
176 self.geom_id
177 }
178
179 pub(crate) fn is_unchanged(&self, cache_id: u8) -> bool {
180 self.is_unchanged.contains(&cache_id)
181 }
182
183 pub(crate) fn set_is_unchanged(&mut self, cache_id: u8, is_unchanged: bool) -> bool {
184 if is_unchanged {
185 self.is_unchanged.insert(cache_id)
186 } else {
187 self.is_unchanged.remove(cache_id)
188 }
189 }
190
191 /// Returns `true` if the layer is enabled.
192 ///
193 /// # Examples
194 ///
195 /// ```
196 /// # use forma_render::prelude::*;
197 /// let mut composition = Composition::new();
198 ///
199 /// let layer = composition.create_layer();
200 ///
201 /// assert!(layer.is_enabled());
202 /// ```
203 #[inline]
204 pub fn is_enabled(&self) -> bool {
205 self.inner.is_enabled
206 }
207
208 /// Sets the layer's enabled state.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// # use forma_render::prelude::*;
214 /// let mut composition = Composition::new();
215 ///
216 /// let mut layer = composition.create_layer();
217 ///
218 /// layer.set_is_enabled(false);
219 ///
220 /// assert!(!layer.is_enabled());
221 /// ```
222 #[inline]
223 pub fn set_is_enabled(&mut self, is_enabled: bool) -> &mut Self {
224 self.inner.is_enabled = is_enabled;
225 self
226 }
227
228 /// Disables the layer.
229 ///
230 /// # Examples
231 ///
232 /// ```
233 /// # use forma_render::prelude::*;
234 /// let mut composition = Composition::new();
235 ///
236 /// let mut layer = composition.create_layer();
237 ///
238 /// layer.disable();
239 ///
240 /// assert!(!layer.is_enabled());
241 /// ```
242 #[inline]
243 pub fn disable(&mut self) -> &mut Self {
244 self.set_is_enabled(false)
245 }
246
247 /// Enables the layer.
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// # use forma_render::prelude::*;
253 /// let mut composition = Composition::new();
254 ///
255 /// let mut layer = composition.create_layer();
256 ///
257 /// layer.disable();
258 /// layer.enable();
259 ///
260 /// assert!(layer.is_enabled());
261 /// ```
262 #[inline]
263 pub fn enable(&mut self) -> &mut Self {
264 self.set_is_enabled(true)
265 }
266
267 /// Returns the layer's transform.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// # use forma_render::prelude::*;
273 /// let mut composition = Composition::new();
274 ///
275 /// let layer = composition.create_layer();
276 ///
277 /// assert!(layer.transform().is_identity());
278 /// ```
279 #[inline]
280 pub fn transform(&self) -> GeomPresTransform {
281 self.inner.affine_transform.unwrap_or_default()
282 }
283
284 /// Sets the layer's transform.
285 ///
286 /// # Examples
287 ///
288 /// ```
289 /// # use forma_render::prelude::*;
290 /// let mut composition = Composition::new();
291 ///
292 /// let mut layer = composition.create_layer();
293 ///
294 /// layer.set_transform(AffineTransform::from([1.0, 0.0, 0.0, 1.0, 1.0, 0.0]).try_into().unwrap());
295 /// ```
296 #[inline]
297 pub fn set_transform(&mut self, transform: GeomPresTransform) -> &mut Self {
298 // We want to perform a cheap check for the common case without hampering this function too
299 // much.
300 #[allow(clippy::float_cmp)]
301 let affine_transform = (!transform.is_identity()).then_some(transform);
302
303 if self.inner.affine_transform != affine_transform {
304 self.is_unchanged.clear();
305 self.inner.affine_transform = affine_transform;
306 }
307
308 self
309 }
310
311 /// Returns the layer's properties.
312 ///
313 /// # Examples
314 ///
315 /// ```
316 /// # use forma_render::prelude::*;
317 /// let mut composition = Composition::new();
318 ///
319 /// let layer = composition.create_layer();
320 ///
321 /// assert_eq!(layer.props().fill_rule, FillRule::NonZero);
322 /// ```
323 #[inline]
324 pub fn props(&self) -> &Props {
325 &self.props
326 }
327
328 /// Sets the layer's properties.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// # use forma_render::prelude::*;
334 /// let mut composition = Composition::new();
335 ///
336 /// let mut layer = composition.create_layer();
337 ///
338 /// layer.set_props(Props {
339 /// fill_rule: FillRule::EvenOdd,
340 /// ..Default::default()
341 /// });
342 /// ```
343 #[inline]
344 pub fn set_props(&mut self, props: Props) -> &mut Self {
345 if *self.props != props {
346 self.is_unchanged.clear();
347 self.props = self.shared_state.inner().props_interner.get(props);
348 }
349
350 self
351 }
352}
353
354impl Drop for Layer {
355 fn drop(&mut self) {
356 self.shared_state
357 .inner()
358 .geom_id_to_order
359 .remove(&self.geom_id);
360 }
361}