forma_render/composition/
mod.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 std::{cell::RefCell, rc::Rc};
16
17use rustc_hash::FxHashMap;
18
19use crate::{segment::GeomId, styling::Props, utils::SmallBitSet, Order};
20
21mod interner;
22mod layer;
23mod state;
24
25pub use self::{
26    interner::{Interned, Interner},
27    layer::{InnerLayer, Layer},
28    state::{LayerSharedState, LayerSharedStateInner},
29};
30
31const LINES_GARBAGE_THRESHOLD: usize = 2;
32
33/// A composition is an ordered collection of [`Layer`]s. It is the only means through which
34/// content can be rendered.
35///
36/// The composition works similarly to a `HashMap<Order, Layer>`.
37///
38/// # Examples
39///
40/// ```
41/// # use forma_render::prelude::*;
42/// let mut composition = Composition::new();
43///
44/// let layer0 = composition.create_layer();
45/// let layer1 = composition.create_layer();
46///
47/// assert!(composition.insert(Order::new(0).unwrap(), layer0).is_none());
48/// assert!(composition.insert(Order::new(0).unwrap(), layer1).is_some()); // Some(layer0)
49/// ```
50#[derive(Debug, Default)]
51pub struct Composition {
52    pub(crate) layers: FxHashMap<Order, Layer>,
53    pub(crate) shared_state: Rc<RefCell<LayerSharedStateInner>>,
54}
55
56impl Composition {
57    /// Creates a new composition.
58    ///
59    /// # Examples
60    ///
61    /// ```
62    /// # use forma_render::prelude::*;
63    /// let composition = Composition::new();
64    ///
65    /// assert!(composition.is_empty());
66    /// ```
67    #[inline]
68    pub fn new() -> Self {
69        Self::default()
70    }
71
72    /// Creates a new [`Layer`] which is [enabled](Layer::is_enabled) by default.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// # use forma_render::prelude::*;
78    /// let mut composition = Composition::new();
79    ///
80    /// let _layer = composition.create_layer();
81    /// ```
82    #[inline]
83    pub fn create_layer(&mut self) -> Layer {
84        let (geom_id, props) = {
85            let mut state = self.shared_state.borrow_mut();
86
87            let geom_id = state.new_geom_id();
88            let props = state.props_interner.get(Props::default());
89
90            (geom_id, props)
91        };
92
93        Layer {
94            inner: InnerLayer::default(),
95            shared_state: LayerSharedState::new(Rc::clone(&self.shared_state)),
96            geom_id,
97            props,
98            is_unchanged: SmallBitSet::default(),
99            lines_count: 0,
100        }
101    }
102
103    /// Checks if the composition is empty.
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// # use forma_render::prelude::*;
109    /// let composition = Composition::new();
110    ///
111    /// assert!(composition.is_empty());
112    /// ```
113    #[inline]
114    pub fn is_empty(&self) -> bool {
115        self.layers.is_empty()
116    }
117
118    /// Returns the numbers of [`Layer`]s in this composition.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// # use forma_render::prelude::*;
124    /// let composition = Composition::new();
125    ///
126    /// assert_eq!(composition.len(), 0);
127    /// ```
128    #[inline]
129    pub fn len(&self) -> usize {
130        self.layers.len()
131    }
132
133    /// Inserts a `layer` at specified `order` and optionally returns the layer already at `order` if any.
134    ///
135    /// # Examples
136    ///
137    /// ```
138    /// # use forma_render::prelude::*;
139    /// let mut composition = Composition::new();
140    ///
141    /// let mut layer0 = composition.create_layer();
142    /// let layer1 = composition.create_layer();
143    ///
144    /// layer0.disable();
145    ///
146    /// assert!(composition.insert(Order::new(0).unwrap(), layer0).is_none());
147    ///
148    /// match composition.insert(Order::new(0).unwrap(), layer1) {
149    ///     Some(layer0) if !layer0.is_enabled() => (),
150    ///     _ => unreachable!(),
151    /// }
152    /// ```
153    #[inline]
154    pub fn insert(&mut self, order: Order, mut layer: Layer) -> Option<Layer> {
155        assert_eq!(
156            &layer.shared_state, &self.shared_state,
157            "Layer was crated by a different Composition"
158        );
159
160        layer.set_order(Some(order));
161
162        self.layers.insert(order, layer).map(|mut layer| {
163            layer.set_order(None);
164
165            layer
166        })
167    }
168
169    /// Removes a `layer` at specified `order` and optionally returns the layer already at `order` if any.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// # use forma_render::prelude::*;
175    /// let mut composition = Composition::new();
176    ///
177    /// let layer0 = composition.create_layer();
178    /// let layer1 = composition.create_layer();
179    ///
180    /// assert!(composition.insert(Order::new(0).unwrap(), layer0).is_none());
181    /// assert!(composition.insert(Order::new(0).unwrap(), layer1).is_some()); // Some(layer0)
182    /// ```
183    #[inline]
184    pub fn remove(&mut self, order: Order) -> Option<Layer> {
185        self.layers.remove(&order).map(|mut layer| {
186            layer.set_order(None);
187
188            layer
189        })
190    }
191
192    /// Optionally recover the order of presently-stored [`Layer`] by its `geom_id`. Bear in mind
193    /// that [clearing](Layer::clear) its geometry will reset the ID which will need to be
194    /// [refreshed](Layer::geom_id).
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// # use forma_render::prelude::*;
200    /// let mut composition = Composition::new();
201    ///
202    /// let layer = composition.create_layer();
203    ///
204    /// let id0 = layer.geom_id();
205    /// let order = Order::new(0).unwrap();
206    ///
207    /// assert_eq!(composition.get_order_if_stored(id0), None);
208    ///
209    /// // Post-insertion, the geometry is accessible by ID.
210    /// composition.insert(Order::new(0).unwrap(), layer);
211    /// assert_eq!(composition.get_order_if_stored(id0), Some(order));
212    ///
213    /// let layer = composition.get_mut(order).unwrap();
214    ///
215    /// layer.clear();
216    ///
217    /// let id1 = layer.geom_id();
218    ///
219    /// assert_ne!(id0, id1);
220    ///
221    /// // Old ID canot be use any longer.
222    /// assert_eq!(composition.get_order_if_stored(id0), None);
223    ///
224    /// // Since is has not been removed, the geometry is still accessible by ID.
225    /// assert_eq!(composition.get_order_if_stored(id1), Some(order));
226    ///
227    /// // Post-remove, the geometry is no longer accessible.
228    /// composition.remove(order);
229    /// assert_eq!(composition.get_order_if_stored(id1), None);
230    /// ```
231    #[inline]
232    pub fn get_order_if_stored(&self, geom_id: GeomId) -> Option<Order> {
233        self.shared_state
234            .borrow()
235            .geom_id_to_order
236            .get(&geom_id)
237            .copied()
238            .flatten()
239    }
240
241    /// Optionally returns a reference to the layer stored at specified `order`.
242    ///
243    /// # Examples
244    ///
245    /// ```
246    /// # use forma_render::prelude::*;
247    /// let mut composition = Composition::new();
248    ///
249    /// let layer = composition.create_layer();
250    /// let order = Order::new(0).unwrap();
251    ///
252    /// composition.insert(order, layer);
253    ///
254    /// assert!(composition.get(order).is_some());
255    /// ```
256    #[inline]
257    pub fn get(&self, order: Order) -> Option<&Layer> {
258        self.layers.get(&order)
259    }
260
261    /// Optionally returns a mutable reference to the layer stored at specified `order`.
262    ///
263    /// # Examples
264    ///
265    /// ```
266    /// # use forma_render::prelude::*;
267    /// let mut composition = Composition::new();
268    ///
269    /// let layer = composition.create_layer();
270    /// let order = Order::new(0).unwrap();
271    ///
272    /// composition.insert(order, layer);
273    ///
274    /// assert!(composition.get_mut(order).is_some());
275    /// ```
276    #[inline]
277    pub fn get_mut(&mut self, order: Order) -> Option<&mut Layer> {
278        self.layers.get_mut(&order)
279    }
280
281    /// Creates and inserts a default layer into the composition, returning a mutable reference
282    /// to it. it is a combined form of [`Self::create_layer`] and
283    /// [`Self::insert`]/[`Self::get_mut`].
284    ///
285    /// It is especially useful when wanting to update a specific layer for multiple frames.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// # use forma_render::prelude::*;
291    /// let mut composition = Composition::new();
292    ///
293    /// let line = PathBuilder::new().line_to(Point::new(10.0, 10.0)).build();
294    ///
295    /// composition.get_mut_or_insert_default(Order::new(0).unwrap()).insert(&line);
296    /// ```
297    #[inline]
298    pub fn get_mut_or_insert_default(&mut self, order: Order) -> &mut Layer {
299        if !self.layers.contains_key(&order) {
300            let layer = self.create_layer();
301            self.insert(order, layer);
302        }
303
304        self.get_mut(order).unwrap()
305    }
306
307    /// Returns an [`ExactSizeIterator`] over all order/layer reference pairs.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// # use forma_render::prelude::*;
313    /// let mut composition = Composition::new();
314    ///
315    /// composition.get_mut_or_insert_default(Order::new(0).unwrap());
316    /// composition.get_mut_or_insert_default(Order::new(1).unwrap());
317    ///
318    /// assert_eq!(composition.layers().count(), 2);
319    /// ```
320    #[inline]
321    pub fn layers(&self) -> impl ExactSizeIterator<Item = (Order, &Layer)> + '_ {
322        self.layers.iter().map(|(&order, layer)| (order, layer))
323    }
324
325    /// Returns an [`ExactSizeIterator`] over all order/mutable layer reference pairs.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// # use forma_render::prelude::*;
331    /// let mut composition = Composition::new();
332    ///
333    /// composition.get_mut_or_insert_default(Order::new(0).unwrap());
334    /// composition.get_mut_or_insert_default(Order::new(1).unwrap());
335    ///
336    /// assert_eq!(composition.layers_mut().count(), 2);
337    /// ```
338    #[inline]
339    pub fn layers_mut(&mut self) -> impl ExactSizeIterator<Item = (Order, &mut Layer)> + '_ {
340        self.layers.iter_mut().map(|(&order, layer)| (order, layer))
341    }
342
343    fn builder_len(&self) -> usize {
344        self.shared_state
345            .borrow()
346            .segment_buffer
347            .as_ref()
348            .expect("lines_builder should not be None")
349            .len()
350    }
351
352    fn actual_len(&self) -> usize {
353        self.layers.values().map(|layer| layer.lines_count).sum()
354    }
355
356    /// Forces the composition to run geometry garbage collection if more than half the memory
357    /// occupied by it is not accessible anymore by the end-user. (i.e. by [`Layer::clear`] or
358    /// [`Layer::drop`])
359    ///
360    /// # Examples
361    ///
362    /// ```
363    /// # use forma_render::prelude::*;
364    /// let mut composition = Composition::new();
365    ///
366    /// // Insertions and removals/clears happen here.
367    ///
368    /// composition.compact_geom();
369    /// ```
370    #[inline]
371    pub fn compact_geom(&mut self) {
372        if self.builder_len() >= self.actual_len() * LINES_GARBAGE_THRESHOLD {
373            let state = &mut *self.shared_state.borrow_mut();
374            let lines_builder = &mut state.segment_buffer;
375            let geom_id_to_order = &mut state.geom_id_to_order;
376
377            lines_builder
378                .as_mut()
379                .expect("lines_builder should not be None")
380                .retain(|id| geom_id_to_order.contains_key(&id));
381        }
382    }
383}
384
385#[cfg(test)]
386mod tests {
387    use super::*;
388
389    use crate::{
390        consts::cpu::{TILE_HEIGHT, TILE_WIDTH},
391        cpu::{
392            buffer::{layout::LinearLayout, BufferBuilder},
393            Renderer, RGBA,
394        },
395        math::{GeomPresTransform, Point},
396        styling::{Color, Fill, FillRule, Func, Style},
397        Path, PathBuilder,
398    };
399
400    const BLACK_SRGB: [u8; 4] = [0x00, 0x00, 0x00, 0xFF];
401    const GRAY_SRGB: [u8; 4] = [0xBB, 0xBB, 0xBB, 0xFF];
402    const GRAY_ALPHA_50_SRGB: [u8; 4] = [0xBB, 0xBB, 0xBB, 0x80];
403    const WHITE_ALPHA_0_SRGB: [u8; 4] = [0xFF, 0xFF, 0xFF, 0x00];
404    const RED_SRGB: [u8; 4] = [0xFF, 0x00, 0x00, 0xFF];
405    const GREEN_SRGB: [u8; 4] = [0x00, 0xFF, 0x00, 0xFF];
406    const RED_50_GREEN_50_SRGB: [u8; 4] = [0xBB, 0xBB, 0x00, 0xFF];
407
408    const BLACK: Color = Color {
409        r: 0.0,
410        g: 0.0,
411        b: 0.0,
412        a: 1.0,
413    };
414    const BLACK_ALPHA_50: Color = Color {
415        r: 0.0,
416        g: 0.0,
417        b: 0.0,
418        a: 0.5,
419    };
420    const GRAY: Color = Color {
421        r: 0.5,
422        g: 0.5,
423        b: 0.5,
424        a: 1.0,
425    };
426    const WHITE_TRANSPARENT: Color = Color {
427        r: 1.0,
428        g: 1.0,
429        b: 1.0,
430        a: 0.0,
431    };
432    const RED: Color = Color {
433        r: 1.0,
434        g: 0.0,
435        b: 0.0,
436        a: 1.0,
437    };
438    const GREEN: Color = Color {
439        r: 0.0,
440        g: 1.0,
441        b: 0.0,
442        a: 1.0,
443    };
444
445    fn pixel_path(x: i32, y: i32) -> Path {
446        let mut builder = PathBuilder::new();
447
448        builder.move_to(Point::new(x as f32, y as f32));
449        builder.line_to(Point::new(x as f32, (y + 1) as f32));
450        builder.line_to(Point::new((x + 1) as f32, (y + 1) as f32));
451        builder.line_to(Point::new((x + 1) as f32, y as f32));
452        builder.line_to(Point::new(x as f32, y as f32));
453
454        builder.build()
455    }
456
457    fn solid(color: Color) -> Props {
458        Props {
459            func: Func::Draw(Style {
460                fill: Fill::Solid(color),
461                ..Default::default()
462            }),
463            ..Default::default()
464        }
465    }
466
467    #[test]
468    fn composition_len() {
469        let mut composition = Composition::new();
470
471        assert!(composition.is_empty());
472        assert_eq!(composition.len(), 0);
473
474        composition.get_mut_or_insert_default(Order::new(0).unwrap());
475
476        assert!(!composition.is_empty());
477        assert_eq!(composition.len(), 1);
478    }
479
480    #[test]
481    fn background_color_clear() {
482        let mut buffer = [GREEN_SRGB].concat();
483        let mut layout = LinearLayout::new(1, 4, 1);
484
485        let mut composition = Composition::new();
486        let mut renderer = Renderer::new();
487
488        renderer.render(
489            &mut composition,
490            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
491            RGBA,
492            RED,
493            None,
494        );
495
496        assert_eq!(buffer, [RED_SRGB].concat());
497    }
498
499    #[test]
500    fn background_color_clear_when_changed() {
501        let mut buffer = [GREEN_SRGB].concat();
502        let mut layout = LinearLayout::new(1, 4, 1);
503
504        let mut composition = Composition::new();
505        let mut renderer = Renderer::new();
506        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
507
508        renderer.render(
509            &mut composition,
510            &mut BufferBuilder::new(&mut buffer, &mut layout)
511                .layer_cache(layer_cache.clone())
512                .build(),
513            RGBA,
514            RED,
515            None,
516        );
517
518        assert_eq!(buffer, [RED_SRGB].concat());
519
520        buffer = [GREEN_SRGB].concat();
521
522        renderer.render(
523            &mut composition,
524            &mut BufferBuilder::new(&mut buffer, &mut layout)
525                .layer_cache(layer_cache.clone())
526                .build(),
527            RGBA,
528            RED,
529            None,
530        );
531
532        // Skip clearing if the color is the same.
533        assert_eq!(buffer, [GREEN_SRGB].concat());
534
535        renderer.render(
536            &mut composition,
537            &mut BufferBuilder::new(&mut buffer, &mut layout)
538                .layer_cache(layer_cache)
539                .build(),
540            RGBA,
541            BLACK,
542            None,
543        );
544
545        assert_eq!(buffer, [BLACK_SRGB].concat());
546    }
547
548    #[test]
549    fn one_pixel() {
550        let mut buffer = [GREEN_SRGB; 3].concat();
551        let mut layout = LinearLayout::new(3, 3 * 4, 1);
552
553        let mut composition = Composition::new();
554        let mut renderer = Renderer::new();
555
556        let mut layer = composition.create_layer();
557        layer.insert(&pixel_path(1, 0)).set_props(solid(RED));
558
559        composition.insert(Order::new(0).unwrap(), layer);
560
561        renderer.render(
562            &mut composition,
563            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
564            RGBA,
565            GREEN,
566            None,
567        );
568
569        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, GREEN_SRGB].concat());
570    }
571
572    #[test]
573    fn two_pixels_same_layer() {
574        let mut buffer = [GREEN_SRGB; 3].concat();
575        let mut layout = LinearLayout::new(3, 3 * 4, 1);
576        let mut composition = Composition::new();
577        let mut renderer = Renderer::new();
578
579        let mut layer = composition.create_layer();
580        layer
581            .insert(&pixel_path(1, 0))
582            .insert(&pixel_path(2, 0))
583            .set_props(solid(RED));
584
585        composition.insert(Order::new(0).unwrap(), layer);
586
587        renderer.render(
588            &mut composition,
589            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
590            RGBA,
591            GREEN,
592            None,
593        );
594
595        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, RED_SRGB].concat());
596    }
597
598    #[test]
599    fn one_pixel_translated() {
600        let mut buffer = [GREEN_SRGB; 3].concat();
601        let mut layout = LinearLayout::new(3, 3 * 4, 1);
602
603        let mut composition = Composition::new();
604        let mut renderer = Renderer::new();
605
606        let mut layer = composition.create_layer();
607        layer
608            .insert(&pixel_path(1, 0))
609            .set_props(solid(RED))
610            .set_transform(GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 0.5, 0.0]).unwrap());
611
612        composition.insert(Order::new(0).unwrap(), layer);
613
614        renderer.render(
615            &mut composition,
616            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
617            RGBA,
618            GREEN,
619            None,
620        );
621
622        assert_eq!(
623            buffer,
624            [GREEN_SRGB, RED_50_GREEN_50_SRGB, RED_50_GREEN_50_SRGB].concat()
625        );
626    }
627
628    #[test]
629    fn one_pixel_rotated() {
630        let mut buffer = [GREEN_SRGB; 3].concat();
631        let mut layout = LinearLayout::new(3, 3 * 4, 1);
632
633        let mut composition = Composition::new();
634        let mut renderer = Renderer::new();
635
636        let angle = -std::f32::consts::PI / 2.0;
637
638        let mut layer = composition.create_layer();
639        layer
640            .insert(&pixel_path(-1, 1))
641            .set_props(solid(RED))
642            .set_transform(
643                GeomPresTransform::try_from([
644                    angle.cos(),
645                    -angle.sin(),
646                    angle.sin(),
647                    angle.cos(),
648                    0.0,
649                    0.0,
650                ])
651                .unwrap(),
652            );
653
654        composition.insert(Order::new(0).unwrap(), layer);
655
656        renderer.render(
657            &mut composition,
658            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
659            RGBA,
660            GREEN,
661            None,
662        );
663
664        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, GREEN_SRGB].concat());
665    }
666
667    #[test]
668    fn clear_and_resize() {
669        let mut buffer = [GREEN_SRGB; 4].concat();
670        let mut composition = Composition::new();
671        let mut renderer = Renderer::new();
672
673        let order0 = Order::new(0).unwrap();
674        let order1 = Order::new(1).unwrap();
675        let order2 = Order::new(2).unwrap();
676
677        let mut layer0 = composition.create_layer();
678        layer0.insert(&pixel_path(0, 0)).set_props(solid(RED));
679
680        composition.insert(order0, layer0);
681
682        let mut layer1 = composition.create_layer();
683        layer1.insert(&pixel_path(1, 0)).set_props(solid(RED));
684
685        composition.insert(order1, layer1);
686
687        let mut layer2 = composition.create_layer();
688        layer2
689            .insert(&pixel_path(2, 0))
690            .insert(&pixel_path(3, 0))
691            .set_props(solid(RED));
692
693        composition.insert(order2, layer2);
694
695        let mut layout = LinearLayout::new(4, 4 * 4, 1);
696
697        renderer.render(
698            &mut composition,
699            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
700            RGBA,
701            GREEN,
702            None,
703        );
704
705        assert_eq!(buffer, [RED_SRGB, RED_SRGB, RED_SRGB, RED_SRGB].concat());
706        assert_eq!(composition.builder_len(), 16);
707        assert_eq!(composition.actual_len(), 16);
708
709        buffer = [GREEN_SRGB; 4].concat();
710
711        let mut layout = LinearLayout::new(4, 4 * 4, 1);
712
713        composition.get_mut(order0).unwrap().clear();
714
715        renderer.render(
716            &mut composition,
717            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
718            RGBA,
719            GREEN,
720            None,
721        );
722
723        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, RED_SRGB, RED_SRGB].concat());
724        assert_eq!(composition.builder_len(), 16);
725        assert_eq!(composition.actual_len(), 12);
726
727        buffer = [GREEN_SRGB; 4].concat();
728
729        let mut layout = LinearLayout::new(4, 4 * 4, 1);
730
731        composition.get_mut(order2).unwrap().clear();
732
733        renderer.render(
734            &mut composition,
735            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
736            RGBA,
737            GREEN,
738            None,
739        );
740
741        assert_eq!(
742            buffer,
743            [GREEN_SRGB, RED_SRGB, GREEN_SRGB, GREEN_SRGB].concat()
744        );
745        assert_eq!(composition.builder_len(), 4);
746        assert_eq!(composition.actual_len(), 4);
747    }
748
749    #[test]
750    fn clear_twice() {
751        let mut composition = Composition::new();
752
753        let order = Order::new(0).unwrap();
754
755        let mut layer = composition.create_layer();
756        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
757
758        composition.insert(order, layer);
759
760        assert_eq!(composition.actual_len(), 4);
761
762        composition.get_mut(order).unwrap().clear();
763
764        assert_eq!(composition.actual_len(), 0);
765
766        composition.get_mut(order).unwrap().clear();
767
768        assert_eq!(composition.actual_len(), 0);
769    }
770
771    #[test]
772    fn insert_over_layer() {
773        let mut buffer = [BLACK_SRGB; 3].concat();
774        let mut layout = LinearLayout::new(3, 3 * 4, 1);
775
776        let mut composition = Composition::new();
777        let mut renderer = Renderer::new();
778
779        let mut layer = composition.create_layer();
780        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
781
782        composition.insert(Order::new(0).unwrap(), layer);
783
784        renderer.render(
785            &mut composition,
786            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
787            RGBA,
788            BLACK,
789            None,
790        );
791
792        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
793
794        let mut layer = composition.create_layer();
795        layer.insert(&pixel_path(1, 0)).set_props(solid(GREEN));
796
797        buffer = [BLACK_SRGB; 3].concat();
798
799        renderer.render(
800            &mut composition,
801            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
802            RGBA,
803            BLACK,
804            None,
805        );
806
807        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
808
809        composition.insert(Order::new(0).unwrap(), layer);
810
811        buffer = [BLACK_SRGB; 3].concat();
812
813        renderer.render(
814            &mut composition,
815            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
816            RGBA,
817            BLACK,
818            None,
819        );
820
821        assert_eq!(buffer, [BLACK_SRGB, GREEN_SRGB, BLACK_SRGB].concat());
822    }
823
824    #[test]
825    fn layer_replace_remove() {
826        let mut buffer = [BLACK_SRGB; 3].concat();
827        let mut layout = LinearLayout::new(3, 3 * 4, 1);
828
829        let mut composition = Composition::new();
830        let mut renderer = Renderer::new();
831
832        let mut layer = composition.create_layer();
833        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
834
835        composition.insert(Order::new(0).unwrap(), layer);
836
837        renderer.render(
838            &mut composition,
839            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
840            RGBA,
841            BLACK,
842            None,
843        );
844
845        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
846
847        let mut layer = composition.create_layer();
848        layer.insert(&pixel_path(1, 0)).set_props(solid(GREEN));
849
850        let _old_layer = composition.insert(Order::new(0).unwrap(), layer);
851
852        buffer = [BLACK_SRGB; 3].concat();
853
854        renderer.render(
855            &mut composition,
856            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
857            RGBA,
858            BLACK,
859            None,
860        );
861
862        assert_eq!(buffer, [BLACK_SRGB, GREEN_SRGB, BLACK_SRGB].concat());
863
864        let _old_layer = composition.remove(Order::new(0).unwrap());
865
866        buffer = [BLACK_SRGB; 3].concat();
867
868        renderer.render(
869            &mut composition,
870            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
871            RGBA,
872            BLACK,
873            None,
874        );
875
876        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
877    }
878
879    #[test]
880    fn layer_clear() {
881        let mut buffer = [BLACK_SRGB; 3].concat();
882        let mut layout = LinearLayout::new(3, 3 * 4, 1);
883
884        let mut composition = Composition::new();
885        let mut renderer = Renderer::new();
886
887        let order = Order::new(0).unwrap();
888
889        let mut layer = composition.create_layer();
890        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
891
892        composition.insert(order, layer);
893
894        renderer.render(
895            &mut composition,
896            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
897            RGBA,
898            BLACK,
899            None,
900        );
901
902        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
903
904        composition
905            .get_mut(order)
906            .unwrap()
907            .insert(&pixel_path(1, 0));
908
909        buffer = [BLACK_SRGB; 3].concat();
910
911        renderer.render(
912            &mut composition,
913            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
914            RGBA,
915            BLACK,
916            None,
917        );
918
919        assert_eq!(buffer, [RED_SRGB, RED_SRGB, BLACK_SRGB].concat());
920
921        composition.get_mut(order).unwrap().clear();
922
923        buffer = [BLACK_SRGB; 3].concat();
924
925        renderer.render(
926            &mut composition,
927            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
928            RGBA,
929            BLACK,
930            None,
931        );
932
933        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
934
935        composition
936            .get_mut(order)
937            .unwrap()
938            .insert(&pixel_path(2, 0));
939
940        buffer = [BLACK_SRGB; 3].concat();
941
942        renderer.render(
943            &mut composition,
944            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
945            RGBA,
946            BLACK,
947            None,
948        );
949
950        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, RED_SRGB].concat());
951    }
952
953    #[test]
954    fn geom_id() {
955        let mut composition = Composition::new();
956
957        let mut layer = composition.create_layer();
958
959        layer.insert(&PathBuilder::new().build());
960        let geom_id0 = layer.geom_id();
961
962        layer.insert(&PathBuilder::new().build());
963        let geom_id1 = layer.geom_id();
964
965        assert_eq!(geom_id0, geom_id1);
966
967        layer.clear();
968
969        assert_ne!(layer.geom_id(), geom_id0);
970
971        layer.insert(&PathBuilder::new().build());
972        let geom_id2 = layer.geom_id();
973
974        assert_ne!(geom_id0, geom_id2);
975
976        let order = Order::new(0).unwrap();
977        composition.insert(order, layer);
978
979        assert_eq!(composition.get_order_if_stored(geom_id2), Some(order));
980
981        let layer = composition.create_layer();
982        composition.insert(order, layer);
983
984        assert_eq!(composition.get_order_if_stored(geom_id2), None);
985    }
986
987    #[test]
988    fn srgb_alpha_blending() {
989        let mut buffer = [BLACK_SRGB; 3].concat();
990        let mut layout = LinearLayout::new(3, 3 * 4, 1);
991
992        let mut composition = Composition::new();
993        let mut renderer = Renderer::new();
994
995        let mut layer = composition.create_layer();
996        layer
997            .insert(&pixel_path(0, 0))
998            .set_props(solid(BLACK_ALPHA_50));
999
1000        composition.insert(Order::new(0).unwrap(), layer);
1001
1002        let mut layer = composition.create_layer();
1003
1004        layer.insert(&pixel_path(1, 0)).set_props(solid(GRAY));
1005
1006        composition.insert(Order::new(1).unwrap(), layer);
1007
1008        renderer.render(
1009            &mut composition,
1010            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
1011            RGBA,
1012            WHITE_TRANSPARENT,
1013            None,
1014        );
1015
1016        assert_eq!(
1017            buffer,
1018            [GRAY_ALPHA_50_SRGB, GRAY_SRGB, WHITE_ALPHA_0_SRGB].concat()
1019        );
1020    }
1021
1022    #[test]
1023    fn render_changed_layers_only() {
1024        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
1025        let mut layout = LinearLayout::new(3 * TILE_WIDTH, 3 * TILE_WIDTH * 4, TILE_HEIGHT);
1026        let mut composition = Composition::new();
1027        let mut renderer = Renderer::new();
1028        let layer_cache = renderer.create_buffer_layer_cache();
1029
1030        let mut layer = composition.create_layer();
1031        layer
1032            .insert(&pixel_path(0, 0))
1033            .insert(&pixel_path(TILE_WIDTH as i32, 0))
1034            .set_props(solid(RED));
1035
1036        composition.insert(Order::new(0).unwrap(), layer);
1037
1038        let order = Order::new(1).unwrap();
1039
1040        let mut layer = composition.create_layer();
1041        layer
1042            .insert(&pixel_path(TILE_WIDTH as i32 + 1, 0))
1043            .insert(&pixel_path(2 * TILE_WIDTH as i32, 0))
1044            .set_props(solid(GREEN));
1045
1046        composition.insert(order, layer);
1047
1048        renderer.render(
1049            &mut composition,
1050            &mut BufferBuilder::new(&mut buffer, &mut layout)
1051                .layer_cache(layer_cache.clone().unwrap())
1052                .build(),
1053            RGBA,
1054            BLACK,
1055            None,
1056        );
1057
1058        assert_eq!(buffer[0..4], RED_SRGB);
1059        assert_eq!(buffer[TILE_WIDTH * 4..TILE_WIDTH * 4 + 4], RED_SRGB);
1060        assert_eq!(
1061            buffer[(TILE_WIDTH + 1) * 4..(TILE_WIDTH + 1) * 4 + 4],
1062            GREEN_SRGB
1063        );
1064        assert_eq!(
1065            buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4],
1066            GREEN_SRGB
1067        );
1068
1069        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
1070
1071        composition.get_mut(order).unwrap().set_props(solid(RED));
1072
1073        renderer.render(
1074            &mut composition,
1075            &mut BufferBuilder::new(&mut buffer, &mut layout)
1076                .layer_cache(layer_cache.unwrap())
1077                .build(),
1078            RGBA,
1079            BLACK,
1080            None,
1081        );
1082
1083        assert_eq!(buffer[0..4], BLACK_SRGB);
1084        assert_eq!(buffer[TILE_WIDTH * 4..TILE_WIDTH * 4 + 4], RED_SRGB);
1085        assert_eq!(
1086            buffer[(TILE_WIDTH + 1) * 4..(TILE_WIDTH + 1) * 4 + 4],
1087            RED_SRGB
1088        );
1089        assert_eq!(buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4], RED_SRGB);
1090    }
1091
1092    #[test]
1093    fn insert_remove_same_order_will_not_render_again() {
1094        let mut buffer = [BLACK_SRGB; 3].concat();
1095        let mut layout = LinearLayout::new(3, 3 * 4, 1);
1096
1097        let mut composition = Composition::new();
1098        let mut renderer = Renderer::new();
1099        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
1100
1101        let mut layer = composition.create_layer();
1102        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
1103
1104        composition.insert(Order::new(0).unwrap(), layer);
1105
1106        renderer.render(
1107            &mut composition,
1108            &mut BufferBuilder::new(&mut buffer, &mut layout)
1109                .layer_cache(layer_cache.clone())
1110                .build(),
1111            RGBA,
1112            BLACK,
1113            None,
1114        );
1115
1116        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
1117
1118        let layer = composition.remove(Order::new(0).unwrap()).unwrap();
1119        composition.insert(Order::new(0).unwrap(), layer);
1120
1121        buffer = [BLACK_SRGB; 3].concat();
1122
1123        renderer.render(
1124            &mut composition,
1125            &mut BufferBuilder::new(&mut buffer, &mut layout)
1126                .layer_cache(layer_cache)
1127                .build(),
1128            RGBA,
1129            BLACK,
1130            None,
1131        );
1132
1133        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
1134    }
1135
1136    #[test]
1137    fn clear_emptied_tiles() {
1138        let mut buffer = [BLACK_SRGB; 2 * TILE_WIDTH * TILE_HEIGHT].concat();
1139        let mut layout = LinearLayout::new(2 * TILE_WIDTH, 2 * TILE_WIDTH * 4, TILE_HEIGHT);
1140        let mut composition = Composition::new();
1141        let mut renderer = Renderer::new();
1142        let layer_cache = renderer.create_buffer_layer_cache();
1143
1144        let order = Order::new(0).unwrap();
1145
1146        let mut layer = composition.create_layer();
1147        layer
1148            .insert(&pixel_path(0, 0))
1149            .set_props(solid(RED))
1150            .insert(&pixel_path(TILE_WIDTH as i32, 0));
1151
1152        composition.insert(order, layer);
1153
1154        renderer.render(
1155            &mut composition,
1156            &mut BufferBuilder::new(&mut buffer, &mut layout)
1157                .layer_cache(layer_cache.clone().unwrap())
1158                .build(),
1159            RGBA,
1160            BLACK,
1161            None,
1162        );
1163
1164        assert_eq!(buffer[0..4], RED_SRGB);
1165
1166        composition.get_mut(order).unwrap().set_transform(
1167            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, TILE_WIDTH as f32, 0.0]).unwrap(),
1168        );
1169
1170        renderer.render(
1171            &mut composition,
1172            &mut BufferBuilder::new(&mut buffer, &mut layout)
1173                .layer_cache(layer_cache.clone().unwrap())
1174                .build(),
1175            RGBA,
1176            BLACK,
1177            None,
1178        );
1179
1180        assert_eq!(buffer[0..4], BLACK_SRGB);
1181
1182        composition.get_mut(order).unwrap().set_transform(
1183            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, -(TILE_WIDTH as f32), 0.0]).unwrap(),
1184        );
1185
1186        renderer.render(
1187            &mut composition,
1188            &mut BufferBuilder::new(&mut buffer, &mut layout)
1189                .layer_cache(layer_cache.clone().unwrap())
1190                .build(),
1191            RGBA,
1192            BLACK,
1193            None,
1194        );
1195
1196        assert_eq!(buffer[0..4], RED_SRGB);
1197
1198        composition.get_mut(order).unwrap().set_transform(
1199            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 0.0, TILE_HEIGHT as f32]).unwrap(),
1200        );
1201
1202        renderer.render(
1203            &mut composition,
1204            &mut BufferBuilder::new(&mut buffer, &mut layout)
1205                .layer_cache(layer_cache.unwrap())
1206                .build(),
1207            RGBA,
1208            BLACK,
1209            None,
1210        );
1211
1212        assert_eq!(buffer[0..4], BLACK_SRGB);
1213    }
1214
1215    #[test]
1216    fn separate_layer_caches() {
1217        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
1218        let mut layout = LinearLayout::new(TILE_WIDTH, TILE_WIDTH * 4, TILE_HEIGHT);
1219        let mut composition = Composition::new();
1220        let mut renderer = Renderer::new();
1221        let layer_cache0 = renderer.create_buffer_layer_cache();
1222        let layer_cache1 = renderer.create_buffer_layer_cache();
1223
1224        let order = Order::new(0).unwrap();
1225
1226        let mut layer = composition.create_layer();
1227        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
1228
1229        composition.insert(order, layer);
1230
1231        renderer.render(
1232            &mut composition,
1233            &mut BufferBuilder::new(&mut buffer, &mut layout)
1234                .layer_cache(layer_cache0.clone().unwrap())
1235                .build(),
1236            RGBA,
1237            BLACK,
1238            None,
1239        );
1240
1241        assert_eq!(buffer[0..4], RED_SRGB);
1242
1243        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
1244
1245        renderer.render(
1246            &mut composition,
1247            &mut BufferBuilder::new(&mut buffer, &mut layout)
1248                .layer_cache(layer_cache0.clone().unwrap())
1249                .build(),
1250            RGBA,
1251            BLACK,
1252            None,
1253        );
1254
1255        assert_eq!(buffer[0..4], BLACK_SRGB);
1256
1257        renderer.render(
1258            &mut composition,
1259            &mut BufferBuilder::new(&mut buffer, &mut layout)
1260                .layer_cache(layer_cache1.clone().unwrap())
1261                .build(),
1262            RGBA,
1263            BLACK,
1264            None,
1265        );
1266
1267        assert_eq!(buffer[0..4], RED_SRGB);
1268
1269        composition
1270            .get_mut(order)
1271            .unwrap()
1272            .set_transform(GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 1.0, 0.0]).unwrap());
1273
1274        renderer.render(
1275            &mut composition,
1276            &mut BufferBuilder::new(&mut buffer, &mut layout)
1277                .layer_cache(layer_cache0.unwrap())
1278                .build(),
1279            RGBA,
1280            BLACK,
1281            None,
1282        );
1283
1284        assert_eq!(buffer[0..4], BLACK_SRGB);
1285        assert_eq!(buffer[4..8], RED_SRGB);
1286
1287        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
1288
1289        renderer.render(
1290            &mut composition,
1291            &mut BufferBuilder::new(&mut buffer, &mut layout)
1292                .layer_cache(layer_cache1.unwrap())
1293                .build(),
1294            RGBA,
1295            BLACK,
1296            None,
1297        );
1298
1299        assert_eq!(buffer[0..4], BLACK_SRGB);
1300        assert_eq!(buffer[4..8], RED_SRGB);
1301    }
1302
1303    #[test]
1304    fn draw_if_width_or_height_change() {
1305        let mut buffer = [BLACK_SRGB; 1].concat();
1306        let mut layout = LinearLayout::new(1, 4, 1);
1307
1308        let mut composition = Composition::new();
1309        let mut renderer = Renderer::new();
1310        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
1311
1312        renderer.render(
1313            &mut composition,
1314            &mut BufferBuilder::new(&mut buffer, &mut layout)
1315                .layer_cache(layer_cache.clone())
1316                .build(),
1317            RGBA,
1318            RED,
1319            None,
1320        );
1321
1322        assert_eq!(buffer[0..4], RED_SRGB);
1323
1324        buffer = [BLACK_SRGB; 1].concat();
1325
1326        renderer.render(
1327            &mut composition,
1328            &mut BufferBuilder::new(&mut buffer, &mut layout)
1329                .layer_cache(layer_cache.clone())
1330                .build(),
1331            RGBA,
1332            RED,
1333            None,
1334        );
1335
1336        assert_eq!(buffer[0..4], BLACK_SRGB);
1337
1338        buffer = [BLACK_SRGB; 2].concat();
1339        layout = LinearLayout::new(2, 2 * 4, 1);
1340
1341        renderer.render(
1342            &mut composition,
1343            &mut BufferBuilder::new(&mut buffer, &mut layout)
1344                .layer_cache(layer_cache.clone())
1345                .build(),
1346            RGBA,
1347            RED,
1348            None,
1349        );
1350
1351        assert_eq!(buffer[0..8], [RED_SRGB; 2].concat());
1352
1353        buffer = [BLACK_SRGB; 2].concat();
1354        layout = LinearLayout::new(1, 4, 2);
1355
1356        renderer.render(
1357            &mut composition,
1358            &mut BufferBuilder::new(&mut buffer, &mut layout)
1359                .layer_cache(layer_cache)
1360                .build(),
1361            RGBA,
1362            RED,
1363            None,
1364        );
1365
1366        assert_eq!(buffer[0..8], [RED_SRGB; 2].concat());
1367    }
1368
1369    #[test]
1370    fn even_odd() {
1371        let mut builder = PathBuilder::new();
1372
1373        builder.move_to(Point::new(0.0, 0.0));
1374        builder.line_to(Point::new(0.0, TILE_HEIGHT as f32));
1375        builder.line_to(Point::new(3.0 * TILE_WIDTH as f32, TILE_HEIGHT as f32));
1376        builder.line_to(Point::new(3.0 * TILE_WIDTH as f32, 0.0));
1377        builder.line_to(Point::new(TILE_WIDTH as f32, 0.0));
1378        builder.line_to(Point::new(TILE_WIDTH as f32, TILE_HEIGHT as f32));
1379        builder.line_to(Point::new(2.0 * TILE_WIDTH as f32, TILE_HEIGHT as f32));
1380        builder.line_to(Point::new(2.0 * TILE_WIDTH as f32, 0.0));
1381        builder.line_to(Point::new(0.0, 0.0));
1382
1383        let path = builder.build();
1384
1385        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
1386        let mut layout = LinearLayout::new(3 * TILE_WIDTH, 3 * TILE_WIDTH * 4, TILE_HEIGHT);
1387
1388        let mut composition = Composition::new();
1389        let mut renderer = Renderer::new();
1390
1391        let mut layer = composition.create_layer();
1392        layer.insert(&path).set_props(Props {
1393            fill_rule: FillRule::EvenOdd,
1394            func: Func::Draw(Style {
1395                fill: Fill::Solid(RED),
1396                ..Default::default()
1397            }),
1398        });
1399
1400        composition.insert(Order::new(0).unwrap(), layer);
1401
1402        renderer.render(
1403            &mut composition,
1404            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
1405            RGBA,
1406            BLACK,
1407            None,
1408        );
1409
1410        assert_eq!(buffer[0..4], RED_SRGB);
1411        assert_eq!(buffer[TILE_WIDTH * 4..(TILE_WIDTH * 4 + 4)], BLACK_SRGB);
1412        assert_eq!(buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4], RED_SRGB);
1413    }
1414}