sensehat_screen/
scroll.rs

1//! Scrolling for pixel frames on the LED Matrix.
2use super::{Clip, Offset, PixelFrame};
3use std::ops::Index;
4
5/// A sequence of frames
6#[derive(Debug, PartialEq)]
7pub enum FrameDirection {
8    RightToLeft,
9    LeftToRight,
10    BottomToTop,
11    TopToBottom,
12}
13
14/// A sequence of frames to be scrolled on the LED Matrix.
15#[derive(Debug, PartialEq)]
16pub struct FrameSequence {
17    clips: Vec<Clip>,
18    direction: FrameDirection,
19    position: usize,
20}
21
22impl FrameSequence {
23    /// Create a new `FrameSequence` from a reference to a `Scroll` and a `FrameDirection`.
24    fn new(scroll: &Scroll, direction: FrameDirection) -> Self {
25        let position = 0usize;
26        let clips = scroll.clips();
27        FrameSequence {
28            clips,
29            direction,
30            position,
31        }
32    }
33
34    /// Returns the number of positions that the frame sequence can render as pixel frames.
35    pub fn positions(&self) -> usize {
36        self.clips.len() * 8
37    }
38
39    // Returns the offset depending on the internal FrameDirection.
40    fn offset(&self, off: u8) -> Offset {
41        match self.direction {
42            FrameDirection::RightToLeft => Offset::left(off),
43            FrameDirection::LeftToRight => Offset::right(off),
44            FrameDirection::TopToBottom => Offset::bottom(off),
45            FrameDirection::BottomToTop => Offset::top(off),
46        }
47    }
48}
49
50impl Iterator for FrameSequence {
51    type Item = PixelFrame;
52
53    fn next(&mut self) -> Option<PixelFrame> {
54        let total_pos = self.positions();
55        match self.position {
56            n if n == (total_pos + 1) => None,
57            n if n == total_pos => {
58                self.position += 1;
59                Some(self.clips[self.clips.len() - 1].offset(self.offset(8)))
60            }
61            n => {
62                self.position += 1;
63                let frame = n / 8;
64                let offset = n % 8;
65                let f = self.clips[frame];
66                Some(f.offset(self.offset(offset as u8)))
67            }
68        }
69    }
70}
71
72/// A type representing a collection of `PixelFrame`s that may be scrolled.
73#[derive(Debug, PartialEq)]
74pub struct Scroll(Vec<PixelFrame>);
75
76impl Scroll {
77    /// Creates a new scroll from a slice of `PixelFrame`s.
78    ///
79    /// # Panics
80    /// The scroll needs at least 2 PixelFrames to be created.
81    pub fn new(frames: &[PixelFrame]) -> Self {
82        assert!(frames.len() > 1);
83        Scroll(frames.to_vec())
84    }
85
86    /// Returns `&[PixelFrame]` with the pixel frames that constitute this scroll.
87    pub fn frames(&self) -> &[PixelFrame] {
88        self.0.as_slice()
89    }
90
91    /// Returns `Vec<Clip>` with the pixel frames clips that may be rendered.
92    pub fn clips(&self) -> Vec<Clip> {
93        let mut iter = self.0.iter();
94        let mut clips = Vec::new();
95        let mut base_frame = iter.next().unwrap();
96        for next in iter {
97            clips.push(base_frame.build_clip(next));
98            base_frame = next;
99        }
100        clips
101    }
102
103    /// Reverse the order of the inner pixel frames.
104    pub fn reverse(&mut self) {
105        self.0.reverse();
106    }
107
108    /// Return the number of pixel frames in the scroll.
109    pub fn len(&self) -> usize {
110        self.0.len()
111    }
112
113    /// Returns `true` if the scroll has no pixel frames.
114    pub fn is_empty(&self) -> bool {
115        self.0.is_empty()
116    }
117
118    /// Returns a `FrameSequence` iterator that moves the frames from the right to the left.
119    pub fn right_to_left(&self) -> FrameSequence {
120        FrameSequence::new(self, FrameDirection::RightToLeft)
121    }
122
123    /// Returns a `FrameSequence` iterator that moves the frames from the left to the right.
124    pub fn left_to_right(&self) -> FrameSequence {
125        FrameSequence::new(self, FrameDirection::LeftToRight)
126    }
127
128    /// Returns a `FrameSequence` iterator that moves the frames from the top to the bottom.
129    pub fn top_to_bottom(&self) -> FrameSequence {
130        FrameSequence::new(self, FrameDirection::TopToBottom)
131    }
132
133    /// Returns a `FrameSequence` iterator that moves the frames from the bottom to the bottom.
134    pub fn bottom_to_top(&self) -> FrameSequence {
135        FrameSequence::new(self, FrameDirection::BottomToTop)
136    }
137}
138
139impl Index<usize> for Scroll {
140    type Output = PixelFrame;
141
142    fn index(&self, index: usize) -> &PixelFrame {
143        &self.0[index]
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::super::{fonts::FontCollection, PixelColor};
150    use super::*;
151
152    const BLK: PixelFrame = PixelFrame::BLACK;
153    const RED: PixelFrame = PixelFrame::RED;
154    const YLW: PixelFrame = PixelFrame::YELLOW;
155
156    const SCROLL_ONE: &[PixelFrame] = &[BLK, RED];
157    const SCROLL_TWO: &[PixelFrame] = &[BLK, RED, YLW];
158
159    // Helper function to generate a PixelFrame out of a utf16-encoded symbol,
160    // a stroke color, and a background color.
161    fn font_pixel_frames(s: &str, stroke: PixelColor, background: PixelColor) -> Vec<PixelFrame> {
162        let fonts = FontCollection::new();
163        let fstring = fonts.sanitize_str(s).unwrap();
164        fstring.pixel_frames(stroke, background)
165    }
166
167    #[test]
168    #[should_panic]
169    fn scroll_is_created_from_empty_slice_of_pixel_frames_will_panic() {
170        let _ = Scroll::new(&[]);
171    }
172
173    #[test]
174    #[should_panic]
175    fn scroll_is_created_from_slice_of_1_pixel_frame_will_panic() {
176        let _ = Scroll::new(&[PixelFrame::BLUE]);
177    }
178
179    #[test]
180    fn scroll_is_created_from_slice_of_at_least_2_pixel_frames() {
181        let scroll = Scroll::new(SCROLL_ONE);
182        assert_eq!(scroll, Scroll(SCROLL_ONE.to_vec()));
183    }
184
185    #[test]
186    fn scroll_has_clips_method_returns_slice_of_clips() {
187        let scroll = Scroll::new(SCROLL_ONE);
188        let expected_clips = vec![BLK.build_clip(&RED)];
189        assert_eq!(scroll.clips(), expected_clips);
190
191        let scroll = Scroll::new(SCROLL_TWO);
192        let expected_clips = vec![BLK.build_clip(&RED), RED.build_clip(&YLW)];
193        assert_eq!(scroll.clips(), expected_clips);
194    }
195
196    #[test]
197    fn scroll_has_frames_method_returns_slice_of_pixel_frames() {
198        let scroll = Scroll::new(SCROLL_ONE);
199        assert_eq!(scroll.frames(), SCROLL_ONE);
200    }
201
202    #[test]
203    fn scroll_has_reverse_method_returns_slice_of_pixel_frames() {
204        let mut scroll = Scroll::new(SCROLL_ONE);
205        scroll.reverse();
206        assert_eq!(scroll.frames(), &[RED, BLK]);
207    }
208
209    #[test]
210    fn scroll_has_len_method_returns_the_number_of_pixel_frames() {
211        let scroll = Scroll::new(&font_pixel_frames(
212            "áàäeéìiöòó",
213            PixelColor::WHITE,
214            PixelColor::BLUE,
215        ));
216        assert_eq!(scroll.len(), 10);
217    }
218
219    #[test]
220    fn scrolls_create_right_to_left_frame_sequence() {
221        let scroll = Scroll::new(SCROLL_ONE);
222        let sequence = scroll.right_to_left();
223        assert_eq!(
224            sequence,
225            FrameSequence {
226                clips: vec![BLK.build_clip(&RED)],
227                direction: FrameDirection::RightToLeft,
228                position: 0,
229            }
230        );
231    }
232
233    #[test]
234    fn scrolls_create_left_to_right_frame_sequence() {
235        let scroll = Scroll::new(SCROLL_ONE);
236        let sequence = scroll.left_to_right();
237        assert_eq!(
238            sequence,
239            FrameSequence {
240                clips: vec![BLK.build_clip(&RED)],
241                direction: FrameDirection::LeftToRight,
242                position: 0,
243            }
244        );
245    }
246
247    #[test]
248    fn scrolls_create_top_to_bottom_frame_sequence() {
249        let scroll = Scroll::new(SCROLL_ONE);
250        let sequence = scroll.top_to_bottom();
251        assert_eq!(
252            sequence,
253            FrameSequence {
254                clips: vec![BLK.build_clip(&RED)],
255                direction: FrameDirection::TopToBottom,
256                position: 0,
257            }
258        );
259    }
260
261    #[test]
262    fn scrolls_create_bottom_to_top_frame_sequence() {
263        let scroll = Scroll::new(SCROLL_ONE);
264        let sequence = scroll.bottom_to_top();
265        assert_eq!(
266            sequence,
267            FrameSequence {
268                clips: vec![BLK.build_clip(&RED)],
269                direction: FrameDirection::BottomToTop,
270                position: 0,
271            }
272        );
273    }
274
275    #[test]
276    fn scroll_implements_index_trait_with_pixel_frame_output() {
277        let scroll = Scroll::new(SCROLL_ONE);
278        assert_eq!(scroll[0], BLK);
279        assert_eq!(scroll[1], RED);
280    }
281
282    #[test]
283    #[should_panic]
284    fn scroll_implements_index_trait_with_pixel_frame_output_panics_when_out_of_bounds() {
285        let scroll = Scroll::new(SCROLL_ONE);
286        assert_eq!(scroll[4], BLK);
287    }
288
289    #[test]
290    fn frame_sequence_positions_method_returns_number_of_pixel_frame_positions() {
291        let scroll = Scroll::new(&font_pixel_frames(
292            "bas  bas  ",
293            PixelColor::YELLOW,
294            PixelColor::BLACK,
295        ));
296        let sequence = scroll.left_to_right();
297        assert_eq!(sequence.positions(), 72);
298    }
299
300    #[test]
301    fn frame_sequence_iterator_count_equals_number_of_positions_plus_one() {
302        let scroll = Scroll::new(&font_pixel_frames(
303            "bas",
304            PixelColor::YELLOW,
305            PixelColor::BLACK,
306        ));
307        let seq = scroll.left_to_right();
308        let positions_plus_one = seq.positions() + 1;
309        assert_eq!(seq.count(), positions_plus_one);
310    }
311
312    #[test]
313    fn frame_sequence_implements_iterator_of_pixel_frames_left_to_right() {
314        let scroll = Scroll::new(&font_pixel_frames(
315            "bás",
316            PixelColor::YELLOW,
317            PixelColor::BLACK,
318        ));
319
320        let mut seq = scroll.left_to_right();
321        let first_frame = seq.nth(0).unwrap();
322        assert_eq!(first_frame, scroll[0]);
323
324        let mut seq = scroll.left_to_right();
325        let nth_frame = seq.nth(1).unwrap();
326        assert_eq!(
327            nth_frame,
328            scroll[0].build_clip(&scroll[1]).offset(Offset::right(1))
329        );
330
331        let mut seq = scroll.left_to_right();
332        let nth_frame = seq.nth(2).unwrap();
333        assert_eq!(
334            nth_frame,
335            scroll[0].build_clip(&scroll[1]).offset(Offset::right(2))
336        );
337
338        let mut seq = scroll.left_to_right();
339        let nth_frame = seq.nth(3).unwrap();
340        assert_eq!(
341            nth_frame,
342            scroll[0].build_clip(&scroll[1]).offset(Offset::right(3))
343        );
344
345        let mut seq = scroll.left_to_right();
346        let nth_frame = seq.nth(4).unwrap();
347        assert_eq!(
348            nth_frame,
349            scroll[0].build_clip(&scroll[1]).offset(Offset::right(4))
350        );
351
352        let mut seq = scroll.left_to_right();
353        let nth_frame = seq.nth(5).unwrap();
354        assert_eq!(
355            nth_frame,
356            scroll[0].build_clip(&scroll[1]).offset(Offset::right(5))
357        );
358
359        let mut seq = scroll.left_to_right();
360        let nth_frame = seq.nth(6).unwrap();
361        assert_eq!(
362            nth_frame,
363            scroll[0].build_clip(&scroll[1]).offset(Offset::right(6))
364        );
365
366        let mut seq = scroll.left_to_right();
367        let nth_frame = seq.nth(7).unwrap();
368        assert_eq!(
369            nth_frame,
370            scroll[0].build_clip(&scroll[1]).offset(Offset::right(7))
371        );
372
373        let mut seq = scroll.left_to_right();
374        let eighth_frame = seq.nth(8).unwrap();
375        assert_eq!(eighth_frame, scroll[1]);
376
377        let mut seq = scroll.left_to_right();
378        let nth_frame = seq.nth(9).unwrap();
379        assert_eq!(
380            nth_frame,
381            scroll[1].build_clip(&scroll[2]).offset(Offset::right(1))
382        );
383
384        let mut seq = scroll.left_to_right();
385        let nth_frame = seq.nth(10).unwrap();
386        assert_eq!(
387            nth_frame,
388            scroll[1].build_clip(&scroll[2]).offset(Offset::right(2))
389        );
390
391        let mut seq = scroll.left_to_right();
392        let nth_frame = seq.nth(11).unwrap();
393        assert_eq!(
394            nth_frame,
395            scroll[1].build_clip(&scroll[2]).offset(Offset::right(3))
396        );
397
398        let mut seq = scroll.left_to_right();
399        let nth_frame = seq.nth(12).unwrap();
400        assert_eq!(
401            nth_frame,
402            scroll[1].build_clip(&scroll[2]).offset(Offset::right(4))
403        );
404
405        let mut seq = scroll.left_to_right();
406        let twelfth_frame = seq.nth(13).unwrap();
407        assert_eq!(
408            twelfth_frame,
409            scroll[1].build_clip(&scroll[2]).offset(Offset::right(5))
410        );
411
412        let mut seq = scroll.left_to_right();
413        let nth_frame = seq.nth(14).unwrap();
414        assert_eq!(
415            nth_frame,
416            scroll[1].build_clip(&scroll[2]).offset(Offset::right(6))
417        );
418
419        let mut seq = scroll.left_to_right();
420        let nth_frame = seq.nth(15).unwrap();
421        assert_eq!(
422            nth_frame,
423            scroll[1].build_clip(&scroll[2]).offset(Offset::right(7))
424        );
425
426        let mut seq = scroll.left_to_right();
427        let last_frame = seq.nth(16).unwrap();
428        assert_eq!(last_frame, scroll[2]);
429    }
430
431    #[test]
432    fn frame_sequence_implements_iterator_of_pixel_frames_right_to_left() {
433        let scroll = Scroll::new(&font_pixel_frames(
434            "áàä",
435            PixelColor::WHITE,
436            PixelColor::BLUE,
437        ));
438
439        let mut seq = scroll.right_to_left();
440        let first_frame = seq.nth(0).unwrap();
441        assert_eq!(first_frame, scroll[0]);
442
443        let mut seq = scroll.right_to_left();
444        let nth_frame = seq.nth(1).unwrap();
445        assert_eq!(
446            nth_frame,
447            scroll[0].build_clip(&scroll[1]).offset(Offset::left(1))
448        );
449
450        let mut seq = scroll.right_to_left();
451        let nth_frame = seq.nth(2).unwrap();
452        assert_eq!(
453            nth_frame,
454            scroll[0].build_clip(&scroll[1]).offset(Offset::left(2))
455        );
456
457        let mut seq = scroll.right_to_left();
458        let nth_frame = seq.nth(3).unwrap();
459        assert_eq!(
460            nth_frame,
461            scroll[0].build_clip(&scroll[1]).offset(Offset::left(3))
462        );
463
464        let mut seq = scroll.right_to_left();
465        let nth_frame = seq.nth(4).unwrap();
466        assert_eq!(
467            nth_frame,
468            scroll[0].build_clip(&scroll[1]).offset(Offset::left(4))
469        );
470
471        let mut seq = scroll.right_to_left();
472        let nth_frame = seq.nth(5).unwrap();
473        assert_eq!(
474            nth_frame,
475            scroll[0].build_clip(&scroll[1]).offset(Offset::left(5))
476        );
477
478        let mut seq = scroll.right_to_left();
479        let nth_frame = seq.nth(6).unwrap();
480        assert_eq!(
481            nth_frame,
482            scroll[0].build_clip(&scroll[1]).offset(Offset::left(6))
483        );
484
485        let mut seq = scroll.right_to_left();
486        let nth_frame = seq.nth(7).unwrap();
487        assert_eq!(
488            nth_frame,
489            scroll[0].build_clip(&scroll[1]).offset(Offset::left(7))
490        );
491
492        let mut seq = scroll.right_to_left();
493        let eighth_frame = seq.nth(8).unwrap();
494        assert_eq!(eighth_frame, scroll[1]);
495
496        let mut seq = scroll.right_to_left();
497        let nth_frame = seq.nth(9).unwrap();
498        assert_eq!(
499            nth_frame,
500            scroll[1].build_clip(&scroll[2]).offset(Offset::left(1))
501        );
502
503        let mut seq = scroll.right_to_left();
504        let nth_frame = seq.nth(10).unwrap();
505        assert_eq!(
506            nth_frame,
507            scroll[1].build_clip(&scroll[2]).offset(Offset::left(2))
508        );
509
510        let mut seq = scroll.right_to_left();
511        let nth_frame = seq.nth(11).unwrap();
512        assert_eq!(
513            nth_frame,
514            scroll[1].build_clip(&scroll[2]).offset(Offset::left(3))
515        );
516
517        let mut seq = scroll.right_to_left();
518        let nth_frame = seq.nth(12).unwrap();
519        assert_eq!(
520            nth_frame,
521            scroll[1].build_clip(&scroll[2]).offset(Offset::left(4))
522        );
523
524        let mut seq = scroll.right_to_left();
525        let twelfth_frame = seq.nth(13).unwrap();
526        assert_eq!(
527            twelfth_frame,
528            scroll[1].build_clip(&scroll[2]).offset(Offset::left(5))
529        );
530
531        let mut seq = scroll.right_to_left();
532        let nth_frame = seq.nth(14).unwrap();
533        assert_eq!(
534            nth_frame,
535            scroll[1].build_clip(&scroll[2]).offset(Offset::left(6))
536        );
537
538        let mut seq = scroll.right_to_left();
539        let nth_frame = seq.nth(15).unwrap();
540        assert_eq!(
541            nth_frame,
542            scroll[1].build_clip(&scroll[2]).offset(Offset::left(7))
543        );
544
545        let mut seq = scroll.right_to_left();
546        let last_frame = seq.nth(16).unwrap();
547        assert_eq!(last_frame, scroll[2]);
548    }
549
550    #[test]
551    fn frame_sequence_implements_iterator_of_pixel_frames_top_to_bottom() {
552        let scroll = Scroll::new(&font_pixel_frames(
553            "bás",
554            PixelColor::YELLOW,
555            PixelColor::BLACK,
556        ));
557
558        let mut seq = scroll.top_to_bottom();
559        let first_frame = seq.nth(0).unwrap();
560        assert_eq!(first_frame, scroll[0]);
561
562        let mut seq = scroll.top_to_bottom();
563        let nth_frame = seq.nth(1).unwrap();
564        assert_eq!(
565            nth_frame,
566            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(1))
567        );
568
569        let mut seq = scroll.top_to_bottom();
570        let nth_frame = seq.nth(2).unwrap();
571        assert_eq!(
572            nth_frame,
573            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(2))
574        );
575
576        let mut seq = scroll.top_to_bottom();
577        let nth_frame = seq.nth(3).unwrap();
578        assert_eq!(
579            nth_frame,
580            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(3))
581        );
582
583        let mut seq = scroll.top_to_bottom();
584        let nth_frame = seq.nth(4).unwrap();
585        assert_eq!(
586            nth_frame,
587            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(4))
588        );
589
590        let mut seq = scroll.top_to_bottom();
591        let nth_frame = seq.nth(5).unwrap();
592        assert_eq!(
593            nth_frame,
594            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(5))
595        );
596
597        let mut seq = scroll.top_to_bottom();
598        let nth_frame = seq.nth(6).unwrap();
599        assert_eq!(
600            nth_frame,
601            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(6))
602        );
603
604        let mut seq = scroll.top_to_bottom();
605        let nth_frame = seq.nth(7).unwrap();
606        assert_eq!(
607            nth_frame,
608            scroll[0].build_clip(&scroll[1]).offset(Offset::bottom(7))
609        );
610
611        let mut seq = scroll.top_to_bottom();
612        let eighth_frame = seq.nth(8).unwrap();
613        assert_eq!(eighth_frame, scroll[1]);
614
615        let mut seq = scroll.top_to_bottom();
616        let nth_frame = seq.nth(9).unwrap();
617        assert_eq!(
618            nth_frame,
619            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(1))
620        );
621
622        let mut seq = scroll.top_to_bottom();
623        let nth_frame = seq.nth(10).unwrap();
624        assert_eq!(
625            nth_frame,
626            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(2))
627        );
628
629        let mut seq = scroll.top_to_bottom();
630        let nth_frame = seq.nth(11).unwrap();
631        assert_eq!(
632            nth_frame,
633            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(3))
634        );
635
636        let mut seq = scroll.top_to_bottom();
637        let nth_frame = seq.nth(12).unwrap();
638        assert_eq!(
639            nth_frame,
640            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(4))
641        );
642
643        let mut seq = scroll.top_to_bottom();
644        let twelfth_frame = seq.nth(13).unwrap();
645        assert_eq!(
646            twelfth_frame,
647            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(5))
648        );
649
650        let mut seq = scroll.top_to_bottom();
651        let nth_frame = seq.nth(14).unwrap();
652        assert_eq!(
653            nth_frame,
654            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(6))
655        );
656
657        let mut seq = scroll.top_to_bottom();
658        let nth_frame = seq.nth(15).unwrap();
659        assert_eq!(
660            nth_frame,
661            scroll[1].build_clip(&scroll[2]).offset(Offset::bottom(7))
662        );
663
664        let mut seq = scroll.top_to_bottom();
665        let last_frame = seq.nth(16).unwrap();
666        assert_eq!(last_frame, scroll[2]);
667    }
668
669    #[test]
670    fn frame_sequence_implements_iterator_of_pixel_frames_bottom_to_top() {
671        let scroll = Scroll::new(&font_pixel_frames(
672            "áàä",
673            PixelColor::WHITE,
674            PixelColor::BLUE,
675        ));
676
677        let mut seq = scroll.bottom_to_top();
678        let first_frame = seq.nth(0).unwrap();
679        assert_eq!(first_frame, scroll[0]);
680
681        let mut seq = scroll.bottom_to_top();
682        let nth_frame = seq.nth(1).unwrap();
683        assert_eq!(
684            nth_frame,
685            scroll[0].build_clip(&scroll[1]).offset(Offset::top(1))
686        );
687
688        let mut seq = scroll.bottom_to_top();
689        let nth_frame = seq.nth(2).unwrap();
690        assert_eq!(
691            nth_frame,
692            scroll[0].build_clip(&scroll[1]).offset(Offset::top(2))
693        );
694
695        let mut seq = scroll.bottom_to_top();
696        let nth_frame = seq.nth(3).unwrap();
697        assert_eq!(
698            nth_frame,
699            scroll[0].build_clip(&scroll[1]).offset(Offset::top(3))
700        );
701
702        let mut seq = scroll.bottom_to_top();
703        let nth_frame = seq.nth(4).unwrap();
704        assert_eq!(
705            nth_frame,
706            scroll[0].build_clip(&scroll[1]).offset(Offset::top(4))
707        );
708
709        let mut seq = scroll.bottom_to_top();
710        let nth_frame = seq.nth(5).unwrap();
711        assert_eq!(
712            nth_frame,
713            scroll[0].build_clip(&scroll[1]).offset(Offset::top(5))
714        );
715
716        let mut seq = scroll.bottom_to_top();
717        let nth_frame = seq.nth(6).unwrap();
718        assert_eq!(
719            nth_frame,
720            scroll[0].build_clip(&scroll[1]).offset(Offset::top(6))
721        );
722
723        let mut seq = scroll.bottom_to_top();
724        let nth_frame = seq.nth(7).unwrap();
725        assert_eq!(
726            nth_frame,
727            scroll[0].build_clip(&scroll[1]).offset(Offset::top(7))
728        );
729
730        let mut seq = scroll.bottom_to_top();
731        let eighth_frame = seq.nth(8).unwrap();
732        assert_eq!(eighth_frame, scroll[1]);
733
734        let mut seq = scroll.bottom_to_top();
735        let nth_frame = seq.nth(9).unwrap();
736        assert_eq!(
737            nth_frame,
738            scroll[1].build_clip(&scroll[2]).offset(Offset::top(1))
739        );
740
741        let mut seq = scroll.bottom_to_top();
742        let nth_frame = seq.nth(10).unwrap();
743        assert_eq!(
744            nth_frame,
745            scroll[1].build_clip(&scroll[2]).offset(Offset::top(2))
746        );
747
748        let mut seq = scroll.bottom_to_top();
749        let nth_frame = seq.nth(11).unwrap();
750        assert_eq!(
751            nth_frame,
752            scroll[1].build_clip(&scroll[2]).offset(Offset::top(3))
753        );
754
755        let mut seq = scroll.bottom_to_top();
756        let nth_frame = seq.nth(12).unwrap();
757        assert_eq!(
758            nth_frame,
759            scroll[1].build_clip(&scroll[2]).offset(Offset::top(4))
760        );
761
762        let mut seq = scroll.bottom_to_top();
763        let twelfth_frame = seq.nth(13).unwrap();
764        assert_eq!(
765            twelfth_frame,
766            scroll[1].build_clip(&scroll[2]).offset(Offset::top(5))
767        );
768
769        let mut seq = scroll.bottom_to_top();
770        let nth_frame = seq.nth(14).unwrap();
771        assert_eq!(
772            nth_frame,
773            scroll[1].build_clip(&scroll[2]).offset(Offset::top(6))
774        );
775
776        let mut seq = scroll.bottom_to_top();
777        let nth_frame = seq.nth(15).unwrap();
778        assert_eq!(
779            nth_frame,
780            scroll[1].build_clip(&scroll[2]).offset(Offset::top(7))
781        );
782
783        let mut seq = scroll.bottom_to_top();
784        let last_frame = seq.nth(16).unwrap();
785        assert_eq!(last_frame, scroll[2]);
786    }
787}