Skip to main content

qrcode/
canvas.rs

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