xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/qr_code-2.0.0/src/canvas.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //! The `canvas` module puts raw bits into the QR code canvas.
2 //!
3 //!     use qr_code::types::{Version, EcLevel};
4 //!     use qr_code::canvas::{Canvas, MaskPattern};
5 //!
6 //!     let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
7 //!     c.draw_all_functional_patterns();
8 //!     c.draw_data(b"data_here", b"ec_code_here");
9 //!     c.apply_mask(MaskPattern::Checkerboard);
10 //!     let bools = c.to_bools();
11 
12 use std::cmp::max;
13 
14 use crate::cast::As;
15 use crate::types::{Color, EcLevel, Version};
16 
17 //------------------------------------------------------------------------------
18 //{{{ Modules
19 
20 /// The color of a module (pixel) in the QR code.
21 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
22 pub enum Module {
23     /// The module is empty.
24     Empty,
25 
26     /// The module is of functional patterns which cannot be masked, or pixels
27     /// which have been masked.
28     Masked(Color),
29 
30     /// The module is of data and error correction bits before masking.
31     Unmasked(Color),
32 }
33 
34 impl From<Module> for Color {
from(module: Module) -> Self35     fn from(module: Module) -> Self {
36         match module {
37             Module::Empty => Color::Light,
38             Module::Masked(c) | Module::Unmasked(c) => c,
39         }
40     }
41 }
42 
43 impl Module {
44     /// Checks whether a module is dark.
is_dark(self) -> bool45     pub fn is_dark(self) -> bool {
46         Color::from(self) == Color::Dark
47     }
48 
49     /// Apply a mask to the unmasked modules.
50     ///
51     ///     use qr_code::canvas::Module;
52     ///     use qr_code::types::Color;
53     ///
54     ///     assert_eq!(Module::Unmasked(Color::Light).mask(true), Module::Masked(Color::Dark));
55     ///     assert_eq!(Module::Unmasked(Color::Dark).mask(true), Module::Masked(Color::Light));
56     ///     assert_eq!(Module::Unmasked(Color::Light).mask(false), Module::Masked(Color::Light));
57     ///     assert_eq!(Module::Masked(Color::Dark).mask(true), Module::Masked(Color::Dark));
58     ///     assert_eq!(Module::Masked(Color::Dark).mask(false), Module::Masked(Color::Dark));
59     ///
mask(self, should_invert: bool) -> Self60     pub fn mask(self, should_invert: bool) -> Self {
61         match (self, should_invert) {
62             (Module::Empty, true) => Module::Masked(Color::Dark),
63             (Module::Empty, false) => Module::Masked(Color::Light),
64             (Module::Unmasked(c), true) => Module::Masked(!c),
65             (Module::Unmasked(c), false) | (Module::Masked(c), _) => Module::Masked(c),
66         }
67     }
68 }
69 
70 //}}}
71 //------------------------------------------------------------------------------
72 //{{{ Canvas
73 
74 /// `Canvas` is an intermediate helper structure to render error-corrected data
75 /// into a QR code.
76 #[derive(Clone)]
77 pub struct Canvas {
78     /// The width and height of the canvas (cached as it is needed frequently).
79     width: i16,
80 
81     /// The version of the QR code.
82     version: Version,
83 
84     /// The error correction level of the QR code.
85     ec_level: EcLevel,
86 
87     /// The modules of the QR code. Modules are arranged in left-to-right, then
88     /// top-to-bottom order.
89     modules: Vec<Module>,
90 }
91 
92 impl Canvas {
93     /// Constructs a new canvas big enough for a QR code of the given version.
new(version: Version, ec_level: EcLevel) -> Self94     pub fn new(version: Version, ec_level: EcLevel) -> Self {
95         let width = version.width();
96         Self {
97             width,
98             version,
99             ec_level,
100             modules: vec![Module::Empty; (width * width).as_usize()],
101         }
102     }
103 
104     /// Converts the canvas into a human-readable string.
105     #[cfg(test)]
to_debug_str(&self) -> String106     fn to_debug_str(&self) -> String {
107         let width = self.width;
108         let mut res = String::with_capacity((width * (width + 1)) as usize);
109         for y in 0..width {
110             res.push('\n');
111             for x in 0..width {
112                 res.push(match self.get(x, y) {
113                     Module::Empty => '?',
114                     Module::Masked(Color::Light) => '.',
115                     Module::Masked(Color::Dark) => '#',
116                     Module::Unmasked(Color::Light) => '-',
117                     Module::Unmasked(Color::Dark) => '*',
118                 });
119             }
120         }
121         res
122     }
123 
coords_to_index(&self, x: i16, y: i16) -> usize124     fn coords_to_index(&self, x: i16, y: i16) -> usize {
125         let x = if x < 0 { x + self.width } else { x }.as_usize();
126         let y = if y < 0 { y + self.width } else { y }.as_usize();
127         y * self.width.as_usize() + x
128     }
129 
130     /// Obtains a module at the given coordinates. For convenience, negative
131     /// coordinates will wrap around.
get(&self, x: i16, y: i16) -> Module132     pub fn get(&self, x: i16, y: i16) -> Module {
133         self.modules[self.coords_to_index(x, y)]
134     }
135 
136     /// Obtains a mutable module at the given coordinates. For convenience,
137     /// negative coordinates will wrap around.
get_mut(&mut self, x: i16, y: i16) -> &mut Module138     pub fn get_mut(&mut self, x: i16, y: i16) -> &mut Module {
139         let index = self.coords_to_index(x, y);
140         &mut self.modules[index]
141     }
142 
143     /// Sets the color of a functional module at the given coordinates. For
144     /// convenience, negative coordinates will wrap around.
put(&mut self, x: i16, y: i16, color: Color)145     pub fn put(&mut self, x: i16, y: i16, color: Color) {
146         *self.get_mut(x, y) = Module::Masked(color);
147     }
148 }
149 
150 #[cfg(test)]
151 mod basic_canvas_tests {
152     use crate::canvas::{Canvas, Module};
153     use crate::types::{Color, EcLevel, Version};
154 
155     #[test]
test_index()156     fn test_index() {
157         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
158 
159         assert_eq!(c.get(0, 4), Module::Empty);
160         assert_eq!(c.get(-1, -7), Module::Empty);
161         assert_eq!(c.get(21 - 1, 21 - 7), Module::Empty);
162 
163         c.put(0, 0, Color::Dark);
164         c.put(-1, -7, Color::Light);
165         assert_eq!(c.get(0, 0), Module::Masked(Color::Dark));
166         assert_eq!(c.get(21 - 1, -7), Module::Masked(Color::Light));
167         assert_eq!(c.get(-1, 21 - 7), Module::Masked(Color::Light));
168     }
169 
170     #[test]
test_debug_str()171     fn test_debug_str() {
172         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
173 
174         for i in 3_i16..20 {
175             for j in 3_i16..20 {
176                 *c.get_mut(i, j) = match ((i * 3) ^ j) % 5 {
177                     0 => Module::Empty,
178                     1 => Module::Masked(Color::Light),
179                     2 => Module::Masked(Color::Dark),
180                     3 => Module::Unmasked(Color::Light),
181                     4 => Module::Unmasked(Color::Dark),
182                     _ => unreachable!(),
183                 };
184             }
185         }
186 
187         assert_eq!(
188             &*c.to_debug_str(),
189             "\n\
190              ?????????????????????\n\
191              ?????????????????????\n\
192              ?????????????????????\n\
193              ?????####****....---?\n\
194              ???--.##-..##?..#??.?\n\
195              ???#*?-.*?#.-*#?-*.??\n\
196              ?????*?*?****-*-*---?\n\
197              ???*.-.-.-?-?#?#?#*#?\n\
198              ???.*#.*.*#.*#*#.*#*?\n\
199              ?????.#-#--??.?.#---?\n\
200              ???-.?*.-#?-.?#*-#?.?\n\
201              ???##*??*..##*--*..??\n\
202              ?????-???--??---?---?\n\
203              ???*.#.*.#**.#*#.#*#?\n\
204              ???##.-##..##..?#..??\n\
205              ???.-?*.-?#.-?#*-?#*?\n\
206              ????-.#?-.**#?-.#?-.?\n\
207              ???**?-**??--**?-**??\n\
208              ???#?*?#?*#.*-.-*-.-?\n\
209              ???..-...--??###?###?\n\
210              ?????????????????????"
211         );
212     }
213 }
214 
215 //}}}
216 //------------------------------------------------------------------------------
217 //{{{ Finder patterns
218 
219 impl Canvas {
220     /// Draws a single finder pattern with the center at (x, y).
draw_finder_pattern_at(&mut self, x: i16, y: i16)221     fn draw_finder_pattern_at(&mut self, x: i16, y: i16) {
222         let (dx_left, dx_right) = if x >= 0 { (-3, 4) } else { (-4, 3) };
223         let (dy_top, dy_bottom) = if y >= 0 { (-3, 4) } else { (-4, 3) };
224         for j in dy_top..=dy_bottom {
225             for i in dx_left..=dx_right {
226                 self.put(
227                     x + i,
228                     y + j,
229                     #[allow(clippy::match_same_arms)]
230                     match (i, j) {
231                         (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light,
232                         (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark,
233                         (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light,
234                         _ => Color::Dark,
235                     },
236                 );
237             }
238         }
239     }
240 
241     /// Draws the finder patterns.
242     ///
243     /// The finder patterns is are 7×7 square patterns appearing at the three
244     /// corners of a QR code. They allows scanner to locate the QR code and
245     /// determine the orientation.
draw_finder_patterns(&mut self)246     fn draw_finder_patterns(&mut self) {
247         self.draw_finder_pattern_at(3, 3);
248 
249         match self.version {
250             Version::Micro(_) => {}
251             Version::Normal(_) => {
252                 self.draw_finder_pattern_at(-4, 3);
253                 self.draw_finder_pattern_at(3, -4);
254             }
255         }
256     }
257 }
258 
259 #[cfg(test)]
260 mod finder_pattern_tests {
261     use crate::canvas::Canvas;
262     use crate::types::{EcLevel, Version};
263 
264     #[test]
test_qr()265     fn test_qr() {
266         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
267         c.draw_finder_patterns();
268         assert_eq!(
269             &*c.to_debug_str(),
270             "\n\
271              #######.?????.#######\n\
272              #.....#.?????.#.....#\n\
273              #.###.#.?????.#.###.#\n\
274              #.###.#.?????.#.###.#\n\
275              #.###.#.?????.#.###.#\n\
276              #.....#.?????.#.....#\n\
277              #######.?????.#######\n\
278              ........?????........\n\
279              ?????????????????????\n\
280              ?????????????????????\n\
281              ?????????????????????\n\
282              ?????????????????????\n\
283              ?????????????????????\n\
284              ........?????????????\n\
285              #######.?????????????\n\
286              #.....#.?????????????\n\
287              #.###.#.?????????????\n\
288              #.###.#.?????????????\n\
289              #.###.#.?????????????\n\
290              #.....#.?????????????\n\
291              #######.?????????????"
292         );
293     }
294 
295     #[test]
test_micro_qr()296     fn test_micro_qr() {
297         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
298         c.draw_finder_patterns();
299         assert_eq!(
300             &*c.to_debug_str(),
301             "\n\
302              #######.???\n\
303              #.....#.???\n\
304              #.###.#.???\n\
305              #.###.#.???\n\
306              #.###.#.???\n\
307              #.....#.???\n\
308              #######.???\n\
309              ........???\n\
310              ???????????\n\
311              ???????????\n\
312              ???????????"
313         );
314     }
315 }
316 
317 //}}}
318 //------------------------------------------------------------------------------
319 //{{{ Alignment patterns
320 
321 impl Canvas {
322     /// Draws a alignment pattern with the center at (x, y).
draw_alignment_pattern_at(&mut self, x: i16, y: i16)323     fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) {
324         if self.get(x, y) != Module::Empty {
325             return;
326         }
327         for j in -2..=2 {
328             for i in -2..=2 {
329                 self.put(
330                     x + i,
331                     y + j,
332                     match (i, j) {
333                         (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark,
334                         _ => Color::Light,
335                     },
336                 );
337             }
338         }
339     }
340 
341     /// Draws the alignment patterns.
342     ///
343     /// The alignment patterns are 5×5 square patterns inside the QR code symbol
344     /// to help the scanner create the square grid.
draw_alignment_patterns(&mut self)345     fn draw_alignment_patterns(&mut self) {
346         match self.version {
347             Version::Micro(_) | Version::Normal(1) => {}
348             Version::Normal(2..=6) => self.draw_alignment_pattern_at(-7, -7),
349             Version::Normal(a) => {
350                 let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
351                 for x in positions.iter() {
352                     for y in positions.iter() {
353                         self.draw_alignment_pattern_at(*x, *y);
354                     }
355                 }
356             }
357         }
358     }
359 }
360 
361 #[cfg(test)]
362 mod alignment_pattern_tests {
363     use crate::canvas::Canvas;
364     use crate::types::{EcLevel, Version};
365 
366     #[test]
test_draw_alignment_patterns_1()367     fn test_draw_alignment_patterns_1() {
368         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
369         c.draw_finder_patterns();
370         c.draw_alignment_patterns();
371         assert_eq!(
372             &*c.to_debug_str(),
373             "\n\
374              #######.?????.#######\n\
375              #.....#.?????.#.....#\n\
376              #.###.#.?????.#.###.#\n\
377              #.###.#.?????.#.###.#\n\
378              #.###.#.?????.#.###.#\n\
379              #.....#.?????.#.....#\n\
380              #######.?????.#######\n\
381              ........?????........\n\
382              ?????????????????????\n\
383              ?????????????????????\n\
384              ?????????????????????\n\
385              ?????????????????????\n\
386              ?????????????????????\n\
387              ........?????????????\n\
388              #######.?????????????\n\
389              #.....#.?????????????\n\
390              #.###.#.?????????????\n\
391              #.###.#.?????????????\n\
392              #.###.#.?????????????\n\
393              #.....#.?????????????\n\
394              #######.?????????????"
395         );
396     }
397 
398     #[test]
test_draw_alignment_patterns_3()399     fn test_draw_alignment_patterns_3() {
400         let mut c = Canvas::new(Version::Normal(3), EcLevel::L);
401         c.draw_finder_patterns();
402         c.draw_alignment_patterns();
403         assert_eq!(
404             &*c.to_debug_str(),
405             "\n\
406              #######.?????????????.#######\n\
407              #.....#.?????????????.#.....#\n\
408              #.###.#.?????????????.#.###.#\n\
409              #.###.#.?????????????.#.###.#\n\
410              #.###.#.?????????????.#.###.#\n\
411              #.....#.?????????????.#.....#\n\
412              #######.?????????????.#######\n\
413              ........?????????????........\n\
414              ?????????????????????????????\n\
415              ?????????????????????????????\n\
416              ?????????????????????????????\n\
417              ?????????????????????????????\n\
418              ?????????????????????????????\n\
419              ?????????????????????????????\n\
420              ?????????????????????????????\n\
421              ?????????????????????????????\n\
422              ?????????????????????????????\n\
423              ?????????????????????????????\n\
424              ?????????????????????????????\n\
425              ?????????????????????????????\n\
426              ????????????????????#####????\n\
427              ........????????????#...#????\n\
428              #######.????????????#.#.#????\n\
429              #.....#.????????????#...#????\n\
430              #.###.#.????????????#####????\n\
431              #.###.#.?????????????????????\n\
432              #.###.#.?????????????????????\n\
433              #.....#.?????????????????????\n\
434              #######.?????????????????????"
435         );
436     }
437 
438     #[test]
test_draw_alignment_patterns_7()439     fn test_draw_alignment_patterns_7() {
440         let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
441         c.draw_finder_patterns();
442         c.draw_alignment_patterns();
443         assert_eq!(
444             &*c.to_debug_str(),
445             "\n\
446              #######.?????????????????????????????.#######\n\
447              #.....#.?????????????????????????????.#.....#\n\
448              #.###.#.?????????????????????????????.#.###.#\n\
449              #.###.#.?????????????????????????????.#.###.#\n\
450              #.###.#.????????????#####????????????.#.###.#\n\
451              #.....#.????????????#...#????????????.#.....#\n\
452              #######.????????????#.#.#????????????.#######\n\
453              ........????????????#...#????????????........\n\
454              ????????????????????#####????????????????????\n\
455              ?????????????????????????????????????????????\n\
456              ?????????????????????????????????????????????\n\
457              ?????????????????????????????????????????????\n\
458              ?????????????????????????????????????????????\n\
459              ?????????????????????????????????????????????\n\
460              ?????????????????????????????????????????????\n\
461              ?????????????????????????????????????????????\n\
462              ?????????????????????????????????????????????\n\
463              ?????????????????????????????????????????????\n\
464              ?????????????????????????????????????????????\n\
465              ?????????????????????????????????????????????\n\
466              ????#####???????????#####???????????#####????\n\
467              ????#...#???????????#...#???????????#...#????\n\
468              ????#.#.#???????????#.#.#???????????#.#.#????\n\
469              ????#...#???????????#...#???????????#...#????\n\
470              ????#####???????????#####???????????#####????\n\
471              ?????????????????????????????????????????????\n\
472              ?????????????????????????????????????????????\n\
473              ?????????????????????????????????????????????\n\
474              ?????????????????????????????????????????????\n\
475              ?????????????????????????????????????????????\n\
476              ?????????????????????????????????????????????\n\
477              ?????????????????????????????????????????????\n\
478              ?????????????????????????????????????????????\n\
479              ?????????????????????????????????????????????\n\
480              ?????????????????????????????????????????????\n\
481              ?????????????????????????????????????????????\n\
482              ????????????????????#####???????????#####????\n\
483              ........????????????#...#???????????#...#????\n\
484              #######.????????????#.#.#???????????#.#.#????\n\
485              #.....#.????????????#...#???????????#...#????\n\
486              #.###.#.????????????#####???????????#####????\n\
487              #.###.#.?????????????????????????????????????\n\
488              #.###.#.?????????????????????????????????????\n\
489              #.....#.?????????????????????????????????????\n\
490              #######.?????????????????????????????????????"
491         );
492     }
493 }
494 
495 /// `ALIGNMENT_PATTERN_POSITIONS` describes the x- and y-coordinates of the
496 /// center of the alignment patterns. Since the QR code is symmetric, only one
497 /// coordinate is needed.
498 static ALIGNMENT_PATTERN_POSITIONS: [&[i16]; 34] = [
499     &[6, 22, 38],
500     &[6, 24, 42],
501     &[6, 26, 46],
502     &[6, 28, 50],
503     &[6, 30, 54],
504     &[6, 32, 58],
505     &[6, 34, 62],
506     &[6, 26, 46, 66],
507     &[6, 26, 48, 70],
508     &[6, 26, 50, 74],
509     &[6, 30, 54, 78],
510     &[6, 30, 56, 82],
511     &[6, 30, 58, 86],
512     &[6, 34, 62, 90],
513     &[6, 28, 50, 72, 94],
514     &[6, 26, 50, 74, 98],
515     &[6, 30, 54, 78, 102],
516     &[6, 28, 54, 80, 106],
517     &[6, 32, 58, 84, 110],
518     &[6, 30, 58, 86, 114],
519     &[6, 34, 62, 90, 118],
520     &[6, 26, 50, 74, 98, 122],
521     &[6, 30, 54, 78, 102, 126],
522     &[6, 26, 52, 78, 104, 130],
523     &[6, 30, 56, 82, 108, 134],
524     &[6, 34, 60, 86, 112, 138],
525     &[6, 30, 58, 86, 114, 142],
526     &[6, 34, 62, 90, 118, 146],
527     &[6, 30, 54, 78, 102, 126, 150],
528     &[6, 24, 50, 76, 102, 128, 154],
529     &[6, 28, 54, 80, 106, 132, 158],
530     &[6, 32, 58, 84, 110, 136, 162],
531     &[6, 26, 54, 82, 110, 138, 166],
532     &[6, 30, 58, 86, 114, 142, 170],
533 ];
534 
535 //}}}
536 //------------------------------------------------------------------------------
537 //{{{ Timing patterns
538 
539 impl Canvas {
540     /// Draws a line from (x1, y1) to (x2, y2), inclusively.
541     ///
542     /// The line must be either horizontal or vertical, i.e.
543     /// `x1 == x2 || y1 == y2`. Additionally, the first coordinates must be less
544     /// then the second ones.
545     ///
546     /// On even coordinates, `color_even` will be plotted; on odd coordinates,
547     /// `color_odd` will be plotted instead. Thus the timing pattern can be
548     /// drawn using this method.
549     ///
draw_line( &mut self, x1: i16, y1: i16, x2: i16, y2: i16, color_even: Color, color_odd: Color, )550     fn draw_line(
551         &mut self,
552         x1: i16,
553         y1: i16,
554         x2: i16,
555         y2: i16,
556         color_even: Color,
557         color_odd: Color,
558     ) {
559         debug_assert!(x1 == x2 || y1 == y2);
560 
561         if y1 == y2 {
562             // Horizontal line.
563             for x in x1..=x2 {
564                 self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd });
565             }
566         } else {
567             // Vertical line.
568             for y in y1..=y2 {
569                 self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd });
570             }
571         }
572     }
573 
574     /// Draws the timing patterns.
575     ///
576     /// The timing patterns are checkboard-colored lines near the edge of the QR
577     /// code symbol, to establish the fine-grained module coordinates when
578     /// scanning.
draw_timing_patterns(&mut self)579     fn draw_timing_patterns(&mut self) {
580         let width = self.width;
581         let (y, x1, x2) = match self.version {
582             Version::Micro(_) => (0, 8, width - 1),
583             Version::Normal(_) => (6, 8, width - 9),
584         };
585         self.draw_line(x1, y, x2, y, Color::Dark, Color::Light);
586         self.draw_line(y, x1, y, x2, Color::Dark, Color::Light);
587     }
588 }
589 
590 #[cfg(test)]
591 mod timing_pattern_tests {
592     use crate::canvas::Canvas;
593     use crate::types::{EcLevel, Version};
594 
595     #[test]
test_draw_timing_patterns_qr()596     fn test_draw_timing_patterns_qr() {
597         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
598         c.draw_timing_patterns();
599         assert_eq!(
600             &*c.to_debug_str(),
601             "\n\
602              ?????????????????????\n\
603              ?????????????????????\n\
604              ?????????????????????\n\
605              ?????????????????????\n\
606              ?????????????????????\n\
607              ?????????????????????\n\
608              ????????#.#.#????????\n\
609              ?????????????????????\n\
610              ??????#??????????????\n\
611              ??????.??????????????\n\
612              ??????#??????????????\n\
613              ??????.??????????????\n\
614              ??????#??????????????\n\
615              ?????????????????????\n\
616              ?????????????????????\n\
617              ?????????????????????\n\
618              ?????????????????????\n\
619              ?????????????????????\n\
620              ?????????????????????\n\
621              ?????????????????????\n\
622              ?????????????????????"
623         );
624     }
625 
626     #[test]
test_draw_timing_patterns_micro_qr()627     fn test_draw_timing_patterns_micro_qr() {
628         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
629         c.draw_timing_patterns();
630         assert_eq!(
631             &*c.to_debug_str(),
632             "\n\
633              ????????#.#\n\
634              ???????????\n\
635              ???????????\n\
636              ???????????\n\
637              ???????????\n\
638              ???????????\n\
639              ???????????\n\
640              ???????????\n\
641              #??????????\n\
642              .??????????\n\
643              #??????????"
644         );
645     }
646 }
647 
648 //}}}
649 //------------------------------------------------------------------------------
650 //{{{ Format info & Version info
651 
652 impl Canvas {
653     /// Draws a big-endian integer onto the canvas with the given coordinates.
654     ///
655     /// The 1 bits will be plotted with `on_color` and the 0 bits with
656     /// `off_color`. The coordinates will be extracted from the `coords`
657     /// iterator. It will start from the most significant bits first, so
658     /// *trailing* zeros will be ignored.
draw_number( &mut self, number: u32, bits: u32, on_color: Color, off_color: Color, coords: &[(i16, i16)], )659     fn draw_number(
660         &mut self,
661         number: u32,
662         bits: u32,
663         on_color: Color,
664         off_color: Color,
665         coords: &[(i16, i16)],
666     ) {
667         let mut mask = 1 << (bits - 1);
668         for &(x, y) in coords {
669             let color = if (mask & number) == 0 {
670                 off_color
671             } else {
672                 on_color
673             };
674             self.put(x, y, color);
675             mask >>= 1;
676         }
677     }
678 
679     /// Draws the format info patterns for an encoded number.
draw_format_info_patterns_with_number(&mut self, format_info: u16)680     fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
681         let format_info = u32::from(format_info);
682         match self.version {
683             Version::Micro(_) => {
684                 self.draw_number(
685                     format_info,
686                     15,
687                     Color::Dark,
688                     Color::Light,
689                     &FORMAT_INFO_COORDS_MICRO_QR,
690                 );
691             }
692             Version::Normal(_) => {
693                 self.draw_number(
694                     format_info,
695                     15,
696                     Color::Dark,
697                     Color::Light,
698                     &FORMAT_INFO_COORDS_QR_MAIN,
699                 );
700                 self.draw_number(
701                     format_info,
702                     15,
703                     Color::Dark,
704                     Color::Light,
705                     &FORMAT_INFO_COORDS_QR_SIDE,
706                 );
707                 self.put(8, -8, Color::Dark); // Dark module.
708             }
709         }
710     }
711 
712     /// Reserves area to put in the format information.
draw_reserved_format_info_patterns(&mut self)713     fn draw_reserved_format_info_patterns(&mut self) {
714         self.draw_format_info_patterns_with_number(0);
715     }
716 
717     /// Draws the version information patterns.
draw_version_info_patterns(&mut self)718     fn draw_version_info_patterns(&mut self) {
719         match self.version {
720             Version::Micro(_) | Version::Normal(1..=6) => {}
721             Version::Normal(a) => {
722                 let version_info = VERSION_INFOS[(a - 7).as_usize()];
723                 self.draw_number(
724                     version_info,
725                     18,
726                     Color::Dark,
727                     Color::Light,
728                     &VERSION_INFO_COORDS_BL,
729                 );
730                 self.draw_number(
731                     version_info,
732                     18,
733                     Color::Dark,
734                     Color::Light,
735                     &VERSION_INFO_COORDS_TR,
736                 );
737             }
738         }
739     }
740 }
741 
742 #[cfg(test)]
743 mod draw_version_info_tests {
744     use crate::canvas::Canvas;
745     use crate::types::{Color, EcLevel, Version};
746 
747     #[test]
test_draw_number()748     fn test_draw_number() {
749         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
750         c.draw_number(
751             0b10101101,
752             8,
753             Color::Dark,
754             Color::Light,
755             &[(0, 0), (0, -1), (-2, -2), (-2, 0)],
756         );
757         assert_eq!(
758             &*c.to_debug_str(),
759             "\n\
760              #????????.?\n\
761              ???????????\n\
762              ???????????\n\
763              ???????????\n\
764              ???????????\n\
765              ???????????\n\
766              ???????????\n\
767              ???????????\n\
768              ???????????\n\
769              ?????????#?\n\
770              .??????????"
771         );
772     }
773 
774     #[test]
test_draw_version_info_1()775     fn test_draw_version_info_1() {
776         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
777         c.draw_version_info_patterns();
778         assert_eq!(
779             &*c.to_debug_str(),
780             "\n\
781              ?????????????????????\n\
782              ?????????????????????\n\
783              ?????????????????????\n\
784              ?????????????????????\n\
785              ?????????????????????\n\
786              ?????????????????????\n\
787              ?????????????????????\n\
788              ?????????????????????\n\
789              ?????????????????????\n\
790              ?????????????????????\n\
791              ?????????????????????\n\
792              ?????????????????????\n\
793              ?????????????????????\n\
794              ?????????????????????\n\
795              ?????????????????????\n\
796              ?????????????????????\n\
797              ?????????????????????\n\
798              ?????????????????????\n\
799              ?????????????????????\n\
800              ?????????????????????\n\
801              ?????????????????????"
802         );
803     }
804 
805     #[test]
test_draw_version_info_7()806     fn test_draw_version_info_7() {
807         let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
808         c.draw_version_info_patterns();
809 
810         assert_eq!(
811             &*c.to_debug_str(),
812             "\n\
813              ??????????????????????????????????..#????????\n\
814              ??????????????????????????????????.#.????????\n\
815              ??????????????????????????????????.#.????????\n\
816              ??????????????????????????????????.##????????\n\
817              ??????????????????????????????????###????????\n\
818              ??????????????????????????????????...????????\n\
819              ?????????????????????????????????????????????\n\
820              ?????????????????????????????????????????????\n\
821              ?????????????????????????????????????????????\n\
822              ?????????????????????????????????????????????\n\
823              ?????????????????????????????????????????????\n\
824              ?????????????????????????????????????????????\n\
825              ?????????????????????????????????????????????\n\
826              ?????????????????????????????????????????????\n\
827              ?????????????????????????????????????????????\n\
828              ?????????????????????????????????????????????\n\
829              ?????????????????????????????????????????????\n\
830              ?????????????????????????????????????????????\n\
831              ?????????????????????????????????????????????\n\
832              ?????????????????????????????????????????????\n\
833              ?????????????????????????????????????????????\n\
834              ?????????????????????????????????????????????\n\
835              ?????????????????????????????????????????????\n\
836              ?????????????????????????????????????????????\n\
837              ?????????????????????????????????????????????\n\
838              ?????????????????????????????????????????????\n\
839              ?????????????????????????????????????????????\n\
840              ?????????????????????????????????????????????\n\
841              ?????????????????????????????????????????????\n\
842              ?????????????????????????????????????????????\n\
843              ?????????????????????????????????????????????\n\
844              ?????????????????????????????????????????????\n\
845              ?????????????????????????????????????????????\n\
846              ?????????????????????????????????????????????\n\
847              ....#.???????????????????????????????????????\n\
848              .####.???????????????????????????????????????\n\
849              #..##.???????????????????????????????????????\n\
850              ?????????????????????????????????????????????\n\
851              ?????????????????????????????????????????????\n\
852              ?????????????????????????????????????????????\n\
853              ?????????????????????????????????????????????\n\
854              ?????????????????????????????????????????????\n\
855              ?????????????????????????????????????????????\n\
856              ?????????????????????????????????????????????\n\
857              ?????????????????????????????????????????????"
858         );
859     }
860 
861     #[test]
test_draw_reserved_format_info_patterns_qr()862     fn test_draw_reserved_format_info_patterns_qr() {
863         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
864         c.draw_reserved_format_info_patterns();
865         assert_eq!(
866             &*c.to_debug_str(),
867             "\n\
868              ????????.????????????\n\
869              ????????.????????????\n\
870              ????????.????????????\n\
871              ????????.????????????\n\
872              ????????.????????????\n\
873              ????????.????????????\n\
874              ?????????????????????\n\
875              ????????.????????????\n\
876              ......?..????........\n\
877              ?????????????????????\n\
878              ?????????????????????\n\
879              ?????????????????????\n\
880              ?????????????????????\n\
881              ????????#????????????\n\
882              ????????.????????????\n\
883              ????????.????????????\n\
884              ????????.????????????\n\
885              ????????.????????????\n\
886              ????????.????????????\n\
887              ????????.????????????\n\
888              ????????.????????????"
889         );
890     }
891 
892     #[test]
test_draw_reserved_format_info_patterns_micro_qr()893     fn test_draw_reserved_format_info_patterns_micro_qr() {
894         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
895         c.draw_reserved_format_info_patterns();
896         assert_eq!(
897             &*c.to_debug_str(),
898             "\n\
899              ???????????\n\
900              ????????.??\n\
901              ????????.??\n\
902              ????????.??\n\
903              ????????.??\n\
904              ????????.??\n\
905              ????????.??\n\
906              ????????.??\n\
907              ?........??\n\
908              ???????????\n\
909              ???????????"
910         );
911     }
912 }
913 
914 static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [
915     (5, -9),
916     (5, -10),
917     (5, -11),
918     (4, -9),
919     (4, -10),
920     (4, -11),
921     (3, -9),
922     (3, -10),
923     (3, -11),
924     (2, -9),
925     (2, -10),
926     (2, -11),
927     (1, -9),
928     (1, -10),
929     (1, -11),
930     (0, -9),
931     (0, -10),
932     (0, -11),
933 ];
934 
935 static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [
936     (-9, 5),
937     (-10, 5),
938     (-11, 5),
939     (-9, 4),
940     (-10, 4),
941     (-11, 4),
942     (-9, 3),
943     (-10, 3),
944     (-11, 3),
945     (-9, 2),
946     (-10, 2),
947     (-11, 2),
948     (-9, 1),
949     (-10, 1),
950     (-11, 1),
951     (-9, 0),
952     (-10, 0),
953     (-11, 0),
954 ];
955 
956 static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [
957     (0, 8),
958     (1, 8),
959     (2, 8),
960     (3, 8),
961     (4, 8),
962     (5, 8),
963     (7, 8),
964     (8, 8),
965     (8, 7),
966     (8, 5),
967     (8, 4),
968     (8, 3),
969     (8, 2),
970     (8, 1),
971     (8, 0),
972 ];
973 
974 static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [
975     (8, -1),
976     (8, -2),
977     (8, -3),
978     (8, -4),
979     (8, -5),
980     (8, -6),
981     (8, -7),
982     (-8, 8),
983     (-7, 8),
984     (-6, 8),
985     (-5, 8),
986     (-4, 8),
987     (-3, 8),
988     (-2, 8),
989     (-1, 8),
990 ];
991 
992 static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [
993     (1, 8),
994     (2, 8),
995     (3, 8),
996     (4, 8),
997     (5, 8),
998     (6, 8),
999     (7, 8),
1000     (8, 8),
1001     (8, 7),
1002     (8, 6),
1003     (8, 5),
1004     (8, 4),
1005     (8, 3),
1006     (8, 2),
1007     (8, 1),
1008 ];
1009 
1010 static VERSION_INFOS: [u32; 34] = [
1011     0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78,
1012     0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab,
1013     0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b,
1014     0x2542e, 0x26a64, 0x27541, 0x28c69,
1015 ];
1016 
1017 //}}}
1018 //------------------------------------------------------------------------------
1019 //{{{ All functional patterns before data placement
1020 
1021 impl Canvas {
1022     /// Draw all functional patterns, before data placement.
1023     ///
1024     /// All functional patterns (e.g. the finder pattern) *except* the format
1025     /// info pattern will be filled in. The format info pattern will be filled
1026     /// with light modules instead. Data bits can then put in the empty modules.
1027     /// with `.draw_data()`.
draw_all_functional_patterns(&mut self)1028     pub fn draw_all_functional_patterns(&mut self) {
1029         self.draw_finder_patterns();
1030         self.draw_alignment_patterns();
1031         self.draw_reserved_format_info_patterns();
1032         self.draw_timing_patterns();
1033         self.draw_version_info_patterns();
1034     }
1035 }
1036 
1037 /// Gets whether the module at the given coordinates represents a functional
1038 /// module.
is_functional(version: Version, width: i16, x: i16, y: i16) -> bool1039 pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool {
1040     debug_assert!(width == version.width());
1041 
1042     let x = if x < 0 { x + width } else { x };
1043     let y = if y < 0 { y + width } else { y };
1044 
1045     match version {
1046         Version::Micro(_) => x == 0 || y == 0 || (x < 9 && y < 9),
1047         Version::Normal(a) => {
1048             let non_alignment_test = x == 6 || y == 6 || // Timing patterns
1049                     (x < 9 && y < 9) ||                  // Top-left finder pattern
1050                     (x < 9 && y >= width-8) ||           // Bottom-left finder pattern
1051                     (x >= width-8 && y < 9); // Top-right finder pattern
1052             if non_alignment_test {
1053                 true
1054             } else if a == 1 {
1055                 false
1056             } else if (2..=6).contains(&a) {
1057                 (width - 7 - x).abs() <= 2 && (width - 7 - y).abs() <= 2
1058             } else {
1059                 let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
1060                 let last = positions.len() - 1;
1061                 for (i, align_x) in positions.iter().enumerate() {
1062                     for (j, align_y) in positions.iter().enumerate() {
1063                         if i == 0 && (j == 0 || j == last) || (i == last && j == 0) {
1064                             continue;
1065                         }
1066                         if (*align_x - x).abs() <= 2 && (*align_y - y).abs() <= 2 {
1067                             return true;
1068                         }
1069                     }
1070                 }
1071                 false
1072             }
1073         }
1074     }
1075 }
1076 
1077 #[cfg(test)]
1078 mod all_functional_patterns_tests {
1079     use crate::canvas::{is_functional, Canvas};
1080     use crate::types::{EcLevel, Version};
1081 
1082     #[test]
test_all_functional_patterns_qr()1083     fn test_all_functional_patterns_qr() {
1084         let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1085         c.draw_all_functional_patterns();
1086         assert_eq!(
1087             &*c.to_debug_str(),
1088             "\n\
1089              #######..????????.#######\n\
1090              #.....#..????????.#.....#\n\
1091              #.###.#..????????.#.###.#\n\
1092              #.###.#..????????.#.###.#\n\
1093              #.###.#..????????.#.###.#\n\
1094              #.....#..????????.#.....#\n\
1095              #######.#.#.#.#.#.#######\n\
1096              .........????????........\n\
1097              ......#..????????........\n\
1098              ??????.??????????????????\n\
1099              ??????#??????????????????\n\
1100              ??????.??????????????????\n\
1101              ??????#??????????????????\n\
1102              ??????.??????????????????\n\
1103              ??????#??????????????????\n\
1104              ??????.??????????????????\n\
1105              ??????#?????????#####????\n\
1106              ........#???????#...#????\n\
1107              #######..???????#.#.#????\n\
1108              #.....#..???????#...#????\n\
1109              #.###.#..???????#####????\n\
1110              #.###.#..????????????????\n\
1111              #.###.#..????????????????\n\
1112              #.....#..????????????????\n\
1113              #######..????????????????"
1114         );
1115     }
1116 
1117     #[test]
test_all_functional_patterns_micro_qr()1118     fn test_all_functional_patterns_micro_qr() {
1119         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1120         c.draw_all_functional_patterns();
1121         assert_eq!(
1122             &*c.to_debug_str(),
1123             "\n\
1124              #######.#.#\n\
1125              #.....#..??\n\
1126              #.###.#..??\n\
1127              #.###.#..??\n\
1128              #.###.#..??\n\
1129              #.....#..??\n\
1130              #######..??\n\
1131              .........??\n\
1132              #........??\n\
1133              .??????????\n\
1134              #??????????"
1135         );
1136     }
1137 
1138     #[test]
test_is_functional_qr_1()1139     fn test_is_functional_qr_1() {
1140         let version = Version::Normal(1);
1141         assert!(is_functional(version, version.width(), 0, 0));
1142         assert!(is_functional(version, version.width(), 10, 6));
1143         assert!(!is_functional(version, version.width(), 10, 5));
1144         assert!(!is_functional(version, version.width(), 14, 14));
1145         assert!(is_functional(version, version.width(), 6, 11));
1146         assert!(!is_functional(version, version.width(), 4, 11));
1147         assert!(is_functional(version, version.width(), 4, 13));
1148         assert!(is_functional(version, version.width(), 17, 7));
1149         assert!(!is_functional(version, version.width(), 17, 17));
1150     }
1151 
1152     #[test]
test_is_functional_qr_3()1153     fn test_is_functional_qr_3() {
1154         let version = Version::Normal(3);
1155         assert!(is_functional(version, version.width(), 0, 0));
1156         assert!(!is_functional(version, version.width(), 25, 24));
1157         assert!(is_functional(version, version.width(), 24, 24));
1158         assert!(!is_functional(version, version.width(), 9, 25));
1159         assert!(!is_functional(version, version.width(), 20, 0));
1160         assert!(is_functional(version, version.width(), 21, 0));
1161     }
1162 
1163     #[test]
test_is_functional_qr_7()1164     fn test_is_functional_qr_7() {
1165         let version = Version::Normal(7);
1166         assert!(is_functional(version, version.width(), 21, 4));
1167         assert!(is_functional(version, version.width(), 7, 21));
1168         assert!(is_functional(version, version.width(), 22, 22));
1169         assert!(is_functional(version, version.width(), 8, 8));
1170         assert!(!is_functional(version, version.width(), 19, 5));
1171         assert!(!is_functional(version, version.width(), 36, 3));
1172         assert!(!is_functional(version, version.width(), 4, 36));
1173         assert!(is_functional(version, version.width(), 38, 38));
1174     }
1175 
1176     #[test]
test_is_functional_micro()1177     fn test_is_functional_micro() {
1178         let version = Version::Micro(1);
1179         assert!(is_functional(version, version.width(), 8, 0));
1180         assert!(is_functional(version, version.width(), 10, 0));
1181         assert!(!is_functional(version, version.width(), 10, 1));
1182         assert!(is_functional(version, version.width(), 8, 8));
1183         assert!(is_functional(version, version.width(), 0, 9));
1184         assert!(!is_functional(version, version.width(), 1, 9));
1185     }
1186 }
1187 
1188 //}}}
1189 //------------------------------------------------------------------------------
1190 //{{{ Data placement iterator
1191 
1192 struct DataModuleIter {
1193     x: i16,
1194     y: i16,
1195     width: i16,
1196     timing_pattern_column: i16,
1197 }
1198 
1199 impl DataModuleIter {
new(version: Version) -> Self1200     fn new(version: Version) -> Self {
1201         let width = version.width();
1202         Self {
1203             x: width - 1,
1204             y: width - 1,
1205             width,
1206             timing_pattern_column: match version {
1207                 Version::Micro(_) => 0,
1208                 Version::Normal(_) => 6,
1209             },
1210         }
1211     }
1212 }
1213 
1214 impl Iterator for DataModuleIter {
1215     type Item = (i16, i16);
1216 
next(&mut self) -> Option<(i16, i16)>1217     fn next(&mut self) -> Option<(i16, i16)> {
1218         let adjusted_ref_col = if self.x <= self.timing_pattern_column {
1219             self.x + 1
1220         } else {
1221             self.x
1222         };
1223         if adjusted_ref_col <= 0 {
1224             return None;
1225         }
1226 
1227         let res = (self.x, self.y);
1228         let column_type = (self.width - adjusted_ref_col) % 4;
1229 
1230         match column_type {
1231             2 if self.y > 0 => {
1232                 self.y -= 1;
1233                 self.x += 1;
1234             }
1235             0 if self.y < self.width - 1 => {
1236                 self.y += 1;
1237                 self.x += 1;
1238             }
1239             0 | 2 if self.x == self.timing_pattern_column + 1 => {
1240                 self.x -= 2;
1241             }
1242             _ => {
1243                 self.x -= 1;
1244             }
1245         }
1246 
1247         Some(res)
1248     }
1249 }
1250 
1251 #[cfg(test)]
1252 #[rustfmt::skip] // skip to prevent file becoming too long.
1253 mod data_iter_tests {
1254     use crate::canvas::DataModuleIter;
1255     use crate::types::Version;
1256 
1257     #[test]
test_qr()1258     fn test_qr() {
1259         let res = DataModuleIter::new(Version::Normal(1)).collect::<Vec<(i16, i16)>>();
1260         assert_eq!(res, vec![
1261             (20, 20), (19, 20), (20, 19), (19, 19), (20, 18), (19, 18),
1262             (20, 17), (19, 17), (20, 16), (19, 16), (20, 15), (19, 15),
1263             (20, 14), (19, 14), (20, 13), (19, 13), (20, 12), (19, 12),
1264             (20, 11), (19, 11), (20, 10), (19, 10), (20, 9), (19, 9),
1265             (20, 8), (19, 8), (20, 7), (19, 7), (20, 6), (19, 6),
1266             (20, 5), (19, 5), (20, 4), (19, 4), (20, 3), (19, 3),
1267             (20, 2), (19, 2), (20, 1), (19, 1), (20, 0), (19, 0),
1268 
1269             (18, 0), (17, 0), (18, 1), (17, 1), (18, 2), (17, 2),
1270             (18, 3), (17, 3), (18, 4), (17, 4), (18, 5), (17, 5),
1271             (18, 6), (17, 6), (18, 7), (17, 7), (18, 8), (17, 8),
1272             (18, 9), (17, 9), (18, 10), (17, 10), (18, 11), (17, 11),
1273             (18, 12), (17, 12), (18, 13), (17, 13), (18, 14), (17, 14),
1274             (18, 15), (17, 15), (18, 16), (17, 16), (18, 17), (17, 17),
1275             (18, 18), (17, 18), (18, 19), (17, 19), (18, 20), (17, 20),
1276 
1277             (16, 20), (15, 20), (16, 19), (15, 19), (16, 18), (15, 18),
1278             (16, 17), (15, 17), (16, 16), (15, 16), (16, 15), (15, 15),
1279             (16, 14), (15, 14), (16, 13), (15, 13), (16, 12), (15, 12),
1280             (16, 11), (15, 11), (16, 10), (15, 10), (16, 9), (15, 9),
1281             (16, 8), (15, 8), (16, 7), (15, 7), (16, 6), (15, 6),
1282             (16, 5), (15, 5), (16, 4), (15, 4), (16, 3), (15, 3),
1283             (16, 2), (15, 2), (16, 1), (15, 1), (16, 0), (15, 0),
1284 
1285             (14, 0), (13, 0), (14, 1), (13, 1), (14, 2), (13, 2),
1286             (14, 3), (13, 3), (14, 4), (13, 4), (14, 5), (13, 5),
1287             (14, 6), (13, 6), (14, 7), (13, 7), (14, 8), (13, 8),
1288             (14, 9), (13, 9), (14, 10), (13, 10), (14, 11), (13, 11),
1289             (14, 12), (13, 12), (14, 13), (13, 13), (14, 14), (13, 14),
1290             (14, 15), (13, 15), (14, 16), (13, 16), (14, 17), (13, 17),
1291             (14, 18), (13, 18), (14, 19), (13, 19), (14, 20), (13, 20),
1292 
1293             (12, 20), (11, 20), (12, 19), (11, 19), (12, 18), (11, 18),
1294             (12, 17), (11, 17), (12, 16), (11, 16), (12, 15), (11, 15),
1295             (12, 14), (11, 14), (12, 13), (11, 13), (12, 12), (11, 12),
1296             (12, 11), (11, 11), (12, 10), (11, 10), (12, 9), (11, 9),
1297             (12, 8), (11, 8), (12, 7), (11, 7), (12, 6), (11, 6),
1298             (12, 5), (11, 5), (12, 4), (11, 4), (12, 3), (11, 3),
1299             (12, 2), (11, 2), (12, 1), (11, 1), (12, 0), (11, 0),
1300 
1301             (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2),
1302             (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5),
1303             (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8),
1304             (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11),
1305             (10, 12), (9, 12), (10, 13), (9, 13), (10, 14), (9, 14),
1306             (10, 15), (9, 15), (10, 16), (9, 16), (10, 17), (9, 17),
1307             (10, 18), (9, 18), (10, 19), (9, 19), (10, 20), (9, 20),
1308 
1309             (8, 20), (7, 20), (8, 19), (7, 19), (8, 18), (7, 18),
1310             (8, 17), (7, 17), (8, 16), (7, 16), (8, 15), (7, 15),
1311             (8, 14), (7, 14), (8, 13), (7, 13), (8, 12), (7, 12),
1312             (8, 11), (7, 11), (8, 10), (7, 10), (8, 9), (7, 9),
1313             (8, 8), (7, 8), (8, 7), (7, 7), (8, 6), (7, 6),
1314             (8, 5), (7, 5), (8, 4), (7, 4), (8, 3), (7, 3),
1315             (8, 2), (7, 2), (8, 1), (7, 1), (8, 0), (7, 0),
1316 
1317             (5, 0), (4, 0), (5, 1), (4, 1), (5, 2), (4, 2),
1318             (5, 3), (4, 3), (5, 4), (4, 4), (5, 5), (4, 5),
1319             (5, 6), (4, 6), (5, 7), (4, 7), (5, 8), (4, 8),
1320             (5, 9), (4, 9), (5, 10), (4, 10), (5, 11), (4, 11),
1321             (5, 12), (4, 12), (5, 13), (4, 13), (5, 14), (4, 14),
1322             (5, 15), (4, 15), (5, 16), (4, 16), (5, 17), (4, 17),
1323             (5, 18), (4, 18), (5, 19), (4, 19), (5, 20), (4, 20),
1324 
1325             (3, 20), (2, 20), (3, 19), (2, 19), (3, 18), (2, 18),
1326             (3, 17), (2, 17), (3, 16), (2, 16), (3, 15), (2, 15),
1327             (3, 14), (2, 14), (3, 13), (2, 13), (3, 12), (2, 12),
1328             (3, 11), (2, 11), (3, 10), (2, 10), (3, 9), (2, 9),
1329             (3, 8), (2, 8), (3, 7), (2, 7), (3, 6), (2, 6),
1330             (3, 5), (2, 5), (3, 4), (2, 4), (3, 3), (2, 3),
1331             (3, 2), (2, 2), (3, 1), (2, 1), (3, 0), (2, 0),
1332 
1333             (1, 0), (0, 0), (1, 1), (0, 1), (1, 2), (0, 2),
1334             (1, 3), (0, 3), (1, 4), (0, 4), (1, 5), (0, 5),
1335             (1, 6), (0, 6), (1, 7), (0, 7), (1, 8), (0, 8),
1336             (1, 9), (0, 9), (1, 10), (0, 10), (1, 11), (0, 11),
1337             (1, 12), (0, 12), (1, 13), (0, 13), (1, 14), (0, 14),
1338             (1, 15), (0, 15), (1, 16), (0, 16), (1, 17), (0, 17),
1339             (1, 18), (0, 18), (1, 19), (0, 19), (1, 20), (0, 20),
1340         ]);
1341     }
1342 
1343     #[test]
test_micro_qr()1344     fn test_micro_qr() {
1345         let res = DataModuleIter::new(Version::Micro(1)).collect::<Vec<(i16, i16)>>();
1346         assert_eq!(res, vec![
1347             (10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8),
1348             (10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5),
1349             (10, 4), (9, 4), (10, 3), (9, 3), (10, 2), (9, 2),
1350             (10, 1), (9, 1), (10, 0), (9, 0),
1351 
1352             (8, 0), (7, 0), (8, 1), (7, 1), (8, 2), (7, 2),
1353             (8, 3), (7, 3), (8, 4), (7, 4), (8, 5), (7, 5),
1354             (8, 6), (7, 6), (8, 7), (7, 7), (8, 8), (7, 8),
1355             (8, 9), (7, 9), (8, 10), (7, 10),
1356 
1357             (6, 10), (5, 10), (6, 9), (5, 9), (6, 8), (5, 8),
1358             (6, 7), (5, 7), (6, 6), (5, 6), (6, 5), (5, 5),
1359             (6, 4), (5, 4), (6, 3), (5, 3), (6, 2), (5, 2),
1360             (6, 1), (5, 1), (6, 0), (5, 0),
1361 
1362             (4, 0), (3, 0), (4, 1), (3, 1), (4, 2), (3, 2),
1363             (4, 3), (3, 3), (4, 4), (3, 4), (4, 5), (3, 5),
1364             (4, 6), (3, 6), (4, 7), (3, 7), (4, 8), (3, 8),
1365             (4, 9), (3, 9), (4, 10), (3, 10),
1366 
1367             (2, 10), (1, 10), (2, 9), (1, 9), (2, 8), (1, 8),
1368             (2, 7), (1, 7), (2, 6), (1, 6), (2, 5), (1, 5),
1369             (2, 4), (1, 4), (2, 3), (1, 3), (2, 2), (1, 2),
1370             (2, 1), (1, 1), (2, 0), (1, 0),
1371         ]);
1372     }
1373 
1374     #[test]
test_micro_qr_2()1375     fn test_micro_qr_2() {
1376         let res = DataModuleIter::new(Version::Micro(2)).collect::<Vec<(i16, i16)>>();
1377         assert_eq!(res, vec![
1378             (12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10),
1379             (12, 9), (11, 9), (12, 8), (11, 8), (12, 7), (11, 7),
1380             (12, 6), (11, 6), (12, 5), (11, 5), (12, 4), (11, 4),
1381             (12, 3), (11, 3), (12, 2), (11, 2), (12, 1), (11, 1),
1382             (12, 0), (11, 0),
1383 
1384             (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2),
1385             (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5),
1386             (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8),
1387             (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11),
1388             (10, 12), (9, 12),
1389 
1390             (8, 12), (7, 12), (8, 11), (7, 11), (8, 10), (7, 10),
1391             (8, 9), (7, 9), (8, 8), (7, 8), (8, 7), (7, 7),
1392             (8, 6), (7, 6), (8, 5), (7, 5), (8, 4), (7, 4),
1393             (8, 3), (7, 3), (8, 2), (7, 2), (8, 1), (7, 1),
1394             (8, 0), (7, 0),
1395 
1396             (6, 0), (5, 0), (6, 1), (5, 1), (6, 2), (5, 2),
1397             (6, 3), (5, 3), (6, 4), (5, 4), (6, 5), (5, 5),
1398             (6, 6), (5, 6), (6, 7), (5, 7), (6, 8), (5, 8),
1399             (6, 9), (5, 9), (6, 10), (5, 10), (6, 11), (5, 11),
1400             (6, 12), (5, 12),
1401 
1402             (4, 12), (3, 12), (4, 11), (3, 11), (4, 10), (3, 10),
1403             (4, 9), (3, 9), (4, 8), (3, 8), (4, 7), (3, 7),
1404             (4, 6), (3, 6), (4, 5), (3, 5), (4, 4), (3, 4),
1405             (4, 3), (3, 3), (4, 2), (3, 2), (4, 1), (3, 1),
1406             (4, 0), (3, 0),
1407 
1408             (2, 0), (1, 0), (2, 1), (1, 1), (2, 2), (1, 2),
1409             (2, 3), (1, 3), (2, 4), (1, 4), (2, 5), (1, 5),
1410             (2, 6), (1, 6), (2, 7), (1, 7), (2, 8), (1, 8),
1411             (2, 9), (1, 9), (2, 10), (1, 10), (2, 11), (1, 11),
1412             (2, 12), (1, 12),
1413         ]);
1414     }
1415 }
1416 
1417 //}}}
1418 //------------------------------------------------------------------------------
1419 //{{{ Data placement
1420 
1421 impl Canvas {
draw_codewords<I>(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I) where I: Iterator<Item = (i16, i16)>,1422     fn draw_codewords<I>(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I)
1423     where
1424         I: Iterator<Item = (i16, i16)>,
1425     {
1426         let length = codewords.len();
1427         let last_word = if is_half_codeword_at_end {
1428             length - 1
1429         } else {
1430             length
1431         };
1432         for (i, b) in codewords.iter().enumerate() {
1433             let bits_end = if i == last_word { 4 } else { 0 };
1434             'outside: for j in (bits_end..=7).rev() {
1435                 let color = if (*b & (1 << j)) == 0 {
1436                     Color::Light
1437                 } else {
1438                     Color::Dark
1439                 };
1440                 for (x, y) in coords.by_ref() {
1441                     let r = self.get_mut(x, y);
1442                     if *r == Module::Empty {
1443                         *r = Module::Unmasked(color);
1444                         continue 'outside;
1445                     }
1446                 }
1447                 return;
1448             }
1449         }
1450     }
1451 
1452     /// Draws the encoded data and error correction codes to the empty modules.
draw_data(&mut self, data: &[u8], ec: &[u8])1453     pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
1454         let is_half_codeword_at_end = match (self.version, self.ec_level) {
1455             (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M) => true,
1456             _ => false,
1457         };
1458 
1459         let mut coords = DataModuleIter::new(self.version);
1460         self.draw_codewords(data, is_half_codeword_at_end, &mut coords);
1461         self.draw_codewords(ec, false, &mut coords);
1462     }
1463 }
1464 
1465 #[cfg(test)]
1466 mod draw_codewords_test {
1467     use crate::canvas::Canvas;
1468     use crate::types::{EcLevel, Version};
1469 
1470     #[test]
test_micro_qr_1()1471     fn test_micro_qr_1() {
1472         let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1473         c.draw_all_functional_patterns();
1474         c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
1475         assert_eq!(
1476             &*c.to_debug_str(),
1477             "\n\
1478              #######.#.#\n\
1479              #.....#..-*\n\
1480              #.###.#..**\n\
1481              #.###.#..*-\n\
1482              #.###.#..**\n\
1483              #.....#..*-\n\
1484              #######..*-\n\
1485              .........-*\n\
1486              #........**\n\
1487              .***-**---*\n\
1488              #---*-*-**-"
1489         );
1490     }
1491 
1492     #[test]
test_qr_2()1493     fn test_qr_2() {
1494         let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1495         c.draw_all_functional_patterns();
1496         c.draw_data(
1497             b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\
1498               \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$",
1499             b"",
1500         );
1501         assert_eq!(
1502             &*c.to_debug_str(),
1503             "\n\
1504              #######..--*---*-.#######\n\
1505              #.....#..-*-*-*-*.#.....#\n\
1506              #.###.#..*---*---.#.###.#\n\
1507              #.###.#..--*---*-.#.###.#\n\
1508              #.###.#..-*-*-*-*.#.###.#\n\
1509              #.....#..*---*---.#.....#\n\
1510              #######.#.#.#.#.#.#######\n\
1511              .........--*---*-........\n\
1512              ......#..-*-*-*-*........\n\
1513              --*-*-.-**---*---*--**--*\n\
1514              -*-*--#----*---*---------\n\
1515              *----*.*--*-*-*-*-**--**-\n\
1516              --*-*-#-**---*---*--**--*\n\
1517              -*-*--.----*---*---------\n\
1518              *----*#*--*-*-*-*-**--**-\n\
1519              --*-*-.-**---*---*--**--*\n\
1520              -*-*--#----*---*#####----\n\
1521              ........#-*-*-*-#...#-**-\n\
1522              #######..*---*--#.#.#*--*\n\
1523              #.....#..--*---*#...#----\n\
1524              #.###.#..-*-*-*-#####-**-\n\
1525              #.###.#..*---*--*----*--*\n\
1526              #.###.#..--*------**-----\n\
1527              #.....#..-*-*-**-*--*-**-\n\
1528              #######..*---*--*----*--*"
1529         );
1530     }
1531 }
1532 //}}}
1533 //------------------------------------------------------------------------------
1534 //{{{ Masking
1535 
1536 /// The mask patterns. Since QR code and Micro QR code do not use the same
1537 /// pattern number, we name them according to their shape instead of the number.
1538 #[derive(Debug, Copy, Clone)]
1539 pub enum MaskPattern {
1540     /// QR code pattern 000: `(x + y) % 2 == 0`.
1541     Checkerboard = 0b000,
1542 
1543     /// QR code pattern 001: `y % 2 == 0`.
1544     HorizontalLines = 0b001,
1545 
1546     /// QR code pattern 010: `x % 3 == 0`.
1547     VerticalLines = 0b010,
1548 
1549     /// QR code pattern 011: `(x + y) % 3 == 0`.
1550     DiagonalLines = 0b011,
1551 
1552     /// QR code pattern 100: `((x/3) + (y/2)) % 2 == 0`.
1553     LargeCheckerboard = 0b100,
1554 
1555     /// QR code pattern 101: `(x*y)%2 + (x*y)%3 == 0`.
1556     Fields = 0b101,
1557 
1558     /// QR code pattern 110: `((x*y)%2 + (x*y)%3) % 2 == 0`.
1559     Diamonds = 0b110,
1560 
1561     /// QR code pattern 111: `((x+y)%2 + (x*y)%3) % 2 == 0`.
1562     Meadow = 0b111,
1563 }
1564 
1565 mod mask_functions {
checkerboard(x: i16, y: i16) -> bool1566     pub fn checkerboard(x: i16, y: i16) -> bool {
1567         (x + y) % 2 == 0
1568     }
horizontal_lines(_: i16, y: i16) -> bool1569     pub fn horizontal_lines(_: i16, y: i16) -> bool {
1570         y % 2 == 0
1571     }
vertical_lines(x: i16, _: i16) -> bool1572     pub fn vertical_lines(x: i16, _: i16) -> bool {
1573         x % 3 == 0
1574     }
diagonal_lines(x: i16, y: i16) -> bool1575     pub fn diagonal_lines(x: i16, y: i16) -> bool {
1576         (x + y) % 3 == 0
1577     }
large_checkerboard(x: i16, y: i16) -> bool1578     pub fn large_checkerboard(x: i16, y: i16) -> bool {
1579         ((y / 2) + (x / 3)) % 2 == 0
1580     }
fields(x: i16, y: i16) -> bool1581     pub fn fields(x: i16, y: i16) -> bool {
1582         (x * y) % 2 + (x * y) % 3 == 0
1583     }
diamonds(x: i16, y: i16) -> bool1584     pub fn diamonds(x: i16, y: i16) -> bool {
1585         ((x * y) % 2 + (x * y) % 3) % 2 == 0
1586     }
meadow(x: i16, y: i16) -> bool1587     pub fn meadow(x: i16, y: i16) -> bool {
1588         ((x + y) % 2 + (x * y) % 3) % 2 == 0
1589     }
1590 }
1591 
get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool1592 fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
1593     match pattern {
1594         MaskPattern::Checkerboard => mask_functions::checkerboard,
1595         MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
1596         MaskPattern::VerticalLines => mask_functions::vertical_lines,
1597         MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
1598         MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
1599         MaskPattern::Fields => mask_functions::fields,
1600         MaskPattern::Diamonds => mask_functions::diamonds,
1601         MaskPattern::Meadow => mask_functions::meadow,
1602     }
1603 }
1604 
1605 impl Canvas {
1606     /// Applies a mask to the canvas. This method will also draw the format info
1607     /// patterns.
apply_mask(&mut self, pattern: MaskPattern)1608     pub fn apply_mask(&mut self, pattern: MaskPattern) {
1609         let mask_fn = get_mask_function(pattern);
1610         for x in 0..self.width {
1611             for y in 0..self.width {
1612                 let module = self.get_mut(x, y);
1613                 *module = module.mask(mask_fn(x, y));
1614             }
1615         }
1616 
1617         self.draw_format_info_patterns(pattern);
1618     }
1619 
1620     /// Draws the format information to encode the error correction level and
1621     /// mask pattern.
1622     ///
1623     /// If the error correction level or mask pattern is not supported in the
1624     /// current QR code version, this method will fail.
draw_format_info_patterns(&mut self, pattern: MaskPattern)1625     fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
1626         let format_number = match self.version {
1627             Version::Normal(_) => {
1628                 let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize);
1629                 FORMAT_INFOS_QR[simple_format_number]
1630             }
1631             Version::Micro(a) => {
1632                 let micro_pattern_number = match pattern {
1633                     MaskPattern::HorizontalLines => 0b00,
1634                     MaskPattern::LargeCheckerboard => 0b01,
1635                     MaskPattern::Diamonds => 0b10,
1636                     MaskPattern::Meadow => 0b11,
1637                     _ => panic!("Unsupported mask pattern in Micro QR code"),
1638                 };
1639                 let symbol_number = match (a, self.ec_level) {
1640                     (1, EcLevel::L) => 0b000,
1641                     (2, EcLevel::L) => 0b001,
1642                     (2, EcLevel::M) => 0b010,
1643                     (3, EcLevel::L) => 0b011,
1644                     (3, EcLevel::M) => 0b100,
1645                     (4, EcLevel::L) => 0b101,
1646                     (4, EcLevel::M) => 0b110,
1647                     (4, EcLevel::Q) => 0b111,
1648                     _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
1649                 };
1650                 let simple_format_number = symbol_number << 2 | micro_pattern_number;
1651                 FORMAT_INFOS_MICRO_QR[simple_format_number]
1652             }
1653         };
1654         self.draw_format_info_patterns_with_number(format_number);
1655     }
1656 }
1657 
1658 #[cfg(test)]
1659 mod mask_tests {
1660     use crate::canvas::{Canvas, MaskPattern};
1661     use crate::types::{EcLevel, Version};
1662 
1663     #[test]
test_apply_mask_qr()1664     fn test_apply_mask_qr() {
1665         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1666         c.draw_all_functional_patterns();
1667         c.apply_mask(MaskPattern::Checkerboard);
1668 
1669         assert_eq!(
1670             &*c.to_debug_str(),
1671             "\n\
1672              #######...#.#.#######\n\
1673              #.....#..#.#..#.....#\n\
1674              #.###.#.#.#.#.#.###.#\n\
1675              #.###.#..#.#..#.###.#\n\
1676              #.###.#...#.#.#.###.#\n\
1677              #.....#..#.#..#.....#\n\
1678              #######.#.#.#.#######\n\
1679              ........##.#.........\n\
1680              ###.#####.#.###...#..\n\
1681              .#.#.#.#.#.#.#.#.#.#.\n\
1682              #.#.#.#.#.#.#.#.#.#.#\n\
1683              .#.#.#.#.#.#.#.#.#.#.\n\
1684              #.#.#.#.#.#.#.#.#.#.#\n\
1685              ........##.#.#.#.#.#.\n\
1686              #######.#.#.#.#.#.#.#\n\
1687              #.....#.##.#.#.#.#.#.\n\
1688              #.###.#.#.#.#.#.#.#.#\n\
1689              #.###.#..#.#.#.#.#.#.\n\
1690              #.###.#.#.#.#.#.#.#.#\n\
1691              #.....#.##.#.#.#.#.#.\n\
1692              #######.#.#.#.#.#.#.#"
1693         );
1694     }
1695 
1696     #[test]
test_draw_format_info_patterns_qr()1697     fn test_draw_format_info_patterns_qr() {
1698         let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1699         c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1700         assert_eq!(
1701             &*c.to_debug_str(),
1702             "\n\
1703              ????????#????????????\n\
1704              ????????#????????????\n\
1705              ????????#????????????\n\
1706              ????????#????????????\n\
1707              ????????.????????????\n\
1708              ????????#????????????\n\
1709              ?????????????????????\n\
1710              ????????.????????????\n\
1711              ##..##?..????..#.####\n\
1712              ?????????????????????\n\
1713              ?????????????????????\n\
1714              ?????????????????????\n\
1715              ?????????????????????\n\
1716              ????????#????????????\n\
1717              ????????.????????????\n\
1718              ????????#????????????\n\
1719              ????????#????????????\n\
1720              ????????.????????????\n\
1721              ????????.????????????\n\
1722              ????????#????????????\n\
1723              ????????#????????????"
1724         );
1725     }
1726 
1727     #[test]
test_draw_format_info_patterns_micro_qr()1728     fn test_draw_format_info_patterns_micro_qr() {
1729         let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
1730         c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1731         assert_eq!(
1732             &*c.to_debug_str(),
1733             "\n\
1734              ?????????????\n\
1735              ????????#????\n\
1736              ????????.????\n\
1737              ????????.????\n\
1738              ????????#????\n\
1739              ????????#????\n\
1740              ????????.????\n\
1741              ????????.????\n\
1742              ?#.#....#????\n\
1743              ?????????????\n\
1744              ?????????????\n\
1745              ?????????????\n\
1746              ?????????????"
1747         );
1748     }
1749 }
1750 
1751 static FORMAT_INFOS_QR: [u16; 32] = [
1752     0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d,
1753     0x662f, 0x6318, 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b,
1754     0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed,
1755 ];
1756 
1757 static FORMAT_INFOS_MICRO_QR: [u16; 32] = [
1758     0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca,
1759     0x7678, 0x734f, 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c,
1760     0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3, 0x31d4, 0x3e8d, 0x3bba,
1761 ];
1762 
1763 //}}}
1764 //------------------------------------------------------------------------------
1765 //{{{ Penalty score
1766 
1767 impl Canvas {
1768     /// Compute the penalty score for having too many adjacent modules with the
1769     /// same color.
1770     ///
1771     /// Every 5+N adjacent modules in the same column/row having the same color
1772     /// will contribute 3+N points.
compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u161773     fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 {
1774         let mut total_score = 0;
1775 
1776         for i in 0..self.width {
1777             let map_fn = |j| {
1778                 if is_horizontal {
1779                     self.get(j, i)
1780                 } else {
1781                     self.get(i, j)
1782                 }
1783             };
1784 
1785             let colors = (0..self.width)
1786                 .map(map_fn)
1787                 .chain(Some(Module::Empty).into_iter());
1788             let mut last_color = Module::Empty;
1789             let mut consecutive_len = 1_u16;
1790 
1791             for color in colors {
1792                 if color == last_color {
1793                     consecutive_len += 1;
1794                 } else {
1795                     last_color = color;
1796                     if consecutive_len >= 5 {
1797                         total_score += consecutive_len - 2;
1798                     }
1799                     consecutive_len = 1;
1800                 }
1801             }
1802         }
1803 
1804         total_score
1805     }
1806 
1807     /// Compute the penalty score for having too many rectangles with the same
1808     /// color.
1809     ///
1810     /// Every 2×2 blocks (with overlapping counted) having the same color will
1811     /// contribute 3 points.
compute_block_penalty_score(&self) -> u161812     fn compute_block_penalty_score(&self) -> u16 {
1813         let mut total_score = 0;
1814 
1815         for i in 0..self.width - 1 {
1816             for j in 0..self.width - 1 {
1817                 let this = self.get(i, j);
1818                 let right = self.get(i + 1, j);
1819                 let bottom = self.get(i, j + 1);
1820                 let bottom_right = self.get(i + 1, j + 1);
1821                 if this == right && right == bottom && bottom == bottom_right {
1822                     total_score += 3;
1823                 }
1824             }
1825         }
1826 
1827         total_score
1828     }
1829 
1830     /// Compute the penalty score for having a pattern similar to the finder
1831     /// pattern in the wrong place.
1832     ///
1833     /// Every pattern that looks like `#.###.#....` in any orientation will add
1834     /// 40 points.
compute_finder_penalty_score(&self, is_horizontal: bool) -> u161835     fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
1836         static PATTERN: [Color; 7] = [
1837             Color::Dark,
1838             Color::Light,
1839             Color::Dark,
1840             Color::Dark,
1841             Color::Dark,
1842             Color::Light,
1843             Color::Dark,
1844         ];
1845 
1846         let mut total_score = 0;
1847 
1848         for i in 0..self.width {
1849             let get = |k| -> Color {
1850                 if is_horizontal {
1851                     self.get(k, i).into()
1852                 } else {
1853                     self.get(i, k).into()
1854                 }
1855             };
1856             for j in 0..self.width - 6 {
1857                 if (j..(j + 7)).map(get).ne(PATTERN.iter().cloned()) {
1858                     continue;
1859                 }
1860 
1861                 let check = |k| 0 <= k && k < self.width && get(k) != Color::Light;
1862                 if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) {
1863                     total_score += 40;
1864                 }
1865             }
1866         }
1867 
1868         total_score - 360
1869     }
1870 
1871     /// Compute the penalty score for having an unbalanced dark/light ratio.
1872     ///
1873     /// The score is given linearly by the deviation from a 50% ratio of dark
1874     /// modules. The highest possible score is 100.
1875     ///
1876     /// Note that this algorithm differs slightly from the standard we do not
1877     /// round the result every 5%, but the difference should be negligible and
1878     /// should not affect which mask is chosen.
compute_balance_penalty_score(&self) -> u161879     fn compute_balance_penalty_score(&self) -> u16 {
1880         let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count();
1881         let total_modules = self.modules.len();
1882         let ratio = dark_modules * 200 / total_modules;
1883         if ratio >= 100 {
1884             ratio - 100
1885         } else {
1886             100 - ratio
1887         }
1888         .as_u16()
1889     }
1890 
1891     /// Compute the penalty score for having too many light modules on the sides.
1892     ///
1893     /// This penalty score is exclusive to Micro QR code.
1894     ///
1895     /// Note that the standard gives the formula for *efficiency* score, which
1896     /// has the inverse meaning of this method, but it is very easy to convert
1897     /// between the two (this score is (16×width − standard-score)).
compute_light_side_penalty_score(&self) -> u161898     fn compute_light_side_penalty_score(&self) -> u16 {
1899         let h = (1..self.width)
1900             .filter(|j| !self.get(*j, -1).is_dark())
1901             .count();
1902         let v = (1..self.width)
1903             .filter(|j| !self.get(-1, *j).is_dark())
1904             .count();
1905 
1906         (h + v + 15 * max(h, v)).as_u16()
1907     }
1908 
1909     /// Compute the total penalty scores. A QR code having higher points is less
1910     /// desirable.
compute_total_penalty_scores(&self) -> u161911     fn compute_total_penalty_scores(&self) -> u16 {
1912         match self.version {
1913             Version::Normal(_) => {
1914                 let s1_a = self.compute_adjacent_penalty_score(true);
1915                 let s1_b = self.compute_adjacent_penalty_score(false);
1916                 let s2 = self.compute_block_penalty_score();
1917                 let s3_a = self.compute_finder_penalty_score(true);
1918                 let s3_b = self.compute_finder_penalty_score(false);
1919                 let s4 = self.compute_balance_penalty_score();
1920                 s1_a + s1_b + s2 + s3_a + s3_b + s4
1921             }
1922             Version::Micro(_) => self.compute_light_side_penalty_score(),
1923         }
1924     }
1925 }
1926 
1927 #[cfg(test)]
1928 mod penalty_tests {
1929     use crate::canvas::{Canvas, MaskPattern};
1930     use crate::types::{Color, EcLevel, Version};
1931 
create_test_canvas() -> Canvas1932     fn create_test_canvas() -> Canvas {
1933         let mut c = Canvas::new(Version::Normal(1), EcLevel::Q);
1934         c.draw_all_functional_patterns();
1935         c.draw_data(
1936             b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00",
1937             b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10",
1938         );
1939         c.apply_mask(MaskPattern::Checkerboard);
1940         c
1941     }
1942 
1943     #[test]
check_penalty_canvas()1944     fn check_penalty_canvas() {
1945         let c = create_test_canvas();
1946         assert_eq!(
1947             &*c.to_debug_str(),
1948             "\n\
1949              #######.##....#######\n\
1950              #.....#.#..#..#.....#\n\
1951              #.###.#.#..##.#.###.#\n\
1952              #.###.#.#.....#.###.#\n\
1953              #.###.#.#.#...#.###.#\n\
1954              #.....#...#...#.....#\n\
1955              #######.#.#.#.#######\n\
1956              ........#............\n\
1957              .##.#.##....#.#.#####\n\
1958              .#......####....#...#\n\
1959              ..##.###.##...#.##...\n\
1960              .##.##.#..##.#.#.###.\n\
1961              #...#.#.#.###.###.#.#\n\
1962              ........##.#..#...#.#\n\
1963              #######.#.#....#.##..\n\
1964              #.....#..#.##.##.#...\n\
1965              #.###.#.#.#...#######\n\
1966              #.###.#..#.#.#.#...#.\n\
1967              #.###.#.#...####.#..#\n\
1968              #.....#.#.##.#...#.##\n\
1969              #######.....####....#"
1970         );
1971     }
1972 
1973     #[test]
test_penalty_score_adjacent()1974     fn test_penalty_score_adjacent() {
1975         let c = create_test_canvas();
1976         assert_eq!(c.compute_adjacent_penalty_score(true), 88);
1977         assert_eq!(c.compute_adjacent_penalty_score(false), 92);
1978     }
1979 
1980     #[test]
test_penalty_score_block()1981     fn test_penalty_score_block() {
1982         let c = create_test_canvas();
1983         assert_eq!(c.compute_block_penalty_score(), 90);
1984     }
1985 
1986     #[test]
test_penalty_score_finder()1987     fn test_penalty_score_finder() {
1988         let c = create_test_canvas();
1989         assert_eq!(c.compute_finder_penalty_score(true), 0);
1990         assert_eq!(c.compute_finder_penalty_score(false), 40);
1991     }
1992 
1993     #[test]
test_penalty_score_balance()1994     fn test_penalty_score_balance() {
1995         let c = create_test_canvas();
1996         assert_eq!(c.compute_balance_penalty_score(), 2);
1997     }
1998 
1999     #[test]
test_penalty_score_light_sides()2000     fn test_penalty_score_light_sides() {
2001         static HORIZONTAL_SIDE: [Color; 17] = [
2002             Color::Dark,
2003             Color::Light,
2004             Color::Light,
2005             Color::Dark,
2006             Color::Dark,
2007             Color::Dark,
2008             Color::Light,
2009             Color::Light,
2010             Color::Dark,
2011             Color::Light,
2012             Color::Dark,
2013             Color::Light,
2014             Color::Light,
2015             Color::Dark,
2016             Color::Light,
2017             Color::Light,
2018             Color::Light,
2019         ];
2020         static VERTICAL_SIDE: [Color; 17] = [
2021             Color::Dark,
2022             Color::Dark,
2023             Color::Dark,
2024             Color::Light,
2025             Color::Light,
2026             Color::Dark,
2027             Color::Dark,
2028             Color::Light,
2029             Color::Dark,
2030             Color::Light,
2031             Color::Dark,
2032             Color::Light,
2033             Color::Dark,
2034             Color::Light,
2035             Color::Light,
2036             Color::Dark,
2037             Color::Light,
2038         ];
2039 
2040         let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
2041         for i in 0_i16..17 {
2042             c.put(i, -1, HORIZONTAL_SIDE[i as usize]);
2043             c.put(-1, i, VERTICAL_SIDE[i as usize]);
2044         }
2045 
2046         assert_eq!(c.compute_light_side_penalty_score(), 168);
2047     }
2048 }
2049 
2050 //}}}
2051 //------------------------------------------------------------------------------
2052 //{{{ Select mask with lowest penalty score
2053 
2054 static ALL_PATTERNS_QR: [MaskPattern; 8] = [
2055     MaskPattern::Checkerboard,
2056     MaskPattern::HorizontalLines,
2057     MaskPattern::VerticalLines,
2058     MaskPattern::DiagonalLines,
2059     MaskPattern::LargeCheckerboard,
2060     MaskPattern::Fields,
2061     MaskPattern::Diamonds,
2062     MaskPattern::Meadow,
2063 ];
2064 
2065 static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] = [
2066     MaskPattern::HorizontalLines,
2067     MaskPattern::LargeCheckerboard,
2068     MaskPattern::Diamonds,
2069     MaskPattern::Meadow,
2070 ];
2071 
2072 impl Canvas {
2073     /// Construct a new canvas and apply the best masking that gives the lowest
2074     /// penalty score.
apply_best_mask(&self) -> Self2075     pub fn apply_best_mask(&self) -> Self {
2076         match self.version {
2077             Version::Normal(_) => ALL_PATTERNS_QR.iter(),
2078             Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
2079         }
2080         .map(|ptn| {
2081             let mut c = self.clone();
2082             c.apply_mask(*ptn);
2083             c
2084         })
2085         .min_by_key(Self::compute_total_penalty_scores)
2086         .expect("at least one pattern")
2087     }
2088 
2089     /// Convert the modules into a vector of booleans.
2090     #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")]
to_bools(&self) -> Vec<bool>2091     pub fn to_bools(&self) -> Vec<bool> {
2092         self.modules.iter().map(|m| m.is_dark()).collect()
2093     }
2094 
2095     /// Convert the modules into a vector of colors.
into_colors(self) -> Vec<Color>2096     pub fn into_colors(self) -> Vec<Color> {
2097         self.modules.into_iter().map(Color::from).collect()
2098     }
2099 }
2100 
2101 //}}}
2102 //------------------------------------------------------------------------------
2103