1 use {
2     crate::{
3         display::W,
4         errors::ProgramError,
5     },
6     ansi_colours,
7     crossterm::{
8         style::{
9             Color,
10             Colors,
11             Print,
12             SetColors,
13         },
14         QueueableCommand,
15     },
16     image::Rgba,
17     termimad::fill_bg,
18 };
19 
20 const UPPER_HALF_BLOCK: char = '▀';
21 
22 /// A "double line" normaly contains two lines of pixels
23 /// which are displayed as one line of characters, the
24 /// UPPER_HALF_BLOCK foreground for the upper pixel and
25 /// the background of the char for the lower pixel.
26 /// It acts as a buffer which is dumped to screen when
27 /// full or when the image is totally read.
28 pub struct DoubleLine {
29     img_width: usize,
30     pixels: Vec<Color>, // size twice img_width
31     true_colors: bool,
32 }
33 
34 impl DoubleLine {
new(img_width: usize, true_colors: bool) -> Self35     pub fn new(img_width: usize, true_colors: bool) -> Self {
36         Self {
37             img_width,
38             pixels: Vec::with_capacity(2 * img_width),
39             true_colors,
40         }
41     }
push(&mut self, rgba: Rgba<u8>)42     pub fn push(&mut self, rgba: Rgba<u8>) {
43         self.pixels.push(
44             if self.true_colors {
45                 Color::Rgb {
46                     r: rgba[0],
47                     g: rgba[1],
48                     b: rgba[2],
49                 }
50             } else {
51                 Color::AnsiValue(ansi_colours::ansi256_from_rgb((
52                     rgba[0],
53                     rgba[1],
54                     rgba[2],
55                 )))
56             }
57         );
58     }
is_empty(&self) -> bool59     pub fn is_empty(&self) -> bool {
60         self.pixels.is_empty()
61     }
is_full(&self) -> bool62     pub fn is_full(&self) -> bool {
63         self.pixels.len() == 2 * self.img_width
64     }
write( &mut self, w: &mut W, left_margin: usize, right_margin: usize, bg: Color, ) -> Result<(), ProgramError>65     pub fn write(
66         &mut self,
67         w: &mut W,
68         left_margin: usize,
69         right_margin: usize,
70         bg: Color,
71     ) -> Result<(), ProgramError> {
72         debug_assert!(
73             self.pixels.len() == self.img_width || self.pixels.len() == 2 * self.img_width
74         );
75         // we may have either one or two lines
76         let simple = self.pixels.len() < 2 * self.img_width;
77         fill_bg(w, left_margin, bg)?;
78         for i in 0..self.img_width {
79             let foreground_color = self.pixels[i];
80             let background_color = if simple {
81                 bg
82             } else {
83                 self.pixels[i + self.img_width]
84             };
85             w.queue(SetColors(Colors::new(
86                 foreground_color,
87                 background_color,
88             )))?;
89             w.queue(Print(UPPER_HALF_BLOCK))?;
90         }
91         fill_bg(w, right_margin, bg)?;
92         self.pixels.clear();
93         Ok(())
94     }
95 }
96 
97