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    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)]
77pub 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
92impl Canvas {
93    /// Constructs a new canvas big enough for a QR code of the given version.
94    pub fn new(version: Version, ec_level: EcLevel) -> Self {
95        let width = version.width();
96        Self { width, version, ec_level, modules: vec![Module::Empty; (width * width).as_usize()] }
97    }
98
99    /// Converts the canvas into a human-readable string.
100    #[cfg(test)]
101    fn to_debug_str(&self) -> String {
102        let width = self.width;
103        let mut res = String::with_capacity((width * (width + 1)) as usize);
104        for y in 0..width {
105            res.push('\n');
106            for x in 0..width {
107                res.push(match self.get(x, y) {
108                    Module::Empty => '?',
109                    Module::Masked(Color::Light) => '.',
110                    Module::Masked(Color::Dark) => '#',
111                    Module::Unmasked(Color::Light) => '-',
112                    Module::Unmasked(Color::Dark) => '*',
113                });
114            }
115        }
116        res
117    }
118
119    fn coords_to_index(&self, x: i16, y: i16) -> usize {
120        let x = if x < 0 { x + self.width } else { x }.as_usize();
121        let y = if y < 0 { y + self.width } else { y }.as_usize();
122        y * self.width.as_usize() + x
123    }
124
125    /// Obtains a module at the given coordinates. For convenience, negative
126    /// coordinates will wrap around.
127    pub fn get(&self, x: i16, y: i16) -> Module {
128        self.modules[self.coords_to_index(x, y)]
129    }
130
131    /// Obtains a mutable module at the given coordinates. For convenience,
132    /// negative coordinates will wrap around.
133    pub fn get_mut(&mut self, x: i16, y: i16) -> &mut Module {
134        let index = self.coords_to_index(x, y);
135        &mut self.modules[index]
136    }
137
138    /// Sets the color of a functional module at the given coordinates. For
139    /// convenience, negative coordinates will wrap around.
140    pub fn put(&mut self, x: i16, y: i16, color: Color) {
141        *self.get_mut(x, y) = Module::Masked(color);
142    }
143}
144
145#[cfg(test)]
146mod basic_canvas_tests {
147    use crate::canvas::{Canvas, Module};
148    use crate::types::{Color, EcLevel, Version};
149
150    #[test]
151    fn test_index() {
152        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
153
154        assert_eq!(c.get(0, 4), Module::Empty);
155        assert_eq!(c.get(-1, -7), Module::Empty);
156        assert_eq!(c.get(21 - 1, 21 - 7), Module::Empty);
157
158        c.put(0, 0, Color::Dark);
159        c.put(-1, -7, Color::Light);
160        assert_eq!(c.get(0, 0), Module::Masked(Color::Dark));
161        assert_eq!(c.get(21 - 1, -7), Module::Masked(Color::Light));
162        assert_eq!(c.get(-1, 21 - 7), Module::Masked(Color::Light));
163    }
164
165    #[test]
166    fn test_debug_str() {
167        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
168
169        for i in 3_i16..20 {
170            for j in 3_i16..20 {
171                *c.get_mut(i, j) = match ((i * 3) ^ j) % 5 {
172                    0 => Module::Empty,
173                    1 => Module::Masked(Color::Light),
174                    2 => Module::Masked(Color::Dark),
175                    3 => Module::Unmasked(Color::Light),
176                    4 => Module::Unmasked(Color::Dark),
177                    _ => unreachable!(),
178                };
179            }
180        }
181
182        assert_eq!(
183            &*c.to_debug_str(),
184            "\n\
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             ?????????????????????"
206        );
207    }
208}
209
210//}}}
211//------------------------------------------------------------------------------
212//{{{ Finder patterns
213
214impl Canvas {
215    /// Draws a single finder pattern with the center at (x, y).
216    fn draw_finder_pattern_at(&mut self, x: i16, y: i16) {
217        let (dx_left, dx_right) = if x >= 0 { (-3, 4) } else { (-4, 3) };
218        let (dy_top, dy_bottom) = if y >= 0 { (-3, 4) } else { (-4, 3) };
219        for j in dy_top..=dy_bottom {
220            for i in dx_left..=dx_right {
221                self.put(
222                    x + i,
223                    y + j,
224                    #[allow(clippy::match_same_arms)]
225                    match (i, j) {
226                        (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light,
227                        (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark,
228                        (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light,
229                        _ => Color::Dark,
230                    },
231                );
232            }
233        }
234    }
235
236    /// Draws the finder patterns.
237    ///
238    /// The finder patterns is are 7×7 square patterns appearing at the three
239    /// corners of a QR code. They allows scanner to locate the QR code and
240    /// determine the orientation.
241    fn draw_finder_patterns(&mut self) {
242        self.draw_finder_pattern_at(3, 3);
243
244        match self.version {
245            Version::Micro(_) => {}
246            Version::Normal(_) => {
247                self.draw_finder_pattern_at(-4, 3);
248                self.draw_finder_pattern_at(3, -4);
249            }
250        }
251    }
252}
253
254#[cfg(test)]
255mod finder_pattern_tests {
256    use crate::canvas::Canvas;
257    use crate::types::{EcLevel, Version};
258
259    #[test]
260    fn test_qr() {
261        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
262        c.draw_finder_patterns();
263        assert_eq!(
264            &*c.to_debug_str(),
265            "\n\
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             #######.?????????????"
287        );
288    }
289
290    #[test]
291    fn test_micro_qr() {
292        let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
293        c.draw_finder_patterns();
294        assert_eq!(
295            &*c.to_debug_str(),
296            "\n\
297             #######.???\n\
298             #.....#.???\n\
299             #.###.#.???\n\
300             #.###.#.???\n\
301             #.###.#.???\n\
302             #.....#.???\n\
303             #######.???\n\
304             ........???\n\
305             ???????????\n\
306             ???????????\n\
307             ???????????"
308        );
309    }
310}
311
312//}}}
313//------------------------------------------------------------------------------
314//{{{ Alignment patterns
315
316impl Canvas {
317    /// Draws a alignment pattern with the center at (x, y).
318    fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) {
319        if self.get(x, y) != Module::Empty {
320            return;
321        }
322        for j in -2..=2 {
323            for i in -2..=2 {
324                self.put(
325                    x + i,
326                    y + j,
327                    match (i, j) {
328                        (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark,
329                        _ => Color::Light,
330                    },
331                );
332            }
333        }
334    }
335
336    /// Draws the alignment patterns.
337    ///
338    /// The alignment patterns are 5×5 square patterns inside the QR code symbol
339    /// to help the scanner create the square grid.
340    fn draw_alignment_patterns(&mut self) {
341        match self.version {
342            Version::Micro(_) | Version::Normal(1) => {}
343            Version::Normal(2..=6) => self.draw_alignment_pattern_at(-7, -7),
344            Version::Normal(a) => {
345                let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
346                for x in positions.iter() {
347                    for y in positions.iter() {
348                        self.draw_alignment_pattern_at(*x, *y);
349                    }
350                }
351            }
352        }
353    }
354}
355
356#[cfg(test)]
357mod alignment_pattern_tests {
358    use crate::canvas::Canvas;
359    use crate::types::{EcLevel, Version};
360
361    #[test]
362    fn test_draw_alignment_patterns_1() {
363        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
364        c.draw_finder_patterns();
365        c.draw_alignment_patterns();
366        assert_eq!(
367            &*c.to_debug_str(),
368            "\n\
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             #######.?????????????"
390        );
391    }
392
393    #[test]
394    fn test_draw_alignment_patterns_3() {
395        let mut c = Canvas::new(Version::Normal(3), EcLevel::L);
396        c.draw_finder_patterns();
397        c.draw_alignment_patterns();
398        assert_eq!(
399            &*c.to_debug_str(),
400            "\n\
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             #######.?????????????????????"
430        );
431    }
432
433    #[test]
434    fn test_draw_alignment_patterns_7() {
435        let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
436        c.draw_finder_patterns();
437        c.draw_alignment_patterns();
438        assert_eq!(
439            &*c.to_debug_str(),
440            "\n\
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             #######.?????????????????????????????????????"
486        );
487    }
488}
489
490/// `ALIGNMENT_PATTERN_POSITIONS` describes the x- and y-coordinates of the
491/// center of the alignment patterns. Since the QR code is symmetric, only one
492/// coordinate is needed.
493static ALIGNMENT_PATTERN_POSITIONS: [&[i16]; 34] = [
494    &[6, 22, 38],
495    &[6, 24, 42],
496    &[6, 26, 46],
497    &[6, 28, 50],
498    &[6, 30, 54],
499    &[6, 32, 58],
500    &[6, 34, 62],
501    &[6, 26, 46, 66],
502    &[6, 26, 48, 70],
503    &[6, 26, 50, 74],
504    &[6, 30, 54, 78],
505    &[6, 30, 56, 82],
506    &[6, 30, 58, 86],
507    &[6, 34, 62, 90],
508    &[6, 28, 50, 72, 94],
509    &[6, 26, 50, 74, 98],
510    &[6, 30, 54, 78, 102],
511    &[6, 28, 54, 80, 106],
512    &[6, 32, 58, 84, 110],
513    &[6, 30, 58, 86, 114],
514    &[6, 34, 62, 90, 118],
515    &[6, 26, 50, 74, 98, 122],
516    &[6, 30, 54, 78, 102, 126],
517    &[6, 26, 52, 78, 104, 130],
518    &[6, 30, 56, 82, 108, 134],
519    &[6, 34, 60, 86, 112, 138],
520    &[6, 30, 58, 86, 114, 142],
521    &[6, 34, 62, 90, 118, 146],
522    &[6, 30, 54, 78, 102, 126, 150],
523    &[6, 24, 50, 76, 102, 128, 154],
524    &[6, 28, 54, 80, 106, 132, 158],
525    &[6, 32, 58, 84, 110, 136, 162],
526    &[6, 26, 54, 82, 110, 138, 166],
527    &[6, 30, 58, 86, 114, 142, 170],
528];
529
530//}}}
531//------------------------------------------------------------------------------
532//{{{ Timing patterns
533
534impl Canvas {
535    /// Draws a line from (x1, y1) to (x2, y2), inclusively.
536    ///
537    /// The line must be either horizontal or vertical, i.e.
538    /// `x1 == x2 || y1 == y2`. Additionally, the first coordinates must be less
539    /// then the second ones.
540    ///
541    /// On even coordinates, `color_even` will be plotted; on odd coordinates,
542    /// `color_odd` will be plotted instead. Thus the timing pattern can be
543    /// drawn using this method.
544    ///
545    fn draw_line(&mut self, x1: i16, y1: i16, x2: i16, y2: i16, color_even: Color, color_odd: Color) {
546        debug_assert!(x1 == x2 || y1 == y2);
547
548        if y1 == y2 {
549            // Horizontal line.
550            for x in x1..=x2 {
551                self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd });
552            }
553        } else {
554            // Vertical line.
555            for y in y1..=y2 {
556                self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd });
557            }
558        }
559    }
560
561    /// Draws the timing patterns.
562    ///
563    /// The timing patterns are checkboard-colored lines near the edge of the QR
564    /// code symbol, to establish the fine-grained module coordinates when
565    /// scanning.
566    fn draw_timing_patterns(&mut self) {
567        let width = self.width;
568        let (y, x1, x2) = match self.version {
569            Version::Micro(_) => (0, 8, width - 1),
570            Version::Normal(_) => (6, 8, width - 9),
571        };
572        self.draw_line(x1, y, x2, y, Color::Dark, Color::Light);
573        self.draw_line(y, x1, y, x2, Color::Dark, Color::Light);
574    }
575}
576
577#[cfg(test)]
578mod timing_pattern_tests {
579    use crate::canvas::Canvas;
580    use crate::types::{EcLevel, Version};
581
582    #[test]
583    fn test_draw_timing_patterns_qr() {
584        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
585        c.draw_timing_patterns();
586        assert_eq!(
587            &*c.to_debug_str(),
588            "\n\
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             ?????????????????????"
610        );
611    }
612
613    #[test]
614    fn test_draw_timing_patterns_micro_qr() {
615        let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
616        c.draw_timing_patterns();
617        assert_eq!(
618            &*c.to_debug_str(),
619            "\n\
620             ????????#.#\n\
621             ???????????\n\
622             ???????????\n\
623             ???????????\n\
624             ???????????\n\
625             ???????????\n\
626             ???????????\n\
627             ???????????\n\
628             #??????????\n\
629             .??????????\n\
630             #??????????"
631        );
632    }
633}
634
635//}}}
636//------------------------------------------------------------------------------
637//{{{ Format info & Version info
638
639impl Canvas {
640    /// Draws a big-endian integer onto the canvas with the given coordinates.
641    ///
642    /// The 1 bits will be plotted with `on_color` and the 0 bits with
643    /// `off_color`. The coordinates will be extracted from the `coords`
644    /// iterator. It will start from the most significant bits first, so
645    /// *trailing* zeros will be ignored.
646    fn draw_number(&mut self, number: u32, bits: u32, on_color: Color, off_color: Color, coords: &[(i16, i16)]) {
647        let mut mask = 1 << (bits - 1);
648        for &(x, y) in coords {
649            let color = if (mask & number) == 0 { off_color } else { on_color };
650            self.put(x, y, color);
651            mask >>= 1;
652        }
653    }
654
655    /// Draws the format info patterns for an encoded number.
656    fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
657        let format_info = u32::from(format_info);
658        match self.version {
659            Version::Micro(_) => {
660                self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_MICRO_QR);
661            }
662            Version::Normal(_) => {
663                self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_MAIN);
664                self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_SIDE);
665                self.put(8, -8, Color::Dark); // Dark module.
666            }
667        }
668    }
669
670    /// Reserves area to put in the format information.
671    fn draw_reserved_format_info_patterns(&mut self) {
672        self.draw_format_info_patterns_with_number(0);
673    }
674
675    /// Draws the version information patterns.
676    fn draw_version_info_patterns(&mut self) {
677        match self.version {
678            Version::Micro(_) | Version::Normal(1..=6) => {}
679            Version::Normal(a) => {
680                let version_info = VERSION_INFOS[(a - 7).as_usize()];
681                self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_BL);
682                self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_TR);
683            }
684        }
685    }
686}
687
688#[cfg(test)]
689mod draw_version_info_tests {
690    use crate::canvas::Canvas;
691    use crate::types::{Color, EcLevel, Version};
692
693    #[test]
694    fn test_draw_number() {
695        let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
696        c.draw_number(0b10101101, 8, Color::Dark, Color::Light, &[(0, 0), (0, -1), (-2, -2), (-2, 0)]);
697        assert_eq!(
698            &*c.to_debug_str(),
699            "\n\
700             #????????.?\n\
701             ???????????\n\
702             ???????????\n\
703             ???????????\n\
704             ???????????\n\
705             ???????????\n\
706             ???????????\n\
707             ???????????\n\
708             ???????????\n\
709             ?????????#?\n\
710             .??????????"
711        );
712    }
713
714    #[test]
715    fn test_draw_version_info_1() {
716        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
717        c.draw_version_info_patterns();
718        assert_eq!(
719            &*c.to_debug_str(),
720            "\n\
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             ?????????????????????"
742        );
743    }
744
745    #[test]
746    fn test_draw_version_info_7() {
747        let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
748        c.draw_version_info_patterns();
749
750        assert_eq!(
751            &*c.to_debug_str(),
752            "\n\
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             ?????????????????????????????????????????????"
798        );
799    }
800
801    #[test]
802    fn test_draw_reserved_format_info_patterns_qr() {
803        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
804        c.draw_reserved_format_info_patterns();
805        assert_eq!(
806            &*c.to_debug_str(),
807            "\n\
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             ????????.????????????"
829        );
830    }
831
832    #[test]
833    fn test_draw_reserved_format_info_patterns_micro_qr() {
834        let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
835        c.draw_reserved_format_info_patterns();
836        assert_eq!(
837            &*c.to_debug_str(),
838            "\n\
839             ???????????\n\
840             ????????.??\n\
841             ????????.??\n\
842             ????????.??\n\
843             ????????.??\n\
844             ????????.??\n\
845             ????????.??\n\
846             ????????.??\n\
847             ?........??\n\
848             ???????????\n\
849             ???????????"
850        );
851    }
852}
853
854static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [
855    (5, -9),
856    (5, -10),
857    (5, -11),
858    (4, -9),
859    (4, -10),
860    (4, -11),
861    (3, -9),
862    (3, -10),
863    (3, -11),
864    (2, -9),
865    (2, -10),
866    (2, -11),
867    (1, -9),
868    (1, -10),
869    (1, -11),
870    (0, -9),
871    (0, -10),
872    (0, -11),
873];
874
875static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [
876    (-9, 5),
877    (-10, 5),
878    (-11, 5),
879    (-9, 4),
880    (-10, 4),
881    (-11, 4),
882    (-9, 3),
883    (-10, 3),
884    (-11, 3),
885    (-9, 2),
886    (-10, 2),
887    (-11, 2),
888    (-9, 1),
889    (-10, 1),
890    (-11, 1),
891    (-9, 0),
892    (-10, 0),
893    (-11, 0),
894];
895
896static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [
897    (0, 8),
898    (1, 8),
899    (2, 8),
900    (3, 8),
901    (4, 8),
902    (5, 8),
903    (7, 8),
904    (8, 8),
905    (8, 7),
906    (8, 5),
907    (8, 4),
908    (8, 3),
909    (8, 2),
910    (8, 1),
911    (8, 0),
912];
913
914static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [
915    (8, -1),
916    (8, -2),
917    (8, -3),
918    (8, -4),
919    (8, -5),
920    (8, -6),
921    (8, -7),
922    (-8, 8),
923    (-7, 8),
924    (-6, 8),
925    (-5, 8),
926    (-4, 8),
927    (-3, 8),
928    (-2, 8),
929    (-1, 8),
930];
931
932static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [
933    (1, 8),
934    (2, 8),
935    (3, 8),
936    (4, 8),
937    (5, 8),
938    (6, 8),
939    (7, 8),
940    (8, 8),
941    (8, 7),
942    (8, 6),
943    (8, 5),
944    (8, 4),
945    (8, 3),
946    (8, 2),
947    (8, 1),
948];
949
950static VERSION_INFOS: [u32; 34] = [
951    0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78, 0x1145d, 0x12a17,
952    0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
953    0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 0x27541, 0x28c69,
954];
955
956//}}}
957//------------------------------------------------------------------------------
958//{{{ All functional patterns before data placement
959
960impl Canvas {
961    /// Draw all functional patterns, before data placement.
962    ///
963    /// All functional patterns (e.g. the finder pattern) *except* the format
964    /// info pattern will be filled in. The format info pattern will be filled
965    /// with light modules instead. Data bits can then put in the empty modules.
966    /// with `.draw_data()`.
967    pub fn draw_all_functional_patterns(&mut self) {
968        self.draw_finder_patterns();
969        self.draw_alignment_patterns();
970        self.draw_reserved_format_info_patterns();
971        self.draw_timing_patterns();
972        self.draw_version_info_patterns();
973    }
974}
975
976/// Gets whether the module at the given coordinates represents a functional
977/// module.
978pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool {
979    debug_assert!(width == version.width());
980
981    let x = if x < 0 { x + width } else { x };
982    let y = if y < 0 { y + width } else { y };
983
984    match version {
985        Version::Micro(_) => x == 0 || y == 0 || (x < 9 && y < 9),
986        Version::Normal(a) => {
987            let non_alignment_test = x == 6 || y == 6 || // Timing patterns
988                    (x < 9 && y < 9) ||                  // Top-left finder pattern
989                    (x < 9 && y >= width-8) ||           // Bottom-left finder pattern
990                    (x >= width-8 && y < 9); // Top-right finder pattern
991            if non_alignment_test {
992                true
993            } else if a == 1 {
994                false
995            } else if 2 <= a && a <= 6 {
996                (width - 7 - x).abs() <= 2 && (width - 7 - y).abs() <= 2
997            } else {
998                let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
999                let last = positions.len() - 1;
1000                for (i, align_x) in positions.iter().enumerate() {
1001                    for (j, align_y) in positions.iter().enumerate() {
1002                        if i == 0 && (j == 0 || j == last) || (i == last && j == 0) {
1003                            continue;
1004                        }
1005                        if (*align_x - x).abs() <= 2 && (*align_y - y).abs() <= 2 {
1006                            return true;
1007                        }
1008                    }
1009                }
1010                false
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                while let Some((x, y)) = coords.next() {
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 = match (self.version, self.ec_level) {
1382            (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M) => true,
1383            _ => false,
1384        };
1385
1386        let mut coords = DataModuleIter::new(self.version);
1387        self.draw_codewords(data, is_half_codeword_at_end, &mut coords);
1388        self.draw_codewords(ec, false, &mut coords);
1389    }
1390}
1391
1392#[cfg(test)]
1393mod draw_codewords_test {
1394    use crate::canvas::Canvas;
1395    use crate::types::{EcLevel, Version};
1396
1397    #[test]
1398    fn test_micro_qr_1() {
1399        let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1400        c.draw_all_functional_patterns();
1401        c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
1402        assert_eq!(
1403            &*c.to_debug_str(),
1404            "\n\
1405             #######.#.#\n\
1406             #.....#..-*\n\
1407             #.###.#..**\n\
1408             #.###.#..*-\n\
1409             #.###.#..**\n\
1410             #.....#..*-\n\
1411             #######..*-\n\
1412             .........-*\n\
1413             #........**\n\
1414             .***-**---*\n\
1415             #---*-*-**-"
1416        );
1417    }
1418
1419    #[test]
1420    fn test_qr_2() {
1421        let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1422        c.draw_all_functional_patterns();
1423        c.draw_data(
1424            b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\
1425              \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$",
1426            b"",
1427        );
1428        assert_eq!(
1429            &*c.to_debug_str(),
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             #.###.#..*---*--*----*--*\n\
1453             #.###.#..--*------**-----\n\
1454             #.....#..-*-*-**-*--*-**-\n\
1455             #######..*---*--*----*--*"
1456        );
1457    }
1458}
1459//}}}
1460//------------------------------------------------------------------------------
1461//{{{ Masking
1462
1463/// The mask patterns. Since QR code and Micro QR code do not use the same
1464/// pattern number, we name them according to their shape instead of the number.
1465#[derive(Debug, Copy, Clone)]
1466pub enum MaskPattern {
1467    /// QR code pattern 000: `(x + y) % 2 == 0`.
1468    Checkerboard = 0b000,
1469
1470    /// QR code pattern 001: `y % 2 == 0`.
1471    HorizontalLines = 0b001,
1472
1473    /// QR code pattern 010: `x % 3 == 0`.
1474    VerticalLines = 0b010,
1475
1476    /// QR code pattern 011: `(x + y) % 3 == 0`.
1477    DiagonalLines = 0b011,
1478
1479    /// QR code pattern 100: `((x/3) + (y/2)) % 2 == 0`.
1480    LargeCheckerboard = 0b100,
1481
1482    /// QR code pattern 101: `(x*y)%2 + (x*y)%3 == 0`.
1483    Fields = 0b101,
1484
1485    /// QR code pattern 110: `((x*y)%2 + (x*y)%3) % 2 == 0`.
1486    Diamonds = 0b110,
1487
1488    /// QR code pattern 111: `((x+y)%2 + (x*y)%3) % 2 == 0`.
1489    Meadow = 0b111,
1490}
1491
1492mod mask_functions {
1493    pub fn checkerboard(x: i16, y: i16) -> bool {
1494        (x + y) % 2 == 0
1495    }
1496    pub fn horizontal_lines(_: i16, y: i16) -> bool {
1497        y % 2 == 0
1498    }
1499    pub fn vertical_lines(x: i16, _: i16) -> bool {
1500        x % 3 == 0
1501    }
1502    pub fn diagonal_lines(x: i16, y: i16) -> bool {
1503        (x + y) % 3 == 0
1504    }
1505    pub fn large_checkerboard(x: i16, y: i16) -> bool {
1506        ((y / 2) + (x / 3)) % 2 == 0
1507    }
1508    pub fn fields(x: i16, y: i16) -> bool {
1509        (x * y) % 2 + (x * y) % 3 == 0
1510    }
1511    pub fn diamonds(x: i16, y: i16) -> bool {
1512        ((x * y) % 2 + (x * y) % 3) % 2 == 0
1513    }
1514    pub fn meadow(x: i16, y: i16) -> bool {
1515        ((x + y) % 2 + (x * y) % 3) % 2 == 0
1516    }
1517}
1518
1519fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
1520    match pattern {
1521        MaskPattern::Checkerboard => mask_functions::checkerboard,
1522        MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
1523        MaskPattern::VerticalLines => mask_functions::vertical_lines,
1524        MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
1525        MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
1526        MaskPattern::Fields => mask_functions::fields,
1527        MaskPattern::Diamonds => mask_functions::diamonds,
1528        MaskPattern::Meadow => mask_functions::meadow,
1529    }
1530}
1531
1532impl Canvas {
1533    /// Applies a mask to the canvas. This method will also draw the format info
1534    /// patterns.
1535    pub fn apply_mask(&mut self, pattern: MaskPattern) {
1536        let mask_fn = get_mask_function(pattern);
1537        for x in 0..self.width {
1538            for y in 0..self.width {
1539                let module = self.get_mut(x, y);
1540                *module = module.mask(mask_fn(x, y));
1541            }
1542        }
1543
1544        self.draw_format_info_patterns(pattern);
1545    }
1546
1547    /// Draws the format information to encode the error correction level and
1548    /// mask pattern.
1549    ///
1550    /// If the error correction level or mask pattern is not supported in the
1551    /// current QR code version, this method will fail.
1552    fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
1553        let format_number = match self.version {
1554            Version::Normal(_) => {
1555                let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize);
1556                FORMAT_INFOS_QR[simple_format_number]
1557            }
1558            Version::Micro(a) => {
1559                let micro_pattern_number = match pattern {
1560                    MaskPattern::HorizontalLines => 0b00,
1561                    MaskPattern::LargeCheckerboard => 0b01,
1562                    MaskPattern::Diamonds => 0b10,
1563                    MaskPattern::Meadow => 0b11,
1564                    _ => panic!("Unsupported mask pattern in Micro QR code"),
1565                };
1566                let symbol_number = match (a, self.ec_level) {
1567                    (1, EcLevel::L) => 0b000,
1568                    (2, EcLevel::L) => 0b001,
1569                    (2, EcLevel::M) => 0b010,
1570                    (3, EcLevel::L) => 0b011,
1571                    (3, EcLevel::M) => 0b100,
1572                    (4, EcLevel::L) => 0b101,
1573                    (4, EcLevel::M) => 0b110,
1574                    (4, EcLevel::Q) => 0b111,
1575                    _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
1576                };
1577                let simple_format_number = symbol_number << 2 | micro_pattern_number;
1578                FORMAT_INFOS_MICRO_QR[simple_format_number]
1579            }
1580        };
1581        self.draw_format_info_patterns_with_number(format_number);
1582    }
1583}
1584
1585#[cfg(test)]
1586mod mask_tests {
1587    use crate::canvas::{Canvas, MaskPattern};
1588    use crate::types::{EcLevel, Version};
1589
1590    #[test]
1591    fn test_apply_mask_qr() {
1592        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1593        c.draw_all_functional_patterns();
1594        c.apply_mask(MaskPattern::Checkerboard);
1595
1596        assert_eq!(
1597            &*c.to_debug_str(),
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             #.###.#..#.#.#.#.#.#.\n\
1617             #.###.#.#.#.#.#.#.#.#\n\
1618             #.....#.##.#.#.#.#.#.\n\
1619             #######.#.#.#.#.#.#.#"
1620        );
1621    }
1622
1623    #[test]
1624    fn test_draw_format_info_patterns_qr() {
1625        let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1626        c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1627        assert_eq!(
1628            &*c.to_debug_str(),
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             ????????.????????????\n\
1648             ????????.????????????\n\
1649             ????????#????????????\n\
1650             ????????#????????????"
1651        );
1652    }
1653
1654    #[test]
1655    fn test_draw_format_info_patterns_micro_qr() {
1656        let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
1657        c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1658        assert_eq!(
1659            &*c.to_debug_str(),
1660            "\n\
1661             ?????????????\n\
1662             ????????#????\n\
1663             ????????.????\n\
1664             ????????.????\n\
1665             ????????#????\n\
1666             ????????#????\n\
1667             ????????.????\n\
1668             ????????.????\n\
1669             ?#.#....#????\n\
1670             ?????????????\n\
1671             ?????????????\n\
1672             ?????????????\n\
1673             ?????????????"
1674        );
1675    }
1676}
1677
1678static FORMAT_INFOS_QR: [u16; 32] = [
1679    0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318,
1680    0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06,
1681    0x24b4, 0x2183, 0x2eda, 0x2bed,
1682];
1683
1684static FORMAT_INFOS_MICRO_QR: [u16; 32] = [
1685    0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f,
1686    0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51,
1687    0x34e3, 0x31d4, 0x3e8d, 0x3bba,
1688];
1689
1690//}}}
1691//------------------------------------------------------------------------------
1692//{{{ Penalty score
1693
1694impl Canvas {
1695    /// Compute the penalty score for having too many adjacent modules with the
1696    /// same color.
1697    ///
1698    /// Every 5+N adjacent modules in the same column/row having the same color
1699    /// will contribute 3+N points.
1700    fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 {
1701        let mut total_score = 0;
1702
1703        for i in 0..self.width {
1704            let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) };
1705
1706            let colors = (0..self.width).map(map_fn).chain(Some(Module::Empty).into_iter());
1707            let mut last_color = Module::Empty;
1708            let mut consecutive_len = 1_u16;
1709
1710            for color in colors {
1711                if color == last_color {
1712                    consecutive_len += 1;
1713                } else {
1714                    last_color = color;
1715                    if consecutive_len >= 5 {
1716                        total_score += consecutive_len - 2;
1717                    }
1718                    consecutive_len = 1;
1719                }
1720            }
1721        }
1722
1723        total_score
1724    }
1725
1726    /// Compute the penalty score for having too many rectangles with the same
1727    /// color.
1728    ///
1729    /// Every 2×2 blocks (with overlapping counted) having the same color will
1730    /// contribute 3 points.
1731    fn compute_block_penalty_score(&self) -> u16 {
1732        let mut total_score = 0;
1733
1734        for i in 0..self.width - 1 {
1735            for j in 0..self.width - 1 {
1736                let this = self.get(i, j);
1737                let right = self.get(i + 1, j);
1738                let bottom = self.get(i, j + 1);
1739                let bottom_right = self.get(i + 1, j + 1);
1740                if this == right && right == bottom && bottom == bottom_right {
1741                    total_score += 3;
1742                }
1743            }
1744        }
1745
1746        total_score
1747    }
1748
1749    /// Compute the penalty score for having a pattern similar to the finder
1750    /// pattern in the wrong place.
1751    ///
1752    /// Every pattern that looks like `#.###.#....` in any orientation will add
1753    /// 40 points.
1754    fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
1755        static PATTERN: [Color; 7] =
1756            [Color::Dark, Color::Light, Color::Dark, Color::Dark, Color::Dark, Color::Light, Color::Dark];
1757
1758        let mut total_score = 0;
1759
1760        for i in 0..self.width {
1761            for j in 0..self.width - 6 {
1762                // TODO a ref to a closure should be enough?
1763                let get: Box<dyn Fn(i16) -> Color> = if is_horizontal {
1764                    Box::new(|k| self.get(k, i).into())
1765                } else {
1766                    Box::new(|k| self.get(i, k).into())
1767                };
1768
1769                if (j..(j + 7)).map(&*get).ne(PATTERN.iter().cloned()) {
1770                    continue;
1771                }
1772
1773                let check = |k| 0 <= k && k < self.width && get(k) != Color::Light;
1774                if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) {
1775                    total_score += 40;
1776                }
1777            }
1778        }
1779
1780        total_score - 360
1781    }
1782
1783    /// Compute the penalty score for having an unbalanced dark/light ratio.
1784    ///
1785    /// The score is given linearly by the deviation from a 50% ratio of dark
1786    /// modules. The highest possible score is 100.
1787    ///
1788    /// Note that this algorithm differs slightly from the standard we do not
1789    /// round the result every 5%, but the difference should be negligible and
1790    /// should not affect which mask is chosen.
1791    fn compute_balance_penalty_score(&self) -> u16 {
1792        let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count();
1793        let total_modules = self.modules.len();
1794        let ratio = dark_modules * 200 / total_modules;
1795        if ratio >= 100 { ratio - 100 } else { 100 - ratio }.as_u16()
1796    }
1797
1798    /// Compute the penalty score for having too many light modules on the sides.
1799    ///
1800    /// This penalty score is exclusive to Micro QR code.
1801    ///
1802    /// Note that the standard gives the formula for *efficiency* score, which
1803    /// has the inverse meaning of this method, but it is very easy to convert
1804    /// between the two (this score is (16×width − standard-score)).
1805    fn compute_light_side_penalty_score(&self) -> u16 {
1806        let h = (1..self.width).filter(|j| !self.get(*j, -1).is_dark()).count();
1807        let v = (1..self.width).filter(|j| !self.get(-1, *j).is_dark()).count();
1808
1809        (h + v + 15 * max(h, v)).as_u16()
1810    }
1811
1812    /// Compute the total penalty scores. A QR code having higher points is less
1813    /// desirable.
1814    fn compute_total_penalty_scores(&self) -> u16 {
1815        match self.version {
1816            Version::Normal(_) => {
1817                let s1_a = self.compute_adjacent_penalty_score(true);
1818                let s1_b = self.compute_adjacent_penalty_score(false);
1819                let s2 = self.compute_block_penalty_score();
1820                let s3_a = self.compute_finder_penalty_score(true);
1821                let s3_b = self.compute_finder_penalty_score(false);
1822                let s4 = self.compute_balance_penalty_score();
1823                s1_a + s1_b + s2 + s3_a + s3_b + s4
1824            }
1825            Version::Micro(_) => self.compute_light_side_penalty_score(),
1826        }
1827    }
1828}
1829
1830#[cfg(test)]
1831mod penalty_tests {
1832    use crate::canvas::{Canvas, MaskPattern};
1833    use crate::types::{Color, EcLevel, Version};
1834
1835    fn create_test_canvas() -> Canvas {
1836        let mut c = Canvas::new(Version::Normal(1), EcLevel::Q);
1837        c.draw_all_functional_patterns();
1838        c.draw_data(
1839            b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00",
1840            b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10",
1841        );
1842        c.apply_mask(MaskPattern::Checkerboard);
1843        c
1844    }
1845
1846    #[test]
1847    fn check_penalty_canvas() {
1848        let c = create_test_canvas();
1849        assert_eq!(
1850            &*c.to_debug_str(),
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             #.###.#..#.#.#.#...#.\n\
1870             #.###.#.#...####.#..#\n\
1871             #.....#.#.##.#...#.##\n\
1872             #######.....####....#"
1873        );
1874    }
1875
1876    #[test]
1877    fn test_penalty_score_adjacent() {
1878        let c = create_test_canvas();
1879        assert_eq!(c.compute_adjacent_penalty_score(true), 88);
1880        assert_eq!(c.compute_adjacent_penalty_score(false), 92);
1881    }
1882
1883    #[test]
1884    fn test_penalty_score_block() {
1885        let c = create_test_canvas();
1886        assert_eq!(c.compute_block_penalty_score(), 90);
1887    }
1888
1889    #[test]
1890    fn test_penalty_score_finder() {
1891        let c = create_test_canvas();
1892        assert_eq!(c.compute_finder_penalty_score(true), 0);
1893        assert_eq!(c.compute_finder_penalty_score(false), 40);
1894    }
1895
1896    #[test]
1897    fn test_penalty_score_balance() {
1898        let c = create_test_canvas();
1899        assert_eq!(c.compute_balance_penalty_score(), 2);
1900    }
1901
1902    #[test]
1903    fn test_penalty_score_light_sides() {
1904        static HORIZONTAL_SIDE: [Color; 17] = [
1905            Color::Dark,
1906            Color::Light,
1907            Color::Light,
1908            Color::Dark,
1909            Color::Dark,
1910            Color::Dark,
1911            Color::Light,
1912            Color::Light,
1913            Color::Dark,
1914            Color::Light,
1915            Color::Dark,
1916            Color::Light,
1917            Color::Light,
1918            Color::Dark,
1919            Color::Light,
1920            Color::Light,
1921            Color::Light,
1922        ];
1923        static VERTICAL_SIDE: [Color; 17] = [
1924            Color::Dark,
1925            Color::Dark,
1926            Color::Dark,
1927            Color::Light,
1928            Color::Light,
1929            Color::Dark,
1930            Color::Dark,
1931            Color::Light,
1932            Color::Dark,
1933            Color::Light,
1934            Color::Dark,
1935            Color::Light,
1936            Color::Dark,
1937            Color::Light,
1938            Color::Light,
1939            Color::Dark,
1940            Color::Light,
1941        ];
1942
1943        let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
1944        for i in 0_i16..17 {
1945            c.put(i, -1, HORIZONTAL_SIDE[i as usize]);
1946            c.put(-1, i, VERTICAL_SIDE[i as usize]);
1947        }
1948
1949        assert_eq!(c.compute_light_side_penalty_score(), 168);
1950    }
1951}
1952
1953//}}}
1954//------------------------------------------------------------------------------
1955//{{{ Select mask with lowest penalty score
1956
1957static ALL_PATTERNS_QR: [MaskPattern; 8] = [
1958    MaskPattern::Checkerboard,
1959    MaskPattern::HorizontalLines,
1960    MaskPattern::VerticalLines,
1961    MaskPattern::DiagonalLines,
1962    MaskPattern::LargeCheckerboard,
1963    MaskPattern::Fields,
1964    MaskPattern::Diamonds,
1965    MaskPattern::Meadow,
1966];
1967
1968static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] =
1969    [MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, MaskPattern::Diamonds, MaskPattern::Meadow];
1970
1971impl Canvas {
1972    /// Construct a new canvas and apply the best masking that gives the lowest
1973    /// penalty score.
1974    pub fn apply_best_mask(&self) -> Self {
1975        match self.version {
1976            Version::Normal(_) => ALL_PATTERNS_QR.iter(),
1977            Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
1978        }
1979        .map(|ptn| {
1980            let mut c = self.clone();
1981            c.apply_mask(*ptn);
1982            c
1983        })
1984        .min_by_key(Self::compute_total_penalty_scores)
1985        .expect("at least one pattern")
1986    }
1987
1988    /// Convert the modules into a vector of booleans.
1989    #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")]
1990    pub fn to_bools(&self) -> Vec<bool> {
1991        self.modules.iter().map(|m| m.is_dark()).collect()
1992    }
1993
1994    /// Convert the modules into a vector of colors.
1995    pub fn into_colors(self) -> Vec<Color> {
1996        self.modules.into_iter().map(Color::from).collect()
1997    }
1998}
1999
2000//}}}
2001//------------------------------------------------------------------------------