qrcode_rs/render/
string.rs1use crate::cast::As;
4use crate::render::{Canvas as RenderCanvas, Pixel};
5use crate::types::Color;
6
7pub trait Element: Copy {
8 fn default_color(color: Color) -> Self;
9 fn strlen(self) -> usize;
10 fn append_to_string(self, string: &mut String);
11}
12
13impl Element for char {
14 fn default_color(color: Color) -> Self {
15 color.select('\u{2588}', ' ')
16 }
17
18 fn strlen(self) -> usize {
19 self.len_utf8()
20 }
21
22 fn append_to_string(self, string: &mut String) {
23 string.push(self);
24 }
25}
26
27impl<'a> Element for &'a str {
28 fn default_color(color: Color) -> Self {
29 color.select("\u{2588}", " ")
30 }
31
32 fn strlen(self) -> usize {
33 self.len()
34 }
35
36 fn append_to_string(self, string: &mut String) {
37 string.push_str(self);
38 }
39}
40
41#[doc(hidden)]
42pub struct Canvas<P: Element> {
43 buffer: Vec<P>,
44 width: usize,
45 dark_pixel: P,
46 dark_cap_inc: isize,
47 capacity: isize,
48}
49
50impl<P: Element> Pixel for P {
51 type Image = String;
52 type Canvas = Canvas<Self>;
53
54 fn default_unit_size() -> (u32, u32) {
55 (1, 1)
56 }
57
58 fn default_color(color: Color) -> Self {
59 <Self as Element>::default_color(color)
60 }
61}
62
63impl<P: Element> RenderCanvas for Canvas<P> {
64 type Pixel = P;
65 type Image = String;
66
67 fn new(width: u32, height: u32, dark_pixel: P, light_pixel: P) -> Self {
68 let width = width.as_usize();
69 let height = height.as_isize();
70 let dark_cap = dark_pixel.strlen().as_isize();
71 let light_cap = light_pixel.strlen().as_isize();
72 Self {
73 buffer: vec![light_pixel; width * height.as_usize()],
74 width,
75 dark_pixel,
76 dark_cap_inc: dark_cap - light_cap,
77 capacity: light_cap * width.as_isize() * height + (height - 1),
78 }
79 }
80
81 fn draw_dark_pixel(&mut self, x: u32, y: u32) {
82 let x = x.as_usize();
83 let y = y.as_usize();
84 self.capacity += self.dark_cap_inc;
85 self.buffer[x + y * self.width] = self.dark_pixel;
86 }
87
88 fn into_image(self) -> String {
89 let mut result = String::with_capacity(self.capacity.as_usize());
90 for (i, pixel) in self.buffer.into_iter().enumerate() {
91 if i != 0 && i % self.width == 0 {
92 result.push('\n');
93 }
94 pixel.append_to_string(&mut result);
95 }
96 result
97 }
98}
99
100#[test]
101fn test_render_to_string() {
102 use crate::render::Renderer;
103
104 let colors = &[Color::Dark, Color::Light, Color::Light, Color::Dark];
105 let image: String = Renderer::<char>::new(colors, 2, 1).build();
106 assert_eq!(&image, " \n \u{2588} \n \u{2588} \n ");
107
108 let image2 = Renderer::new(colors, 2, 1).light_color("A").dark_color("!B!").module_dimensions(2, 2).build();
109
110 assert_eq!(
111 &image2,
112 "AAAAAAAA\n\
113 AAAAAAAA\n\
114 AA!B!!B!AAAA\n\
115 AA!B!!B!AAAA\n\
116 AAAA!B!!B!AA\n\
117 AAAA!B!!B!AA\n\
118 AAAAAAAA\n\
119 AAAAAAAA"
120 );
121}