1use crate::cast::As;
4use crate::types::Color;
5use std::cmp::max;
6
7pub mod image;
8pub mod pic;
9pub mod string;
10pub mod svg;
11pub mod unicode;
12
13pub trait Pixel: Copy + Sized {
18 type Image: Sized + 'static;
20
21 type Canvas: Canvas<Pixel = Self, Image = Self::Image>;
24
25 fn default_unit_size() -> (u32, u32) {
27 (8, 8)
28 }
29
30 fn default_color(color: Color) -> Self;
32}
33
34pub trait Canvas: Sized {
36 type Pixel: Sized;
37 type Image: Sized;
38
39 fn new(width: u32, height: u32, dark_pixel: Self::Pixel, light_pixel: Self::Pixel) -> Self;
41
42 fn draw_dark_pixel(&mut self, x: u32, y: u32);
44
45 fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) {
46 for y in top..(top + height) {
47 for x in left..(left + width) {
48 self.draw_dark_pixel(x, y);
49 }
50 }
51 }
52
53 fn into_image(self) -> Self::Image;
55}
56
57pub struct Renderer<'a, P: Pixel> {
64 content: &'a [Color],
65 modules_count: u32, quiet_zone: u32,
67 module_size: (u32, u32),
68
69 dark_color: P,
70 light_color: P,
71 has_quiet_zone: bool,
72}
73
74impl<'a, P: Pixel> Renderer<'a, P> {
75 pub fn new(content: &'a [Color], modules_count: usize, quiet_zone: u32) -> Renderer<'a, P> {
81 assert!(modules_count * modules_count == content.len());
82 Renderer {
83 content,
84 modules_count: modules_count.as_u32(),
85 quiet_zone,
86 module_size: P::default_unit_size(),
87 dark_color: P::default_color(Color::Dark),
88 light_color: P::default_color(Color::Light),
89 has_quiet_zone: true,
90 }
91 }
92
93 pub fn dark_color(&mut self, color: P) -> &mut Self {
95 self.dark_color = color;
96 self
97 }
98
99 pub fn light_color(&mut self, color: P) -> &mut Self {
101 self.light_color = color;
102 self
103 }
104
105 pub fn quiet_zone(&mut self, has_quiet_zone: bool) -> &mut Self {
107 self.has_quiet_zone = has_quiet_zone;
108 self
109 }
110
111 #[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")]
113 pub fn module_size(&mut self, width: u32) -> &mut Self {
114 self.module_dimensions(width, width)
115 }
116
117 pub fn module_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
119 self.module_size = (max(width, 1), max(height, 1));
120 self
121 }
122
123 #[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")]
124 pub fn min_width(&mut self, width: u32) -> &mut Self {
125 self.min_dimensions(width, width)
126 }
127
128 pub fn min_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
137 let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
138 let width_in_modules = self.modules_count + quiet_zone;
139 let unit_width = (width + width_in_modules - 1) / width_in_modules;
140 let unit_height = (height + width_in_modules - 1) / width_in_modules;
141 self.module_dimensions(unit_width, unit_height)
142 }
143
144 pub fn max_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
156 let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
157 let width_in_modules = self.modules_count + quiet_zone;
158 let unit_width = width / width_in_modules;
159 let unit_height = height / width_in_modules;
160 self.module_dimensions(unit_width, unit_height)
161 }
162
163 #[deprecated(since = "0.4.0", note = "renamed to `.build()` to de-emphasize the image connection")]
165 pub fn to_image(&self) -> P::Image {
166 self.build()
167 }
168
169 pub fn build(&self) -> P::Image {
171 let w = self.modules_count;
172 let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 };
173 let width = w + 2 * qz;
174
175 let (mw, mh) = self.module_size;
176 let real_width = width * mw;
177 let real_height = width * mh;
178
179 let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color);
180 let mut i = 0;
181 for y in 0..width {
182 for x in 0..width {
183 if qz <= x && x < w + qz && qz <= y && y < w + qz {
184 if self.content[i] != Color::Light {
185 canvas.draw_dark_rect(x * mw, y * mh, mw, mh);
186 }
187 i += 1;
188 }
189 }
190 }
191
192 canvas.into_image()
193 }
194}
195
196