1use crate::draw::*;
2use crate::color::*;
3use crate::context::*;
4use crate::draw_stream::*;
5
6use std::collections::{HashSet};
7use std::sync::*;
8use std::mem;
9use std::iter;
10
11use desync::{Desync};
12use futures::{Stream};
13use futures::task::{Waker};
14
15struct CanvasCore {
19 main_core: DrawStreamCore,
23
24 streams: Vec<Weak<Desync<DrawStreamCore>>>
26}
27
28impl CanvasCore {
29 pub fn write(&mut self, actions: Vec<Draw>) -> Vec<Waker> {
33 self.main_core.write(actions.iter().cloned());
35
36 let mut remove_idx = vec![];
38 let mut wakers = vec![];
39
40 for (idx, stream) in self.streams.iter().enumerate() {
41 if let Some(stream) = stream.upgrade() {
42 wakers.push(stream.sync(|stream| {
43 stream.write(iter::once(Draw::StartFrame));
44 stream.write(actions.iter().cloned());
45 stream.write(iter::once(Draw::ShowFrame));
46 stream.take_waker()
47 }));
48 } else {
49 remove_idx.push(idx);
50 }
51 }
52
53 if remove_idx.len() > 0 {
55 let remove_idx = remove_idx.into_iter().collect::<HashSet<_>>();
56 let old_streams = mem::take(&mut self.streams);
57
58 self.streams = old_streams.into_iter()
59 .enumerate()
60 .filter(|(idx, _item)| !remove_idx.contains(idx))
61 .map(|(_idx, item)| item)
62 .collect();
63 }
64
65 wakers.into_iter().flatten().collect()
67 }
68}
69
70pub struct Canvas {
82 core: Arc<Desync<CanvasCore>>
84}
85
86impl Canvas {
87 pub fn new() -> Canvas {
91 let mut core = CanvasCore {
93 main_core: DrawStreamCore::new(),
94 streams: vec![]
95 };
96
97 core.main_core.add_usage();
98 core.main_core.write(vec![
99 Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))
100 ].into_iter());
101
102 Canvas {
103 core: Arc::new(Desync::new(core))
104 }
105 }
106
107 pub fn write(&self, to_draw: Vec<Draw>) {
111 if to_draw.len() != 0 {
113 let wakers = self.core.sync(move |core| core.write(to_draw));
114 wakers.into_iter().for_each(|waker| waker.wake());
115 }
116 }
117
118 pub fn draw<FnAction>(&self, action: FnAction)
122 where FnAction: Send+FnOnce(&mut CanvasGraphicsContext) -> () {
123 self.core.sync(move |core| {
124 let mut graphics_context = CanvasGraphicsContext {
125 core: core,
126 pending: vec![]
127 };
128
129 action(&mut graphics_context);
130 })
131 }
132
133 pub fn stream(&self) -> impl Stream<Item=Draw>+Send {
137 let new_core = Arc::new(Desync::new(DrawStreamCore::new()));
139 let new_stream = DrawStream::with_core(&new_core);
140
141 let add_stream = Arc::clone(&new_core);
143 self.core.desync(move |core| {
144 add_stream.sync(|stream| {
146 stream.write(iter::once(Draw::ResetFrame));
147 stream.write(core.main_core.get_pending_drawing())
148 });
149
150 core.streams.push(Arc::downgrade(&add_stream));
152
153 add_stream.sync(|stream| stream.take_waker().map(|waker| waker.wake()));
155 });
156
157 new_stream
159 }
160
161 pub fn get_drawing(&self) -> Vec<Draw> {
165 self.core.sync(|core| core.main_core.get_pending_drawing().collect())
166 }
167}
168
169impl Clone for Canvas {
170 fn clone(&self) -> Canvas {
171 self.core.desync(|core| core.main_core.add_usage());
172
173 Canvas {
174 core: self.core.clone()
175 }
176 }
177}
178
179impl Drop for Canvas {
180 fn drop(&mut self) {
181 self.core.sync(|core| {
183 if core.main_core.finish_usage() == 0 {
184 core.streams.drain(..)
186 .map(|stream| {
187 if let Some(stream) = stream.upgrade() {
188 stream.sync(|stream| { stream.close(); stream.take_waker() })
189 } else {
190 None
191 }
192 })
193 .flatten()
194 .for_each(|waker| waker.wake());
195 }
196 });
197 }
198}
199
200pub struct CanvasGraphicsContext<'a> {
204 core: &'a mut CanvasCore,
205 pending: Vec<Draw>
206}
207
208impl<'a> GraphicsContext for CanvasGraphicsContext<'a> {
209 fn draw(&mut self, d: Draw) { self.pending.push(d); }
210}
211
212impl<'a> Drop for CanvasGraphicsContext<'a> {
213 fn drop(&mut self) {
214 let wakers = self.core.write(mem::take(&mut self.pending));
215 wakers.into_iter().for_each(|waker| waker.wake());
216 }
217}
218
219#[cfg(test)]
220mod test {
221 use super::*;
222 use crate::path::*;
223 use crate::font::*;
224 use crate::gradient::*;
225 use crate::font_face::*;
226 use crate::primitives::*;
227 use crate::transform2d::*;
228
229 use futures::prelude::*;
230 use futures::executor;
231
232 use std::thread::*;
233 use std::time::*;
234
235 #[test]
236 fn can_draw_to_canvas() {
237 let canvas = Canvas::new();
238
239 canvas.write(vec![Draw::Path(PathOp::NewPath)]);
240 }
241
242 #[test]
243 fn can_follow_canvas_stream() {
244 let canvas = Canvas::new();
245 let mut stream = canvas.stream();
246
247 spawn(move || {
249 sleep(Duration::from_millis(50));
250
251 canvas.write(vec![
252 Draw::Path(PathOp::NewPath),
253 Draw::Path(PathOp::Move(0.0, 0.0)),
254 Draw::Path(PathOp::Line(10.0, 0.0)),
255 Draw::Path(PathOp::Line(10.0, 10.0)),
256 Draw::Path(PathOp::Line(0.0, 10.0))
257 ]);
258 });
259
260 executor::block_on(async {
264 assert!(stream.next().await == Some(Draw::ResetFrame));
265 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
266 assert!(stream.next().await == Some(Draw::StartFrame));
267 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
268 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
269 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
270 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
271 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
272 assert!(stream.next().await == Some(Draw::ShowFrame));
273
274 assert!(stream.next().await == None);
276 })
277 }
278
279 #[test]
280 fn can_draw_using_gc() {
281 let canvas = Canvas::new();
282 let mut stream = canvas.stream();
283
284 canvas.draw(|gc| {
286 gc.new_path();
287 gc.move_to(0.0, 0.0);
288 gc.line_to(10.0, 0.0);
289 gc.line_to(10.0, 10.0);
290 gc.line_to(0.0, 10.0);
291 });
292
293 executor::block_on(async {
295 assert!(stream.next().await == Some(Draw::ResetFrame));
296 assert!(stream.next().await == Some(Draw::StartFrame));
297 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
298 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
299 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
300 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
301 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
302 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
303 assert!(stream.next().await == Some(Draw::ShowFrame));
304 });
305 }
306
307 #[test]
308 fn restore_rewinds_canvas() {
309 let canvas = Canvas::new();
310
311 canvas.draw(|gc| {
313 gc.new_path();
314 gc.move_to(0.0, 0.0);
315 gc.line_to(10.0, 0.0);
316 gc.line_to(10.0, 10.0);
317 gc.line_to(0.0, 10.0);
318
319 gc.store();
320 gc.new_path();
321 gc.rect(0.0,0.0, 100.0,100.0);
322 gc.restore();
323
324 gc.stroke();
325 });
326
327 let mut stream = canvas.stream();
329
330 executor::block_on(async {
331 assert!(stream.next().await == Some(Draw::ResetFrame));
332 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
333 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
334 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
335 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
336 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
337 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
338
339 assert!(stream.next().await == Some(Draw::Store));
341
342 assert!(stream.next().await == Some(Draw::Stroke));
343 })
344 }
345
346 #[test]
347 fn free_stored_buffer_after_restore() {
348 let canvas = Canvas::new();
349
350 canvas.draw(|gc| {
352 gc.new_path();
353 gc.move_to(0.0, 0.0);
354 gc.line_to(10.0, 0.0);
355 gc.line_to(10.0, 10.0);
356 gc.line_to(0.0, 10.0);
357
358 gc.store();
359 gc.new_path();
360 gc.rect(0.0,0.0, 100.0,100.0);
361 gc.restore();
362 gc.free_stored_buffer();
363
364 gc.stroke();
365 });
366
367 let mut stream = canvas.stream();
369
370 executor::block_on(async
371 {
372 assert!(stream.next().await == Some(Draw::ResetFrame));
373 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
374 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
375 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
376 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
377 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
378 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
379
380 assert!(stream.next().await == Some(Draw::Stroke));
381 })
382 }
383
384 #[test]
385 fn clip_interrupts_rewind() {
386 let canvas = Canvas::new();
387
388 canvas.draw(|gc| {
390 gc.new_path();
391 gc.move_to(0.0, 0.0);
392 gc.line_to(10.0, 0.0);
393 gc.line_to(10.0, 10.0);
394 gc.line_to(0.0, 10.0);
395
396 gc.store();
397 gc.clip();
398 gc.new_path();
399 gc.restore();
400 });
401
402 let mut stream = canvas.stream();
404 mem::drop(canvas);
405
406 executor::block_on(async {
407 assert!(stream.next().await == Some(Draw::ResetFrame));
408 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
409 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
410 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
411 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
412 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
413 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
414
415 assert!(stream.next().await == Some(Draw::Store));
416 assert!(stream.next().await == Some(Draw::Clip));
417 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
418 assert!(stream.next().await == Some(Draw::Restore));
419 })
420 }
421
422 #[test]
423 fn can_follow_many_streams() {
424 let canvas = Canvas::new();
425 let mut stream = canvas.stream();
426 let mut stream2 = canvas.stream();
427
428 spawn(move || {
430 sleep(Duration::from_millis(50));
431
432 canvas.write(vec![
433 Draw::Path(PathOp::NewPath),
434 Draw::Path(PathOp::Move(0.0, 0.0)),
435 Draw::Path(PathOp::Line(10.0, 0.0)),
436 Draw::Path(PathOp::Line(10.0, 10.0)),
437 Draw::Path(PathOp::Line(0.0, 10.0))
438 ]);
439 });
440
441 executor::block_on(async {
444 assert!(stream.next().await == Some(Draw::ResetFrame));
446 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
447 assert!(stream.next().await == Some(Draw::StartFrame));
448 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
449 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
450
451 assert!(stream2.next().await == Some(Draw::ResetFrame));
452 assert!(stream2.next().await == Some(Draw::StartFrame));
453 assert!(stream2.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
454 assert!(stream2.next().await == Some(Draw::Path(PathOp::NewPath)));
455 assert!(stream2.next().await == Some(Draw::Path(PathOp::Move(0.0, 0.0))));
456
457 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
458 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
459 assert!(stream.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
460
461 assert!(stream2.next().await == Some(Draw::Path(PathOp::Line(10.0, 0.0))));
462 assert!(stream2.next().await == Some(Draw::Path(PathOp::Line(10.0, 10.0))));
463 assert!(stream2.next().await == Some(Draw::Path(PathOp::Line(0.0, 10.0))));
464
465 assert!(stream.next().await == Some(Draw::ShowFrame));
467 assert!(stream2.next().await == Some(Draw::ShowFrame));
468
469 assert!(stream.next().await == None);
470 assert!(stream2.next().await == None);
471 });
472 }
473
474 #[test]
475 fn commands_after_clear_are_suppressed() {
476 let canvas = Canvas::new();
477 let mut stream = canvas.stream();
478
479 spawn(move || {
481 canvas.write(vec![
482 Draw::Path(PathOp::NewPath),
483 Draw::Path(PathOp::Move(0.0, 0.0)),
484 Draw::Path(PathOp::Line(10.0, 0.0)),
485 Draw::Path(PathOp::Line(10.0, 10.0)),
486 Draw::Path(PathOp::Line(0.0, 10.0))
487 ]);
488
489 sleep(Duration::from_millis(100));
491
492 canvas.write(vec![
493 Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 1.0)),
494 Draw::Path(PathOp::Move(200.0, 200.0)),
495 ]);
496 });
497
498 executor::block_on(async {
500 sleep(Duration::from_millis(200));
502
503 assert!(stream.next().await == Some(Draw::ResetFrame));
505 assert!(stream.next().await == Some(Draw::StartFrame));
506
507 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 1.0))));
509 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(200.0, 200.0))));
510 assert!(stream.next().await == Some(Draw::ShowFrame));
511
512 assert!(stream.next().await == None);
514 })
515 }
516
517 #[test]
518 fn clear_layer_0_removes_commands() {
519 let canvas = Canvas::new();
520
521 canvas.draw(|gc| {
523 gc.new_path();
524 gc.move_to(0.0, 0.0);
525 gc.line_to(10.0, 0.0);
526 gc.line_to(10.0, 10.0);
527 gc.line_to(0.0, 10.0);
528
529 gc.stroke();
530 gc.clear_layer();
531
532 gc.new_path();
533 gc.move_to(10.0, 10.0);
534 gc.fill();
535 });
536
537 let mut stream = canvas.stream();
539
540 executor::block_on(async {
541 assert!(stream.next().await == Some(Draw::ResetFrame));
542 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
543 assert!(stream.next().await == Some(Draw::Layer(LayerId(0))));
544 assert!(stream.next().await == Some(Draw::ClearLayer));
545 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
546 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(10.0, 10.0))));
547 assert!(stream.next().await == Some(Draw::Fill));
548 });
549 }
550
551 #[test]
552 fn clear_layer_only_removes_commands_for_the_current_layer() {
553 let canvas = Canvas::new();
554
555 canvas.draw(|gc| {
557 gc.new_path();
558 gc.move_to(20.0, 20.0);
559
560 gc.stroke();
561
562 gc.layer(LayerId(1));
563 gc.new_path();
564 gc.move_to(0.0, 0.0);
565 gc.line_to(10.0, 0.0);
566 gc.line_to(10.0, 10.0);
567 gc.line_to(0.0, 10.0);
568
569 gc.clear_layer();
570
571 gc.new_path();
572 gc.move_to(10.0, 10.0);
573 gc.fill();
574 });
575
576 let mut stream = canvas.stream();
578
579 executor::block_on(async {
580 assert!(stream.next().await == Some(Draw::ResetFrame));
581 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
582 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
583 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(20.0, 20.0))));
584 assert!(stream.next().await == Some(Draw::Stroke));
585
586 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
587 assert!(stream.next().await == Some(Draw::ClearLayer));
588 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
589 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(10.0, 10.0))));
590 assert!(stream.next().await == Some(Draw::Fill));
591 });
592 }
593
594 #[test]
595 fn clear_layer_does_not_clear_sprites() {
596 let canvas = Canvas::new();
597
598 canvas.draw(|gc| {
600 gc.new_path();
601 gc.move_to(20.0, 20.0);
602
603 gc.stroke();
604
605 gc.layer(LayerId(1));
606 gc.new_path();
607 gc.move_to(0.0, 0.0);
608 gc.line_to(10.0, 0.0);
609 gc.line_to(10.0, 10.0);
610 gc.line_to(0.0, 10.0);
611
612 gc.sprite(SpriteId(1));
613 gc.clear_sprite();
614
615 gc.new_path();
616 gc.move_to(10.0, 10.0);
617 gc.fill();
618
619 gc.layer(LayerId(1));
620 gc.clear_layer();
621
622 gc.fill();
623 });
624
625 let mut stream = canvas.stream();
627 println!("{:?}", canvas.get_drawing());
628
629 executor::block_on(async {
630 assert!(stream.next().await == Some(Draw::ResetFrame));
631 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
632 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
633 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(20.0, 20.0))));
634 assert!(stream.next().await == Some(Draw::Stroke));
635
636 assert!(stream.next().await == Some(Draw::Sprite(SpriteId(1))));
637 assert!(stream.next().await == Some(Draw::ClearSprite));
638 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
639 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(10.0, 10.0))));
640 assert!(stream.next().await == Some(Draw::Fill));
641
642 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
643 assert!(stream.next().await == Some(Draw::ClearLayer));
644 assert!(stream.next().await == Some(Draw::Fill));
645 });
646 }
647
648 #[test]
649 fn clear_layer_removes_pushed_transforms() {
650 let canvas = Canvas::new();
651
652 canvas.draw(|gc| {
654 gc.layer(LayerId(1));
655
656 gc.transform(Transform2D::identity());
657
658 gc.push_state();
659 gc.transform(Transform2D::scale(10.0, 10.0));
660 gc.pop_state();
661
662 gc.clear_layer();
663 });
664
665 let mut stream = canvas.stream();
667 println!("{:?}", canvas.get_drawing());
668
669 executor::block_on(async {
670 assert!(stream.next().await == Some(Draw::ResetFrame));
671 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
672 assert!(stream.next().await == Some(Draw::MultiplyTransform(Transform2D::identity())));
673 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
674 assert!(stream.next().await == Some(Draw::ClearLayer));
675 });
676 }
677
678 #[test]
679 fn pushed_transforms_kept_in_order() {
680 let canvas = Canvas::new();
681
682 canvas.draw(|gc| {
684 gc.layer(LayerId(1));
685
686 gc.transform(Transform2D::identity());
687
688 gc.push_state();
689 gc.transform(Transform2D::scale(10.0, 10.0));
690
691 gc.clear_layer();
692 });
693
694 let mut stream = canvas.stream();
696 println!("{:?}", canvas.get_drawing());
697
698 executor::block_on(async {
699 assert!(stream.next().await == Some(Draw::ResetFrame));
700 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
701 assert!(stream.next().await == Some(Draw::MultiplyTransform(Transform2D::identity())));
702 assert!(stream.next().await == Some(Draw::PushState));
703 assert!(stream.next().await == Some(Draw::MultiplyTransform(Transform2D::scale(10.0, 10.0))));
704 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
705 assert!(stream.next().await == Some(Draw::ClearLayer));
706 });
707 }
708
709 #[test]
710 fn font_definitions_survive_clear_layer() {
711 let canvas = Canvas::new();
712 let lato = CanvasFontFace::from_slice(include_bytes!("../test_data/Lato-Regular.ttf"));
713
714 canvas.draw(|gc| {
715 gc.layer(LayerId(1));
716
717 gc.define_font_data(FontId(1), lato.clone());
718 gc.set_font_size(FontId(1), 12.0);
719 gc.draw_text(FontId(1), "Test".to_string(), 100.0, 100.0);
720
721 gc.clear_layer();
722 gc.fill();
723 });
724
725 let mut stream = canvas.stream();
726
727 executor::block_on(async {
728 assert!(stream.next().await == Some(Draw::ResetFrame));
729 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
730
731 assert!(match stream.next().await { Some(Draw::Font(FontId(1), FontOp::UseFontDefinition(_))) => true, _ => false });
732 assert!(stream.next().await == Some(Draw::Font(FontId(1), FontOp::FontSize(12.0))));
733
734 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
735 assert!(stream.next().await == Some(Draw::ClearLayer));
736 assert!(stream.next().await == Some(Draw::Fill));
737 });
738 }
739
740 #[test]
741 fn only_one_font_definition_survives_clear_layer() {
742 let canvas = Canvas::new();
743 let lato = CanvasFontFace::from_slice(include_bytes!("../test_data/Lato-Regular.ttf"));
744
745 canvas.draw(|gc| {
746 gc.layer(LayerId(1));
747
748 gc.define_font_data(FontId(1), lato.clone());
749 gc.define_font_data(FontId(1), lato.clone());
750 gc.define_font_data(FontId(2), lato.clone());
751 gc.define_font_data(FontId(1), lato.clone());
752 gc.set_font_size(FontId(1), 12.0);
753 gc.draw_text(FontId(1), "Test".to_string(), 100.0, 100.0);
754
755 gc.clear_layer();
756 gc.fill();
757 });
758
759 let mut stream = canvas.stream();
760
761 executor::block_on(async {
762 assert!(stream.next().await == Some(Draw::ResetFrame));
763 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
764
765 assert!(match stream.next().await { Some(Draw::Font(FontId(2), FontOp::UseFontDefinition(_))) => true, _ => false });
766 assert!(match stream.next().await { Some(Draw::Font(FontId(1), FontOp::UseFontDefinition(_))) => true, _ => false });
767 assert!(stream.next().await == Some(Draw::Font(FontId(1), FontOp::FontSize(12.0))));
768
769 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
770 assert!(stream.next().await == Some(Draw::ClearLayer));
771 assert!(stream.next().await == Some(Draw::Fill));
772 });
773 }
774
775 #[test]
776 fn only_one_font_size_survives_clear_layer() {
777 let canvas = Canvas::new();
778 let lato = CanvasFontFace::from_slice(include_bytes!("../test_data/Lato-Regular.ttf"));
779
780 canvas.draw(|gc| {
781 gc.layer(LayerId(1));
782
783 gc.define_font_data(FontId(1), lato.clone());
784 gc.set_font_size(FontId(1), 16.0);
785 gc.set_font_size(FontId(1), 15.0);
786 gc.set_font_size(FontId(2), 18.0);
787 gc.set_font_size(FontId(1), 14.0);
788 gc.set_font_size(FontId(1), 13.0);
789 gc.set_font_size(FontId(1), 12.0);
790 gc.draw_text(FontId(1), "Test".to_string(), 100.0, 100.0);
791
792 gc.clear_layer();
793 gc.fill();
794 });
795
796 let mut stream = canvas.stream();
797
798 executor::block_on(async {
799 assert!(stream.next().await == Some(Draw::ResetFrame));
800 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
801
802 assert!(match stream.next().await { Some(Draw::Font(FontId(1), FontOp::UseFontDefinition(_))) => true, _ => false });
803 assert!(stream.next().await == Some(Draw::Font(FontId(2), FontOp::FontSize(18.0))));
804 assert!(stream.next().await == Some(Draw::Font(FontId(1), FontOp::FontSize(12.0))));
805
806 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
807 assert!(stream.next().await == Some(Draw::ClearLayer));
808 assert!(stream.next().await == Some(Draw::Fill));
809 });
810 }
811
812 #[test]
813 fn show_start_frames_cancel_out() {
814 let canvas = Canvas::new();
815
816 canvas.draw(|gc| {
817 gc.clear_canvas(Color::Rgba(0.0, 0.0, 0.0, 0.0));
818
819 gc.start_frame();
820 gc.new_path();
821 gc.start_frame();
822 gc.move_to(20.0, 20.0);
823
824 gc.start_frame();
825 gc.stroke();
826
827 gc.start_frame();
828 gc.layer(LayerId(1));
829 gc.start_frame();
830 gc.new_path();
831 gc.start_frame();
832 gc.move_to(0.0, 0.0);
833 gc.start_frame();
834 gc.line_to(10.0, 0.0);
835 gc.start_frame();
836 gc.line_to(10.0, 10.0);
837 gc.start_frame();
838 gc.line_to(0.0, 10.0);
839
840 gc.start_frame();
841 gc.clear_layer();
842
843 gc.start_frame();
844 gc.new_path();
845 gc.start_frame();
846 gc.move_to(10.0, 10.0);
847 gc.start_frame();
848 gc.fill();
849
850 gc.show_frame();
852 gc.show_frame();
853 gc.show_frame();
854 gc.show_frame();
855 gc.show_frame();
856 gc.show_frame();
857 gc.show_frame();
858 gc.show_frame();
859 gc.show_frame();
860 gc.show_frame();
861 gc.show_frame();
862 gc.show_frame();
863 });
864
865 let mut stream = canvas.stream();
866
867 executor::block_on(async {
869 assert!(stream.next().await == Some(Draw::ResetFrame));
870 assert!(stream.next().await == Some(Draw::StartFrame));
871 assert!(stream.next().await == Some(Draw::StartFrame));
872 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
873 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
874 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(20.0, 20.0))));
875 assert!(stream.next().await == Some(Draw::Stroke));
876
877 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
878 assert!(stream.next().await == Some(Draw::ClearLayer));
879 assert!(stream.next().await == Some(Draw::Path(PathOp::NewPath)));
880 assert!(stream.next().await == Some(Draw::Path(PathOp::Move(10.0, 10.0))));
881 assert!(stream.next().await == Some(Draw::Fill));
882
883 assert!(stream.next().await == Some(Draw::ShowFrame));
884 });
885 }
886
887 #[test]
888 fn gradient_definitions_survive_clear_layer() {
889 let canvas = Canvas::new();
890
891 canvas.draw(|gc| {
892 gc.layer(LayerId(1));
893
894 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
895 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
896 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
897
898 gc.clear_layer();
899 gc.fill();
900 });
901
902 let mut stream = canvas.stream();
903
904 executor::block_on(async {
905 assert!(stream.next().await == Some(Draw::ResetFrame));
906 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
907
908 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::Create(Color::Rgba(0.0, 0.1, 0.2, 0.3)))));
909 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0)))));
910 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0)))));
911
912 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
913 assert!(stream.next().await == Some(Draw::ClearLayer));
914 assert!(stream.next().await == Some(Draw::Fill));
915 });
916 }
917
918 #[test]
919 fn only_one_gradient_definition_survives_clear_layer() {
920 let canvas = Canvas::new();
921
922 canvas.draw(|gc| {
923 gc.layer(LayerId(1));
924
925 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
926 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
927 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
928
929 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
930 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
931 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
932
933 gc.clear_layer();
934 gc.fill();
935 });
936
937 let mut stream = canvas.stream();
938
939 executor::block_on(async {
940 assert!(stream.next().await == Some(Draw::ResetFrame));
941 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
942
943 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::Create(Color::Rgba(0.0, 0.1, 0.2, 0.3)))));
944 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0)))));
945 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0)))));
946
947 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
948 assert!(stream.next().await == Some(Draw::ClearLayer));
949 assert!(stream.next().await == Some(Draw::Fill));
950 });
951 }
952
953 #[test]
954 fn only_one_gradient_definition_survives_clear_other_layer() {
955 let canvas = Canvas::new();
956
957 canvas.draw(|gc| {
958 gc.layer(LayerId(0));
959
960 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
961 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
962 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
963
964 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
965 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
966 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
967
968 gc.layer(LayerId(1));
969 gc.clear_layer();
970 gc.fill();
971 });
972
973 let mut stream = canvas.stream();
974
975 executor::block_on(async {
976 assert!(stream.next().await == Some(Draw::ResetFrame));
977 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
978
979 assert!(stream.next().await == Some(Draw::Layer(LayerId(0))));
980 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::Create(Color::Rgba(0.0, 0.1, 0.2, 0.3)))));
981 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0)))));
982 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0)))));
983
984 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
985 assert!(stream.next().await == Some(Draw::ClearLayer));
986 assert!(stream.next().await == Some(Draw::Fill));
987 });
988 }
989
990 #[test]
991 fn used_gradient_survives_clear_other_layer() {
992 let canvas = Canvas::new();
993
994 canvas.draw(|gc| {
995 gc.layer(LayerId(0));
996
997 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
998 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
999 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
1000
1001 gc.fill_gradient(GradientId(2), 0.0, 1.0, 2.0, 3.0);
1002
1003 gc.create_gradient(GradientId(2), Color::Rgba(0.0, 0.1, 0.2, 0.3));
1004 gc.gradient_stop(GradientId(2), 0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0));
1005 gc.gradient_stop(GradientId(2), 1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0));
1006
1007 gc.layer(LayerId(1));
1008 gc.clear_layer();
1009 gc.fill();
1010 });
1011
1012 let mut stream = canvas.stream();
1013
1014 executor::block_on(async {
1015 assert!(stream.next().await == Some(Draw::ResetFrame));
1016 assert!(stream.next().await == Some(Draw::ClearCanvas(Color::Rgba(0.0, 0.0, 0.0, 0.0))));
1017
1018 assert!(stream.next().await == Some(Draw::Layer(LayerId(0))));
1019
1020 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::Create(Color::Rgba(0.0, 0.1, 0.2, 0.3)))));
1021 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0)))));
1022 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0)))));
1023
1024 assert!(stream.next().await == Some(Draw::FillGradient(GradientId(2), (0.0, 1.0), (2.0, 3.0))));
1025
1026 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::Create(Color::Rgba(0.0, 0.1, 0.2, 0.3)))));
1027 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(0.5, Color::Rgba(0.4, 0.5, 0.6, 1.0)))));
1028 assert!(stream.next().await == Some(Draw::Gradient(GradientId(2), GradientOp::AddStop(1.0, Color::Rgba(0.7, 0.8, 0.9, 1.0)))));
1029
1030 assert!(stream.next().await == Some(Draw::Layer(LayerId(1))));
1031 assert!(stream.next().await == Some(Draw::ClearLayer));
1032 assert!(stream.next().await == Some(Draw::Fill));
1033 });
1034 }
1035}