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