1use 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#[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 #[inline]
68 pub fn new() -> Self {
69 Self::default()
70 }
71
72 #[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 #[inline]
114 pub fn is_empty(&self) -> bool {
115 self.layers.is_empty()
116 }
117
118 #[inline]
129 pub fn len(&self) -> usize {
130 self.layers.len()
131 }
132
133 #[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 #[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 #[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 #[inline]
257 pub fn get(&self, order: Order) -> Option<&Layer> {
258 self.layers.get(&order)
259 }
260
261 #[inline]
277 pub fn get_mut(&mut self, order: Order) -> Option<&mut Layer> {
278 self.layers.get_mut(&order)
279 }
280
281 #[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 #[inline]
321 pub fn layers(&self) -> impl ExactSizeIterator<Item = (Order, &Layer)> + '_ {
322 self.layers.iter().map(|(&order, layer)| (order, layer))
323 }
324
325 #[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 #[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 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}