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> {
76 assert!(modules_count * modules_count == content.len());
77 Renderer {
78 content,
79 modules_count: modules_count.as_u32(),
80 quiet_zone,
81 module_size: P::default_unit_size(),
82 dark_color: P::default_color(Color::Dark),
83 light_color: P::default_color(Color::Light),
84 has_quiet_zone: true,
85 }
86 }
87
88 pub fn dark_color(&mut self, color: P) -> &mut Self {
90 self.dark_color = color;
91 self
92 }
93
94 pub fn light_color(&mut self, color: P) -> &mut Self {
96 self.light_color = color;
97 self
98 }
99
100 pub fn quiet_zone(&mut self, has_quiet_zone: bool) -> &mut Self {
102 self.has_quiet_zone = has_quiet_zone;
103 self
104 }
105
106 #[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")]
108 pub fn module_size(&mut self, width: u32) -> &mut Self {
109 self.module_dimensions(width, width)
110 }
111
112 pub fn module_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
114 self.module_size = (max(width, 1), max(height, 1));
115 self
116 }
117
118 #[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")]
119 pub fn min_width(&mut self, width: u32) -> &mut Self {
120 self.min_dimensions(width, width)
121 }
122
123 pub fn min_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
132 let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
133 let width_in_modules = self.modules_count + quiet_zone;
134 let unit_width = (width + width_in_modules - 1) / width_in_modules;
135 let unit_height = (height + width_in_modules - 1) / width_in_modules;
136 self.module_dimensions(unit_width, unit_height)
137 }
138
139 pub fn max_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
151 let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
152 let width_in_modules = self.modules_count + quiet_zone;
153 let unit_width = width / width_in_modules;
154 let unit_height = height / width_in_modules;
155 self.module_dimensions(unit_width, unit_height)
156 }
157
158 #[deprecated(since = "0.4.0", note = "renamed to `.build()` to de-emphasize the image connection")]
160 pub fn to_image(&self) -> P::Image {
161 self.build()
162 }
163
164 pub fn build(&self) -> P::Image {
166 let w = self.modules_count;
167 let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 };
168 let width = w + 2 * qz;
169
170 let (mw, mh) = self.module_size;
171 let real_width = width * mw;
172 let real_height = width * mh;
173
174 let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color);
175 let mut i = 0;
176 for y in 0..width {
177 for x in 0..width {
178 if qz <= x && x < w + qz && qz <= y && y < w + qz {
179 if self.content[i] != Color::Light {
180 canvas.draw_dark_rect(x * mw, y * mh, mw, mh);
181 }
182 i += 1;
183 }
184 }
185 }
186
187 canvas.into_image()
188 }
189}
190
191