1use 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 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}