forma/composition/
mod.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::cell::RefCell;
6use std::rc::Rc;
7
8use rustc_hash::FxHashMap;
9use surpass::painter::Props;
10use surpass::{GeomId, Order};
11
12use crate::small_bit_set::SmallBitSet;
13
14mod interner;
15mod layer;
16mod state;
17
18pub use self::layer::Layer;
19use state::{LayerSharedState, LayerSharedStateInner};
20
21const LINES_GARBAGE_THRESHOLD: usize = 2;
22
23#[derive(Debug, Default)]
24pub struct Composition {
25    pub(crate) layers: FxHashMap<Order, Layer>,
26    pub(crate) shared_state: Rc<RefCell<LayerSharedStateInner>>,
27}
28
29impl Composition {
30    #[inline]
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    #[inline]
36    pub fn create_layer(&mut self) -> Layer {
37        let (geom_id, props) = {
38            let mut state = self.shared_state.borrow_mut();
39
40            let geom_id = state.new_geom_id();
41            let props = state.props_interner.get(Props::default());
42
43            (geom_id, props)
44        };
45
46        Layer {
47            inner: surpass::Layer::default(),
48            shared_state: LayerSharedState::new(Rc::clone(&self.shared_state)),
49            geom_id,
50            props,
51            is_unchanged: SmallBitSet::default(),
52            lines_count: 0,
53        }
54    }
55
56    #[inline]
57    pub fn is_empty(&self) -> bool {
58        self.layers.is_empty()
59    }
60
61    #[inline]
62    pub fn len(&self) -> usize {
63        self.layers.len()
64    }
65
66    #[inline]
67    pub fn insert(&mut self, order: Order, mut layer: Layer) -> Option<Layer> {
68        assert_eq!(
69            &layer.shared_state, &self.shared_state,
70            "Layer was crated by a different Composition"
71        );
72
73        layer.set_order(Some(order));
74
75        self.layers.insert(order, layer).map(|mut layer| {
76            layer.set_order(None);
77
78            layer
79        })
80    }
81
82    #[inline]
83    pub fn remove(&mut self, order: Order) -> Option<Layer> {
84        self.layers.remove(&order).map(|mut layer| {
85            layer.set_order(None);
86
87            layer
88        })
89    }
90
91    #[inline]
92    pub fn get_order_if_stored(&self, geom_id: GeomId) -> Option<Order> {
93        self.shared_state.borrow().geom_id_to_order.get(&geom_id).copied().flatten()
94    }
95
96    #[inline]
97    pub fn get(&self, order: Order) -> Option<&Layer> {
98        self.layers.get(&order)
99    }
100
101    #[inline]
102    pub fn get_mut(&mut self, order: Order) -> Option<&mut Layer> {
103        self.layers.get_mut(&order)
104    }
105
106    #[inline]
107    pub fn get_mut_or_insert_default(&mut self, order: Order) -> &mut Layer {
108        if !self.layers.contains_key(&order) {
109            let layer = self.create_layer();
110            self.insert(order, layer);
111        }
112
113        self.get_mut(order).unwrap()
114    }
115
116    #[inline]
117    pub fn layers(&self) -> impl ExactSizeIterator<Item = (Order, &Layer)> + '_ {
118        self.layers.iter().map(|(&order, layer)| (order, layer))
119    }
120
121    #[inline]
122    pub fn layers_mut(&mut self) -> impl ExactSizeIterator<Item = (Order, &mut Layer)> + '_ {
123        self.layers.iter_mut().map(|(&order, layer)| (order, layer))
124    }
125
126    fn builder_len(&self) -> usize {
127        self.shared_state
128            .borrow()
129            .lines_builder
130            .as_ref()
131            .expect("lines_builder should not be None")
132            .len()
133    }
134
135    fn actual_len(&self) -> usize {
136        self.layers.values().map(|layer| layer.lines_count).sum()
137    }
138
139    #[inline]
140    pub fn compact_geom(&mut self) {
141        if self.builder_len() >= self.actual_len() * LINES_GARBAGE_THRESHOLD {
142            let state = &mut *self.shared_state.borrow_mut();
143            let lines_builder = &mut state.lines_builder;
144            let geom_id_to_order = &mut state.geom_id_to_order;
145
146            lines_builder
147                .as_mut()
148                .expect("lines_builder should not be None")
149                .retain(|id| geom_id_to_order.contains_key(&id));
150        }
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use super::*;
157
158    use surpass::painter::{Color, RGBA};
159    use surpass::{Path, TILE_HEIGHT, TILE_WIDTH};
160
161    use crate::buffer::layout::LinearLayout;
162    use crate::buffer::BufferBuilder;
163    use crate::{CpuRenderer, Fill, FillRule, Func, GeomPresTransform, PathBuilder, Point, Style};
164
165    const BLACK_SRGB: [u8; 4] = [0x00, 0x00, 0x00, 0xFF];
166    const GRAY_SRGB: [u8; 4] = [0xBB, 0xBB, 0xBB, 0xFF];
167    const GRAY_ALPHA_50_SRGB: [u8; 4] = [0xBB, 0xBB, 0xBB, 0x80];
168    const WHITE_ALPHA_0_SRGB: [u8; 4] = [0xFF, 0xFF, 0xFF, 0x00];
169    const RED_SRGB: [u8; 4] = [0xFF, 0x00, 0x00, 0xFF];
170    const GREEN_SRGB: [u8; 4] = [0x00, 0xFF, 0x00, 0xFF];
171    const RED_50_GREEN_50_SRGB: [u8; 4] = [0xBB, 0xBB, 0x00, 0xFF];
172
173    const BLACK: Color = Color { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
174    const BLACK_ALPHA_50: Color = Color { r: 0.0, g: 0.0, b: 0.0, a: 0.5 };
175    const GRAY: Color = Color { r: 0.5, g: 0.5, b: 0.5, a: 1.0 };
176    const WHITE_TRANSPARENT: Color = Color { r: 1.0, g: 1.0, b: 1.0, a: 0.0 };
177    const RED: Color = Color { r: 1.0, g: 0.0, b: 0.0, a: 1.0 };
178    const GREEN: Color = Color { r: 0.0, g: 1.0, b: 0.0, a: 1.0 };
179
180    fn pixel_path(x: i32, y: i32) -> Path {
181        let mut builder = PathBuilder::new();
182
183        builder.move_to(Point::new(x as f32, y as f32));
184        builder.line_to(Point::new(x as f32, (y + 1) as f32));
185        builder.line_to(Point::new((x + 1) as f32, (y + 1) as f32));
186        builder.line_to(Point::new((x + 1) as f32, y as f32));
187        builder.line_to(Point::new(x as f32, y as f32));
188
189        builder.build()
190    }
191
192    fn solid(color: Color) -> Props {
193        Props {
194            func: Func::Draw(Style { fill: Fill::Solid(color), ..Default::default() }),
195            ..Default::default()
196        }
197    }
198
199    #[test]
200    fn composition_len() {
201        let mut composition = Composition::new();
202
203        assert!(composition.is_empty());
204        assert_eq!(composition.len(), 0);
205
206        composition.get_mut_or_insert_default(Order::new(0).unwrap());
207
208        assert!(!composition.is_empty());
209        assert_eq!(composition.len(), 1);
210    }
211
212    #[test]
213    fn background_color_clear() {
214        let mut buffer = [GREEN_SRGB].concat();
215        let mut layout = LinearLayout::new(1, 4, 1);
216
217        let mut composition = Composition::new();
218        let mut renderer = CpuRenderer::new();
219
220        renderer.render(
221            &mut composition,
222            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
223            RGBA,
224            RED,
225            None,
226        );
227
228        assert_eq!(buffer, [RED_SRGB].concat());
229    }
230
231    #[test]
232    fn background_color_clear_when_changed() {
233        let mut buffer = [GREEN_SRGB].concat();
234        let mut layout = LinearLayout::new(1, 4, 1);
235
236        let mut composition = Composition::new();
237        let mut renderer = CpuRenderer::new();
238        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
239
240        renderer.render(
241            &mut composition,
242            &mut BufferBuilder::new(&mut buffer, &mut layout)
243                .layer_cache(layer_cache.clone())
244                .build(),
245            RGBA,
246            RED,
247            None,
248        );
249
250        assert_eq!(buffer, [RED_SRGB].concat());
251
252        buffer = [GREEN_SRGB].concat();
253
254        renderer.render(
255            &mut composition,
256            &mut BufferBuilder::new(&mut buffer, &mut layout)
257                .layer_cache(layer_cache.clone())
258                .build(),
259            RGBA,
260            RED,
261            None,
262        );
263
264        // Skip clearing if the color is the same.
265        assert_eq!(buffer, [GREEN_SRGB].concat());
266
267        renderer.render(
268            &mut composition,
269            &mut BufferBuilder::new(&mut buffer, &mut layout).layer_cache(layer_cache).build(),
270            RGBA,
271            BLACK,
272            None,
273        );
274
275        assert_eq!(buffer, [BLACK_SRGB].concat());
276    }
277
278    #[test]
279    fn one_pixel() {
280        let mut buffer = [GREEN_SRGB; 3].concat();
281        let mut layout = LinearLayout::new(3, 3 * 4, 1);
282
283        let mut composition = Composition::new();
284        let mut renderer = CpuRenderer::new();
285
286        let mut layer = composition.create_layer();
287        layer.insert(&pixel_path(1, 0)).set_props(solid(RED));
288
289        composition.insert(Order::new(0).unwrap(), layer);
290
291        renderer.render(
292            &mut composition,
293            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
294            RGBA,
295            GREEN,
296            None,
297        );
298
299        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, GREEN_SRGB].concat());
300    }
301
302    #[test]
303    fn two_pixels_same_layer() {
304        let mut buffer = [GREEN_SRGB; 3].concat();
305        let mut layout = LinearLayout::new(3, 3 * 4, 1);
306        let mut composition = Composition::new();
307        let mut renderer = CpuRenderer::new();
308
309        let mut layer = composition.create_layer();
310        layer.insert(&pixel_path(1, 0)).insert(&pixel_path(2, 0)).set_props(solid(RED));
311
312        composition.insert(Order::new(0).unwrap(), layer);
313
314        renderer.render(
315            &mut composition,
316            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
317            RGBA,
318            GREEN,
319            None,
320        );
321
322        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, RED_SRGB].concat());
323    }
324
325    #[test]
326    fn one_pixel_translated() {
327        let mut buffer = [GREEN_SRGB; 3].concat();
328        let mut layout = LinearLayout::new(3, 3 * 4, 1);
329
330        let mut composition = Composition::new();
331        let mut renderer = CpuRenderer::new();
332
333        let mut layer = composition.create_layer();
334        layer
335            .insert(&pixel_path(1, 0))
336            .set_props(solid(RED))
337            .set_transform(GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 0.5, 0.0]).unwrap());
338
339        composition.insert(Order::new(0).unwrap(), layer);
340
341        renderer.render(
342            &mut composition,
343            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
344            RGBA,
345            GREEN,
346            None,
347        );
348
349        assert_eq!(buffer, [GREEN_SRGB, RED_50_GREEN_50_SRGB, RED_50_GREEN_50_SRGB].concat());
350    }
351
352    #[test]
353    fn one_pixel_rotated() {
354        let mut buffer = [GREEN_SRGB; 3].concat();
355        let mut layout = LinearLayout::new(3, 3 * 4, 1);
356
357        let mut composition = Composition::new();
358        let mut renderer = CpuRenderer::new();
359
360        let angle = -std::f32::consts::PI / 2.0;
361
362        let mut layer = composition.create_layer();
363        layer.insert(&pixel_path(-1, 1)).set_props(solid(RED)).set_transform(
364            GeomPresTransform::try_from([
365                angle.cos(),
366                -angle.sin(),
367                angle.sin(),
368                angle.cos(),
369                0.0,
370                0.0,
371            ])
372            .unwrap(),
373        );
374
375        composition.insert(Order::new(0).unwrap(), layer);
376
377        renderer.render(
378            &mut composition,
379            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
380            RGBA,
381            GREEN,
382            None,
383        );
384
385        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, GREEN_SRGB].concat());
386    }
387
388    #[test]
389    fn clear_and_resize() {
390        let mut buffer = [GREEN_SRGB; 4].concat();
391        let mut composition = Composition::new();
392        let mut renderer = CpuRenderer::new();
393
394        let order0 = Order::new(0).unwrap();
395        let order1 = Order::new(1).unwrap();
396        let order2 = Order::new(2).unwrap();
397
398        let mut layer0 = composition.create_layer();
399        layer0.insert(&pixel_path(0, 0)).set_props(solid(RED));
400
401        composition.insert(order0, layer0);
402
403        let mut layer1 = composition.create_layer();
404        layer1.insert(&pixel_path(1, 0)).set_props(solid(RED));
405
406        composition.insert(order1, layer1);
407
408        let mut layer2 = composition.create_layer();
409        layer2.insert(&pixel_path(2, 0)).insert(&pixel_path(3, 0)).set_props(solid(RED));
410
411        composition.insert(order2, layer2);
412
413        let mut layout = LinearLayout::new(4, 4 * 4, 1);
414
415        renderer.render(
416            &mut composition,
417            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
418            RGBA,
419            GREEN,
420            None,
421        );
422
423        assert_eq!(buffer, [RED_SRGB, RED_SRGB, RED_SRGB, RED_SRGB].concat());
424        assert_eq!(composition.builder_len(), 16);
425        assert_eq!(composition.actual_len(), 16);
426
427        buffer = [GREEN_SRGB; 4].concat();
428
429        let mut layout = LinearLayout::new(4, 4 * 4, 1);
430
431        composition.get_mut(order0).unwrap().clear();
432
433        renderer.render(
434            &mut composition,
435            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
436            RGBA,
437            GREEN,
438            None,
439        );
440
441        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, RED_SRGB, RED_SRGB].concat());
442        assert_eq!(composition.builder_len(), 16);
443        assert_eq!(composition.actual_len(), 12);
444
445        buffer = [GREEN_SRGB; 4].concat();
446
447        let mut layout = LinearLayout::new(4, 4 * 4, 1);
448
449        composition.get_mut(order2).unwrap().clear();
450
451        renderer.render(
452            &mut composition,
453            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
454            RGBA,
455            GREEN,
456            None,
457        );
458
459        assert_eq!(buffer, [GREEN_SRGB, RED_SRGB, GREEN_SRGB, GREEN_SRGB].concat());
460        assert_eq!(composition.builder_len(), 4);
461        assert_eq!(composition.actual_len(), 4);
462    }
463
464    #[test]
465    fn clear_twice() {
466        let mut composition = Composition::new();
467
468        let order = Order::new(0).unwrap();
469
470        let mut layer = composition.create_layer();
471        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
472
473        composition.insert(order, layer);
474
475        assert_eq!(composition.actual_len(), 4);
476
477        composition.get_mut(order).unwrap().clear();
478
479        assert_eq!(composition.actual_len(), 0);
480
481        composition.get_mut(order).unwrap().clear();
482
483        assert_eq!(composition.actual_len(), 0);
484    }
485
486    #[test]
487    fn insert_over_layer() {
488        let mut buffer = [BLACK_SRGB; 3].concat();
489        let mut layout = LinearLayout::new(3, 3 * 4, 1);
490
491        let mut composition = Composition::new();
492        let mut renderer = CpuRenderer::new();
493
494        let mut layer = composition.create_layer();
495        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
496
497        composition.insert(Order::new(0).unwrap(), layer);
498
499        renderer.render(
500            &mut composition,
501            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
502            RGBA,
503            BLACK,
504            None,
505        );
506
507        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
508
509        let mut layer = composition.create_layer();
510        layer.insert(&pixel_path(1, 0)).set_props(solid(GREEN));
511
512        buffer = [BLACK_SRGB; 3].concat();
513
514        renderer.render(
515            &mut composition,
516            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
517            RGBA,
518            BLACK,
519            None,
520        );
521
522        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
523
524        composition.insert(Order::new(0).unwrap(), layer);
525
526        buffer = [BLACK_SRGB; 3].concat();
527
528        renderer.render(
529            &mut composition,
530            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
531            RGBA,
532            BLACK,
533            None,
534        );
535
536        assert_eq!(buffer, [BLACK_SRGB, GREEN_SRGB, BLACK_SRGB].concat());
537    }
538
539    #[test]
540    fn layer_replace_remove() {
541        let mut buffer = [BLACK_SRGB; 3].concat();
542        let mut layout = LinearLayout::new(3, 3 * 4, 1);
543
544        let mut composition = Composition::new();
545        let mut renderer = CpuRenderer::new();
546
547        let mut layer = composition.create_layer();
548        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
549
550        composition.insert(Order::new(0).unwrap(), layer);
551
552        renderer.render(
553            &mut composition,
554            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
555            RGBA,
556            BLACK,
557            None,
558        );
559
560        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
561
562        let mut layer = composition.create_layer();
563        layer.insert(&pixel_path(1, 0)).set_props(solid(GREEN));
564
565        let _old_layer = composition.insert(Order::new(0).unwrap(), layer);
566
567        buffer = [BLACK_SRGB; 3].concat();
568
569        renderer.render(
570            &mut composition,
571            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
572            RGBA,
573            BLACK,
574            None,
575        );
576
577        assert_eq!(buffer, [BLACK_SRGB, GREEN_SRGB, BLACK_SRGB].concat());
578
579        let _old_layer = composition.remove(Order::new(0).unwrap());
580
581        buffer = [BLACK_SRGB; 3].concat();
582
583        renderer.render(
584            &mut composition,
585            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
586            RGBA,
587            BLACK,
588            None,
589        );
590
591        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
592    }
593
594    #[test]
595    fn layer_clear() {
596        let mut buffer = [BLACK_SRGB; 3].concat();
597        let mut layout = LinearLayout::new(3, 3 * 4, 1);
598
599        let mut composition = Composition::new();
600        let mut renderer = CpuRenderer::new();
601
602        let order = Order::new(0).unwrap();
603
604        let mut layer = composition.create_layer();
605        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
606
607        composition.insert(order, layer);
608
609        renderer.render(
610            &mut composition,
611            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
612            RGBA,
613            BLACK,
614            None,
615        );
616
617        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
618
619        composition.get_mut(order).unwrap().insert(&pixel_path(1, 0));
620
621        buffer = [BLACK_SRGB; 3].concat();
622
623        renderer.render(
624            &mut composition,
625            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
626            RGBA,
627            BLACK,
628            None,
629        );
630
631        assert_eq!(buffer, [RED_SRGB, RED_SRGB, BLACK_SRGB].concat());
632
633        composition.get_mut(order).unwrap().clear();
634
635        buffer = [BLACK_SRGB; 3].concat();
636
637        renderer.render(
638            &mut composition,
639            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
640            RGBA,
641            BLACK,
642            None,
643        );
644
645        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
646
647        composition.get_mut(order).unwrap().insert(&pixel_path(2, 0));
648
649        buffer = [BLACK_SRGB; 3].concat();
650
651        renderer.render(
652            &mut composition,
653            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
654            RGBA,
655            BLACK,
656            None,
657        );
658
659        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, RED_SRGB].concat());
660    }
661
662    #[test]
663    fn geom_id() {
664        let mut composition = Composition::new();
665
666        let mut layer = composition.create_layer();
667
668        layer.insert(&PathBuilder::new().build());
669        let geom_id0 = layer.geom_id();
670
671        layer.insert(&PathBuilder::new().build());
672        let geom_id1 = layer.geom_id();
673
674        assert_eq!(geom_id0, geom_id1);
675
676        layer.clear();
677
678        assert_ne!(layer.geom_id(), geom_id0);
679
680        layer.insert(&PathBuilder::new().build());
681        let geom_id2 = layer.geom_id();
682
683        assert_ne!(geom_id0, geom_id2);
684
685        let order = Order::new(0).unwrap();
686        composition.insert(order, layer);
687
688        assert_eq!(composition.get_order_if_stored(geom_id2), Some(order));
689
690        let layer = composition.create_layer();
691        composition.insert(order, layer);
692
693        assert_eq!(composition.get_order_if_stored(geom_id2), None);
694    }
695
696    #[test]
697    fn srgb_alpha_blending() {
698        let mut buffer = [BLACK_SRGB; 3].concat();
699        let mut layout = LinearLayout::new(3, 3 * 4, 1);
700
701        let mut composition = Composition::new();
702        let mut renderer = CpuRenderer::new();
703
704        let mut layer = composition.create_layer();
705        layer.insert(&pixel_path(0, 0)).set_props(solid(BLACK_ALPHA_50));
706
707        composition.insert(Order::new(0).unwrap(), layer);
708
709        let mut layer = composition.create_layer();
710
711        layer.insert(&pixel_path(1, 0)).set_props(solid(GRAY));
712
713        composition.insert(Order::new(1).unwrap(), layer);
714
715        renderer.render(
716            &mut composition,
717            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
718            RGBA,
719            WHITE_TRANSPARENT,
720            None,
721        );
722
723        assert_eq!(buffer, [GRAY_ALPHA_50_SRGB, GRAY_SRGB, WHITE_ALPHA_0_SRGB].concat());
724    }
725
726    #[test]
727    fn render_changed_layers_only() {
728        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
729        let mut layout = LinearLayout::new(3 * TILE_WIDTH, 3 * TILE_WIDTH * 4, TILE_HEIGHT);
730        let mut composition = Composition::new();
731        let mut renderer = CpuRenderer::new();
732        let layer_cache = renderer.create_buffer_layer_cache();
733
734        let mut layer = composition.create_layer();
735        layer
736            .insert(&pixel_path(0, 0))
737            .insert(&pixel_path(TILE_WIDTH as i32, 0))
738            .set_props(solid(RED));
739
740        composition.insert(Order::new(0).unwrap(), layer);
741
742        let order = Order::new(1).unwrap();
743
744        let mut layer = composition.create_layer();
745        layer
746            .insert(&pixel_path(TILE_WIDTH as i32 + 1, 0))
747            .insert(&pixel_path(2 * TILE_WIDTH as i32, 0))
748            .set_props(solid(GREEN));
749
750        composition.insert(order, layer);
751
752        renderer.render(
753            &mut composition,
754            &mut BufferBuilder::new(&mut buffer, &mut layout)
755                .layer_cache(layer_cache.clone().unwrap())
756                .build(),
757            RGBA,
758            BLACK,
759            None,
760        );
761
762        assert_eq!(buffer[0..4], RED_SRGB);
763        assert_eq!(buffer[TILE_WIDTH * 4..TILE_WIDTH * 4 + 4], RED_SRGB);
764        assert_eq!(buffer[(TILE_WIDTH + 1) * 4..(TILE_WIDTH + 1) * 4 + 4], GREEN_SRGB);
765        assert_eq!(buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4], GREEN_SRGB);
766
767        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
768
769        composition.get_mut(order).unwrap().set_props(solid(RED));
770
771        renderer.render(
772            &mut composition,
773            &mut BufferBuilder::new(&mut buffer, &mut layout)
774                .layer_cache(layer_cache.unwrap())
775                .build(),
776            RGBA,
777            BLACK,
778            None,
779        );
780
781        assert_eq!(buffer[0..4], BLACK_SRGB);
782        assert_eq!(buffer[TILE_WIDTH * 4..TILE_WIDTH * 4 + 4], RED_SRGB);
783        assert_eq!(buffer[(TILE_WIDTH + 1) * 4..(TILE_WIDTH + 1) * 4 + 4], RED_SRGB);
784        assert_eq!(buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4], RED_SRGB);
785    }
786
787    #[test]
788    fn insert_remove_same_order_will_not_render_again() {
789        let mut buffer = [BLACK_SRGB; 3].concat();
790        let mut layout = LinearLayout::new(3, 3 * 4, 1);
791
792        let mut composition = Composition::new();
793        let mut renderer = CpuRenderer::new();
794        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
795
796        let mut layer = composition.create_layer();
797        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
798
799        composition.insert(Order::new(0).unwrap(), layer);
800
801        renderer.render(
802            &mut composition,
803            &mut BufferBuilder::new(&mut buffer, &mut layout)
804                .layer_cache(layer_cache.clone())
805                .build(),
806            RGBA,
807            BLACK,
808            None,
809        );
810
811        assert_eq!(buffer, [RED_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
812
813        let layer = composition.remove(Order::new(0).unwrap()).unwrap();
814        composition.insert(Order::new(0).unwrap(), layer);
815
816        buffer = [BLACK_SRGB; 3].concat();
817
818        renderer.render(
819            &mut composition,
820            &mut BufferBuilder::new(&mut buffer, &mut layout).layer_cache(layer_cache).build(),
821            RGBA,
822            BLACK,
823            None,
824        );
825
826        assert_eq!(buffer, [BLACK_SRGB, BLACK_SRGB, BLACK_SRGB].concat());
827    }
828
829    #[test]
830    fn clear_emptied_tiles() {
831        let mut buffer = [BLACK_SRGB; 2 * TILE_WIDTH * TILE_HEIGHT].concat();
832        let mut layout = LinearLayout::new(2 * TILE_WIDTH, 2 * TILE_WIDTH * 4, TILE_HEIGHT);
833        let mut composition = Composition::new();
834        let mut renderer = CpuRenderer::new();
835        let layer_cache = renderer.create_buffer_layer_cache();
836
837        let order = Order::new(0).unwrap();
838
839        let mut layer = composition.create_layer();
840        layer
841            .insert(&pixel_path(0, 0))
842            .set_props(solid(RED))
843            .insert(&pixel_path(TILE_WIDTH as i32, 0));
844
845        composition.insert(order, layer);
846
847        renderer.render(
848            &mut composition,
849            &mut BufferBuilder::new(&mut buffer, &mut layout)
850                .layer_cache(layer_cache.clone().unwrap())
851                .build(),
852            RGBA,
853            BLACK,
854            None,
855        );
856
857        assert_eq!(buffer[0..4], RED_SRGB);
858
859        composition.get_mut(order).unwrap().set_transform(
860            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, TILE_WIDTH as f32, 0.0]).unwrap(),
861        );
862
863        renderer.render(
864            &mut composition,
865            &mut BufferBuilder::new(&mut buffer, &mut layout)
866                .layer_cache(layer_cache.clone().unwrap())
867                .build(),
868            RGBA,
869            BLACK,
870            None,
871        );
872
873        assert_eq!(buffer[0..4], BLACK_SRGB);
874
875        composition.get_mut(order).unwrap().set_transform(
876            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, -(TILE_WIDTH as f32), 0.0]).unwrap(),
877        );
878
879        renderer.render(
880            &mut composition,
881            &mut BufferBuilder::new(&mut buffer, &mut layout)
882                .layer_cache(layer_cache.clone().unwrap())
883                .build(),
884            RGBA,
885            BLACK,
886            None,
887        );
888
889        assert_eq!(buffer[0..4], RED_SRGB);
890
891        composition.get_mut(order).unwrap().set_transform(
892            GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 0.0, TILE_HEIGHT as f32]).unwrap(),
893        );
894
895        renderer.render(
896            &mut composition,
897            &mut BufferBuilder::new(&mut buffer, &mut layout)
898                .layer_cache(layer_cache.unwrap())
899                .build(),
900            RGBA,
901            BLACK,
902            None,
903        );
904
905        assert_eq!(buffer[0..4], BLACK_SRGB);
906    }
907
908    #[test]
909    fn separate_layer_caches() {
910        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
911        let mut layout = LinearLayout::new(TILE_WIDTH, TILE_WIDTH * 4, TILE_HEIGHT);
912        let mut composition = Composition::new();
913        let mut renderer = CpuRenderer::new();
914        let layer_cache0 = renderer.create_buffer_layer_cache();
915        let layer_cache1 = renderer.create_buffer_layer_cache();
916
917        let order = Order::new(0).unwrap();
918
919        let mut layer = composition.create_layer();
920        layer.insert(&pixel_path(0, 0)).set_props(solid(RED));
921
922        composition.insert(order, layer);
923
924        renderer.render(
925            &mut composition,
926            &mut BufferBuilder::new(&mut buffer, &mut layout)
927                .layer_cache(layer_cache0.clone().unwrap())
928                .build(),
929            RGBA,
930            BLACK,
931            None,
932        );
933
934        assert_eq!(buffer[0..4], RED_SRGB);
935
936        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
937
938        renderer.render(
939            &mut composition,
940            &mut BufferBuilder::new(&mut buffer, &mut layout)
941                .layer_cache(layer_cache0.clone().unwrap())
942                .build(),
943            RGBA,
944            BLACK,
945            None,
946        );
947
948        assert_eq!(buffer[0..4], BLACK_SRGB);
949
950        renderer.render(
951            &mut composition,
952            &mut BufferBuilder::new(&mut buffer, &mut layout)
953                .layer_cache(layer_cache1.clone().unwrap())
954                .build(),
955            RGBA,
956            BLACK,
957            None,
958        );
959
960        assert_eq!(buffer[0..4], RED_SRGB);
961
962        composition
963            .get_mut(order)
964            .unwrap()
965            .set_transform(GeomPresTransform::try_from([1.0, 0.0, 0.0, 1.0, 1.0, 0.0]).unwrap());
966
967        renderer.render(
968            &mut composition,
969            &mut BufferBuilder::new(&mut buffer, &mut layout)
970                .layer_cache(layer_cache0.unwrap())
971                .build(),
972            RGBA,
973            BLACK,
974            None,
975        );
976
977        assert_eq!(buffer[0..4], BLACK_SRGB);
978        assert_eq!(buffer[4..8], RED_SRGB);
979
980        let mut buffer = [BLACK_SRGB; TILE_WIDTH * TILE_HEIGHT].concat();
981
982        renderer.render(
983            &mut composition,
984            &mut BufferBuilder::new(&mut buffer, &mut layout)
985                .layer_cache(layer_cache1.unwrap())
986                .build(),
987            RGBA,
988            BLACK,
989            None,
990        );
991
992        assert_eq!(buffer[0..4], BLACK_SRGB);
993        assert_eq!(buffer[4..8], RED_SRGB);
994    }
995
996    #[test]
997    fn draw_if_width_or_height_change() {
998        let mut buffer = [BLACK_SRGB; 1].concat();
999        let mut layout = LinearLayout::new(1, 4, 1);
1000
1001        let mut composition = Composition::new();
1002        let mut renderer = CpuRenderer::new();
1003        let layer_cache = renderer.create_buffer_layer_cache().unwrap();
1004
1005        renderer.render(
1006            &mut composition,
1007            &mut BufferBuilder::new(&mut buffer, &mut layout)
1008                .layer_cache(layer_cache.clone())
1009                .build(),
1010            RGBA,
1011            RED,
1012            None,
1013        );
1014
1015        assert_eq!(buffer[0..4], RED_SRGB);
1016
1017        buffer = [BLACK_SRGB; 1].concat();
1018
1019        renderer.render(
1020            &mut composition,
1021            &mut BufferBuilder::new(&mut buffer, &mut layout)
1022                .layer_cache(layer_cache.clone())
1023                .build(),
1024            RGBA,
1025            RED,
1026            None,
1027        );
1028
1029        assert_eq!(buffer[0..4], BLACK_SRGB);
1030
1031        buffer = [BLACK_SRGB; 2].concat();
1032        layout = LinearLayout::new(2, 2 * 4, 1);
1033
1034        renderer.render(
1035            &mut composition,
1036            &mut BufferBuilder::new(&mut buffer, &mut layout)
1037                .layer_cache(layer_cache.clone())
1038                .build(),
1039            RGBA,
1040            RED,
1041            None,
1042        );
1043
1044        assert_eq!(buffer[0..8], [RED_SRGB; 2].concat());
1045
1046        buffer = [BLACK_SRGB; 2].concat();
1047        layout = LinearLayout::new(1, 4, 2);
1048
1049        renderer.render(
1050            &mut composition,
1051            &mut BufferBuilder::new(&mut buffer, &mut layout).layer_cache(layer_cache).build(),
1052            RGBA,
1053            RED,
1054            None,
1055        );
1056
1057        assert_eq!(buffer[0..8], [RED_SRGB; 2].concat());
1058    }
1059
1060    #[test]
1061    fn even_odd() {
1062        let mut builder = PathBuilder::new();
1063
1064        builder.move_to(Point::new(0.0, 0.0));
1065        builder.line_to(Point::new(0.0, TILE_HEIGHT as f32));
1066        builder.line_to(Point::new(3.0 * TILE_WIDTH as f32, TILE_HEIGHT as f32));
1067        builder.line_to(Point::new(3.0 * TILE_WIDTH as f32, 0.0));
1068        builder.line_to(Point::new(TILE_WIDTH as f32, 0.0));
1069        builder.line_to(Point::new(TILE_WIDTH as f32, TILE_HEIGHT as f32));
1070        builder.line_to(Point::new(2.0 * TILE_WIDTH as f32, TILE_HEIGHT as f32));
1071        builder.line_to(Point::new(2.0 * TILE_WIDTH as f32, 0.0));
1072        builder.line_to(Point::new(0.0, 0.0));
1073
1074        let path = builder.build();
1075
1076        let mut buffer = [BLACK_SRGB; 3 * TILE_WIDTH * TILE_HEIGHT].concat();
1077        let mut layout = LinearLayout::new(3 * TILE_WIDTH, 3 * TILE_WIDTH * 4, TILE_HEIGHT);
1078
1079        let mut composition = Composition::new();
1080        let mut renderer = CpuRenderer::new();
1081
1082        let mut layer = composition.create_layer();
1083        layer.insert(&path).set_props(Props {
1084            fill_rule: FillRule::EvenOdd,
1085            func: Func::Draw(Style { fill: Fill::Solid(RED), ..Default::default() }),
1086        });
1087
1088        composition.insert(Order::new(0).unwrap(), layer);
1089
1090        renderer.render(
1091            &mut composition,
1092            &mut BufferBuilder::new(&mut buffer, &mut layout).build(),
1093            RGBA,
1094            BLACK,
1095            None,
1096        );
1097
1098        assert_eq!(buffer[0..4], RED_SRGB);
1099        assert_eq!(buffer[TILE_WIDTH * 4..(TILE_WIDTH * 4 + 4)], BLACK_SRGB);
1100        assert_eq!(buffer[2 * TILE_WIDTH * 4..2 * TILE_WIDTH * 4 + 4], RED_SRGB);
1101    }
1102}