1use std::cmp::max;
13
14use crate::cast::As;
15use crate::types::{Color, EcLevel, Version};
16
17#[derive(PartialEq, Eq, Clone, Copy, Debug)]
22pub enum Module {
23 Empty,
25
26 Masked(Color),
29
30 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 pub fn is_dark(self) -> bool {
46 Color::from(self) == Color::Dark
47 }
48
49 #[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#[derive(Clone)]
78pub struct Canvas {
79 width: i16,
81
82 version: Version,
84
85 ec_level: EcLevel,
87
88 modules: Vec<Module>,
91}
92
93impl Canvas {
94 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 #[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 pub fn get(&self, x: i16, y: i16) -> Module {
129 self.modules[self.coords_to_index(x, y)]
130 }
131
132 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 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
211impl Canvas {
216 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 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
313impl Canvas {
318 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 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
491static 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
531impl Canvas {
536 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 for x in x1..=x2 {
552 self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd });
553 }
554 } else {
555 for y in y1..=y2 {
557 self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd });
558 }
559 }
560 }
561
562 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
636impl Canvas {
641 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 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); }
668 }
669 }
670
671 fn draw_reserved_format_info_patterns(&mut self) {
673 self.draw_format_info_patterns_with_number(0);
674 }
675
676 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(0b1010_1101, 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
957impl Canvas {
962 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
977pub 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 || (x < 9 && y < 9) || (x < 9 && y >= width - 8) || (x >= width - 8 && y < 9); 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
1127struct 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] mod 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 (18, 0), (17, 0), (18, 1), (17, 1), (18, 2), (17, 2),
1204 (18, 3), (17, 3), (18, 4), (17, 4), (18, 5), (17, 5),
1205 (18, 6), (17, 6), (18, 7), (17, 7), (18, 8), (17, 8),
1206 (18, 9), (17, 9), (18, 10), (17, 10), (18, 11), (17, 11),
1207 (18, 12), (17, 12), (18, 13), (17, 13), (18, 14), (17, 14),
1208 (18, 15), (17, 15), (18, 16), (17, 16), (18, 17), (17, 17),
1209 (18, 18), (17, 18), (18, 19), (17, 19), (18, 20), (17, 20),
1210 (16, 20), (15, 20), (16, 19), (15, 19), (16, 18), (15, 18),
1211 (16, 17), (15, 17), (16, 16), (15, 16), (16, 15), (15, 15),
1212 (16, 14), (15, 14), (16, 13), (15, 13), (16, 12), (15, 12),
1213 (16, 11), (15, 11), (16, 10), (15, 10), (16, 9), (15, 9),
1214 (16, 8), (15, 8), (16, 7), (15, 7), (16, 6), (15, 6),
1215 (16, 5), (15, 5), (16, 4), (15, 4), (16, 3), (15, 3),
1216 (16, 2), (15, 2), (16, 1), (15, 1), (16, 0), (15, 0),
1217 (14, 0), (13, 0), (14, 1), (13, 1), (14, 2), (13, 2),
1218 (14, 3), (13, 3), (14, 4), (13, 4), (14, 5), (13, 5),
1219 (14, 6), (13, 6), (14, 7), (13, 7), (14, 8), (13, 8),
1220 (14, 9), (13, 9), (14, 10), (13, 10), (14, 11), (13, 11),
1221 (14, 12), (13, 12), (14, 13), (13, 13), (14, 14), (13, 14),
1222 (14, 15), (13, 15), (14, 16), (13, 16), (14, 17), (13, 17),
1223 (14, 18), (13, 18), (14, 19), (13, 19), (14, 20), (13, 20),
1224 (12, 20), (11, 20), (12, 19), (11, 19), (12, 18), (11, 18),
1225 (12, 17), (11, 17), (12, 16), (11, 16), (12, 15), (11, 15),
1226 (12, 14), (11, 14), (12, 13), (11, 13), (12, 12), (11, 12),
1227 (12, 11), (11, 11), (12, 10), (11, 10), (12, 9), (11, 9),
1228 (12, 8), (11, 8), (12, 7), (11, 7), (12, 6), (11, 6),
1229 (12, 5), (11, 5), (12, 4), (11, 4), (12, 3), (11, 3),
1230 (12, 2), (11, 2), (12, 1), (11, 1), (12, 0), (11, 0),
1231 (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2),
1232 (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5),
1233 (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8),
1234 (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11),
1235 (10, 12), (9, 12), (10, 13), (9, 13), (10, 14), (9, 14),
1236 (10, 15), (9, 15), (10, 16), (9, 16), (10, 17), (9, 17),
1237 (10, 18), (9, 18), (10, 19), (9, 19), (10, 20), (9, 20),
1238 (8, 20), (7, 20), (8, 19), (7, 19), (8, 18), (7, 18),
1239 (8, 17), (7, 17), (8, 16), (7, 16), (8, 15), (7, 15),
1240 (8, 14), (7, 14), (8, 13), (7, 13), (8, 12), (7, 12),
1241 (8, 11), (7, 11), (8, 10), (7, 10), (8, 9), (7, 9),
1242 (8, 8), (7, 8), (8, 7), (7, 7), (8, 6), (7, 6),
1243 (8, 5), (7, 5), (8, 4), (7, 4), (8, 3), (7, 3),
1244 (8, 2), (7, 2), (8, 1), (7, 1), (8, 0), (7, 0),
1245 (5, 0), (4, 0), (5, 1), (4, 1), (5, 2), (4, 2),
1246 (5, 3), (4, 3), (5, 4), (4, 4), (5, 5), (4, 5),
1247 (5, 6), (4, 6), (5, 7), (4, 7), (5, 8), (4, 8),
1248 (5, 9), (4, 9), (5, 10), (4, 10), (5, 11), (4, 11),
1249 (5, 12), (4, 12), (5, 13), (4, 13), (5, 14), (4, 14),
1250 (5, 15), (4, 15), (5, 16), (4, 16), (5, 17), (4, 17),
1251 (5, 18), (4, 18), (5, 19), (4, 19), (5, 20), (4, 20),
1252 (3, 20), (2, 20), (3, 19), (2, 19), (3, 18), (2, 18),
1253 (3, 17), (2, 17), (3, 16), (2, 16), (3, 15), (2, 15),
1254 (3, 14), (2, 14), (3, 13), (2, 13), (3, 12), (2, 12),
1255 (3, 11), (2, 11), (3, 10), (2, 10), (3, 9), (2, 9),
1256 (3, 8), (2, 8), (3, 7), (2, 7), (3, 6), (2, 6),
1257 (3, 5), (2, 5), (3, 4), (2, 4), (3, 3), (2, 3),
1258 (3, 2), (2, 2), (3, 1), (2, 1), (3, 0), (2, 0),
1259 (1, 0), (0, 0), (1, 1), (0, 1), (1, 2), (0, 2),
1260 (1, 3), (0, 3), (1, 4), (0, 4), (1, 5), (0, 5),
1261 (1, 6), (0, 6), (1, 7), (0, 7), (1, 8), (0, 8),
1262 (1, 9), (0, 9), (1, 10), (0, 10), (1, 11), (0, 11),
1263 (1, 12), (0, 12), (1, 13), (0, 13), (1, 14), (0, 14),
1264 (1, 15), (0, 15), (1, 16), (0, 16), (1, 17), (0, 17),
1265 (1, 18), (0, 18), (1, 19), (0, 19), (1, 20), (0, 20),
1266 ]);
1267 }
1268
1269 #[test]
1270 fn test_micro_qr() {
1271 let res = DataModuleIter::new(Version::Micro(1)).collect::<Vec<(i16, i16)>>();
1272 assert_eq!(res, vec![
1273 (10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8),
1274 (10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5),
1275 (10, 4), (9, 4), (10, 3), (9, 3), (10, 2), (9, 2),
1276 (10, 1), (9, 1), (10, 0), (9, 0),
1277 (8, 0), (7, 0), (8, 1), (7, 1), (8, 2), (7, 2),
1278 (8, 3), (7, 3), (8, 4), (7, 4), (8, 5), (7, 5),
1279 (8, 6), (7, 6), (8, 7), (7, 7), (8, 8), (7, 8),
1280 (8, 9), (7, 9), (8, 10), (7, 10),
1281 (6, 10), (5, 10), (6, 9), (5, 9), (6, 8), (5, 8),
1282 (6, 7), (5, 7), (6, 6), (5, 6), (6, 5), (5, 5),
1283 (6, 4), (5, 4), (6, 3), (5, 3), (6, 2), (5, 2),
1284 (6, 1), (5, 1), (6, 0), (5, 0),
1285 (4, 0), (3, 0), (4, 1), (3, 1), (4, 2), (3, 2),
1286 (4, 3), (3, 3), (4, 4), (3, 4), (4, 5), (3, 5),
1287 (4, 6), (3, 6), (4, 7), (3, 7), (4, 8), (3, 8),
1288 (4, 9), (3, 9), (4, 10), (3, 10),
1289 (2, 10), (1, 10), (2, 9), (1, 9), (2, 8), (1, 8),
1290 (2, 7), (1, 7), (2, 6), (1, 6), (2, 5), (1, 5),
1291 (2, 4), (1, 4), (2, 3), (1, 3), (2, 2), (1, 2),
1292 (2, 1), (1, 1), (2, 0), (1, 0),
1293 ]);
1294 }
1295
1296 #[test]
1297 fn test_micro_qr_2() {
1298 let res = DataModuleIter::new(Version::Micro(2)).collect::<Vec<(i16, i16)>>();
1299 assert_eq!(res, vec![
1300 (12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10),
1301 (12, 9), (11, 9), (12, 8), (11, 8), (12, 7), (11, 7),
1302 (12, 6), (11, 6), (12, 5), (11, 5), (12, 4), (11, 4),
1303 (12, 3), (11, 3), (12, 2), (11, 2), (12, 1), (11, 1),
1304 (12, 0), (11, 0),
1305 (10, 0), (9, 0), (10, 1), (9, 1), (10, 2), (9, 2),
1306 (10, 3), (9, 3), (10, 4), (9, 4), (10, 5), (9, 5),
1307 (10, 6), (9, 6), (10, 7), (9, 7), (10, 8), (9, 8),
1308 (10, 9), (9, 9), (10, 10), (9, 10), (10, 11), (9, 11),
1309 (10, 12), (9, 12),
1310 (8, 12), (7, 12), (8, 11), (7, 11), (8, 10), (7, 10),
1311 (8, 9), (7, 9), (8, 8), (7, 8), (8, 7), (7, 7),
1312 (8, 6), (7, 6), (8, 5), (7, 5), (8, 4), (7, 4),
1313 (8, 3), (7, 3), (8, 2), (7, 2), (8, 1), (7, 1),
1314 (8, 0), (7, 0),
1315 (6, 0), (5, 0), (6, 1), (5, 1), (6, 2), (5, 2),
1316 (6, 3), (5, 3), (6, 4), (5, 4), (6, 5), (5, 5),
1317 (6, 6), (5, 6), (6, 7), (5, 7), (6, 8), (5, 8),
1318 (6, 9), (5, 9), (6, 10), (5, 10), (6, 11), (5, 11),
1319 (6, 12), (5, 12),
1320 (4, 12), (3, 12), (4, 11), (3, 11), (4, 10), (3, 10),
1321 (4, 9), (3, 9), (4, 8), (3, 8), (4, 7), (3, 7),
1322 (4, 6), (3, 6), (4, 5), (3, 5), (4, 4), (3, 4),
1323 (4, 3), (3, 3), (4, 2), (3, 2), (4, 1), (3, 1),
1324 (4, 0), (3, 0),
1325 (2, 0), (1, 0), (2, 1), (1, 1), (2, 2), (1, 2),
1326 (2, 3), (1, 3), (2, 4), (1, 4), (2, 5), (1, 5),
1327 (2, 6), (1, 6), (2, 7), (1, 7), (2, 8), (1, 8),
1328 (2, 9), (1, 9), (2, 10), (1, 10), (2, 11), (1, 11),
1329 (2, 12), (1, 12),
1330 ]);
1331 }
1332}
1333
1334impl Canvas {
1339 fn draw_codewords<I>(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I)
1340 where
1341 I: Iterator<Item = (i16, i16)>,
1342 {
1343 let length = codewords.len();
1344 let last_word = if is_half_codeword_at_end { length - 1 } else { length };
1345 for (i, b) in codewords.iter().enumerate() {
1346 let bits_end = if i == last_word { 4 } else { 0 };
1347 'outside: for j in (bits_end..=7).rev() {
1348 let color = if (*b & (1 << j)) == 0 { Color::Light } else { Color::Dark };
1349 for (x, y) in coords.by_ref() {
1350 let r = self.get_mut(x, y);
1351 if *r == Module::Empty {
1352 *r = Module::Unmasked(color);
1353 continue 'outside;
1354 }
1355 }
1356 return;
1357 }
1358 }
1359 }
1360
1361 pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
1363 let is_half_codeword_at_end =
1364 matches!((self.version, self.ec_level), (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M));
1365
1366 let mut coords = DataModuleIter::new(self.version);
1367 self.draw_codewords(data, is_half_codeword_at_end, &mut coords);
1368 self.draw_codewords(ec, false, &mut coords);
1369 }
1370}
1371
1372#[cfg(test)]
1373mod draw_codewords_test {
1374 use crate::canvas::Canvas;
1375 use crate::types::{EcLevel, Version};
1376
1377 #[test]
1378 fn test_micro_qr_1() {
1379 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1380 c.draw_all_functional_patterns();
1381 c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
1382 assert_eq!(
1383 &*c.to_debug_str(),
1384 "\n\
1385 #######.#.#\n\
1386 #.....#..-*\n\
1387 #.###.#..**\n\
1388 #.###.#..*-\n\
1389 #.###.#..**\n\
1390 #.....#..*-\n\
1391 #######..*-\n\
1392 .........-*\n\
1393 #........**\n\
1394 .***-**---*\n\
1395 #---*-*-**-"
1396 );
1397 }
1398
1399 #[test]
1400 fn test_qr_2() {
1401 let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1402 c.draw_all_functional_patterns();
1403 c.draw_data(
1404 b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\
1405 \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$",
1406 b"",
1407 );
1408 assert_eq!(
1409 &*c.to_debug_str(),
1410 "\n\
1411 #######..--*---*-.#######\n\
1412 #.....#..-*-*-*-*.#.....#\n\
1413 #.###.#..*---*---.#.###.#\n\
1414 #.###.#..--*---*-.#.###.#\n\
1415 #.###.#..-*-*-*-*.#.###.#\n\
1416 #.....#..*---*---.#.....#\n\
1417 #######.#.#.#.#.#.#######\n\
1418 .........--*---*-........\n\
1419 ......#..-*-*-*-*........\n\
1420 --*-*-.-**---*---*--**--*\n\
1421 -*-*--#----*---*---------\n\
1422 *----*.*--*-*-*-*-**--**-\n\
1423 --*-*-#-**---*---*--**--*\n\
1424 -*-*--.----*---*---------\n\
1425 *----*#*--*-*-*-*-**--**-\n\
1426 --*-*-.-**---*---*--**--*\n\
1427 -*-*--#----*---*#####----\n\
1428 ........#-*-*-*-#...#-**-\n\
1429 #######..*---*--#.#.#*--*\n\
1430 #.....#..--*---*#...#----\n\
1431 #.###.#..-*-*-*-#####-**-\n\
1432 #.###.#..*---*--*----*--*\n\
1433 #.###.#..--*------**-----\n\
1434 #.....#..-*-*-**-*--*-**-\n\
1435 #######..*---*--*----*--*"
1436 );
1437 }
1438}
1439#[derive(Debug, Copy, Clone)]
1446pub enum MaskPattern {
1447 Checkerboard = 0b000,
1449
1450 HorizontalLines = 0b001,
1452
1453 VerticalLines = 0b010,
1455
1456 DiagonalLines = 0b011,
1458
1459 LargeCheckerboard = 0b100,
1461
1462 Fields = 0b101,
1464
1465 Diamonds = 0b110,
1467
1468 Meadow = 0b111,
1470}
1471
1472mod mask_functions {
1473 pub fn checkerboard(x: i16, y: i16) -> bool {
1474 (x + y) % 2 == 0
1475 }
1476
1477 pub fn horizontal_lines(_: i16, y: i16) -> bool {
1478 y % 2 == 0
1479 }
1480
1481 pub fn vertical_lines(x: i16, _: i16) -> bool {
1482 x % 3 == 0
1483 }
1484
1485 pub fn diagonal_lines(x: i16, y: i16) -> bool {
1486 (x + y) % 3 == 0
1487 }
1488
1489 pub fn large_checkerboard(x: i16, y: i16) -> bool {
1490 ((y / 2) + (x / 3)) % 2 == 0
1491 }
1492
1493 pub fn fields(x: i16, y: i16) -> bool {
1494 (x * y) % 2 + (x * y) % 3 == 0
1495 }
1496
1497 pub fn diamonds(x: i16, y: i16) -> bool {
1498 ((x * y) % 2 + (x * y) % 3) % 2 == 0
1499 }
1500
1501 pub fn meadow(x: i16, y: i16) -> bool {
1502 ((x + y) % 2 + (x * y) % 3) % 2 == 0
1503 }
1504}
1505
1506fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
1507 match pattern {
1508 MaskPattern::Checkerboard => mask_functions::checkerboard,
1509 MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
1510 MaskPattern::VerticalLines => mask_functions::vertical_lines,
1511 MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
1512 MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
1513 MaskPattern::Fields => mask_functions::fields,
1514 MaskPattern::Diamonds => mask_functions::diamonds,
1515 MaskPattern::Meadow => mask_functions::meadow,
1516 }
1517}
1518
1519impl Canvas {
1520 pub fn apply_mask(&mut self, pattern: MaskPattern) {
1523 let mask_fn = get_mask_function(pattern);
1524 for x in 0..self.width {
1525 for y in 0..self.width {
1526 let module = self.get_mut(x, y);
1527 *module = module.mask(mask_fn(x, y));
1528 }
1529 }
1530
1531 self.draw_format_info_patterns(pattern);
1532 }
1533
1534 fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
1540 let format_number = match self.version {
1541 Version::Normal(_) => {
1542 let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize);
1543 FORMAT_INFOS_QR[simple_format_number]
1544 }
1545 Version::Micro(a) => {
1546 let micro_pattern_number = match pattern {
1547 MaskPattern::HorizontalLines => 0b00,
1548 MaskPattern::LargeCheckerboard => 0b01,
1549 MaskPattern::Diamonds => 0b10,
1550 MaskPattern::Meadow => 0b11,
1551 _ => panic!("Unsupported mask pattern in Micro QR code"),
1552 };
1553 let symbol_number = match (a, self.ec_level) {
1554 (1, EcLevel::L) => 0b000,
1555 (2, EcLevel::L) => 0b001,
1556 (2, EcLevel::M) => 0b010,
1557 (3, EcLevel::L) => 0b011,
1558 (3, EcLevel::M) => 0b100,
1559 (4, EcLevel::L) => 0b101,
1560 (4, EcLevel::M) => 0b110,
1561 (4, EcLevel::Q) => 0b111,
1562 _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
1563 };
1564 let simple_format_number = symbol_number << 2 | micro_pattern_number;
1565 FORMAT_INFOS_MICRO_QR[simple_format_number]
1566 }
1567 };
1568 self.draw_format_info_patterns_with_number(format_number);
1569 }
1570}
1571
1572#[cfg(test)]
1573mod mask_tests {
1574 use crate::canvas::{Canvas, MaskPattern};
1575 use crate::types::{EcLevel, Version};
1576
1577 #[test]
1578 fn test_apply_mask_qr() {
1579 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1580 c.draw_all_functional_patterns();
1581 c.apply_mask(MaskPattern::Checkerboard);
1582
1583 assert_eq!(
1584 &*c.to_debug_str(),
1585 "\n\
1586 #######...#.#.#######\n\
1587 #.....#..#.#..#.....#\n\
1588 #.###.#.#.#.#.#.###.#\n\
1589 #.###.#..#.#..#.###.#\n\
1590 #.###.#...#.#.#.###.#\n\
1591 #.....#..#.#..#.....#\n\
1592 #######.#.#.#.#######\n\
1593 ........##.#.........\n\
1594 ###.#####.#.###...#..\n\
1595 .#.#.#.#.#.#.#.#.#.#.\n\
1596 #.#.#.#.#.#.#.#.#.#.#\n\
1597 .#.#.#.#.#.#.#.#.#.#.\n\
1598 #.#.#.#.#.#.#.#.#.#.#\n\
1599 ........##.#.#.#.#.#.\n\
1600 #######.#.#.#.#.#.#.#\n\
1601 #.....#.##.#.#.#.#.#.\n\
1602 #.###.#.#.#.#.#.#.#.#\n\
1603 #.###.#..#.#.#.#.#.#.\n\
1604 #.###.#.#.#.#.#.#.#.#\n\
1605 #.....#.##.#.#.#.#.#.\n\
1606 #######.#.#.#.#.#.#.#"
1607 );
1608 }
1609
1610 #[test]
1611 fn test_draw_format_info_patterns_qr() {
1612 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1613 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1614 assert_eq!(
1615 &*c.to_debug_str(),
1616 "\n\
1617 ????????#????????????\n\
1618 ????????#????????????\n\
1619 ????????#????????????\n\
1620 ????????#????????????\n\
1621 ????????.????????????\n\
1622 ????????#????????????\n\
1623 ?????????????????????\n\
1624 ????????.????????????\n\
1625 ##..##?..????..#.####\n\
1626 ?????????????????????\n\
1627 ?????????????????????\n\
1628 ?????????????????????\n\
1629 ?????????????????????\n\
1630 ????????#????????????\n\
1631 ????????.????????????\n\
1632 ????????#????????????\n\
1633 ????????#????????????\n\
1634 ????????.????????????\n\
1635 ????????.????????????\n\
1636 ????????#????????????\n\
1637 ????????#????????????"
1638 );
1639 }
1640
1641 #[test]
1642 fn test_draw_format_info_patterns_micro_qr() {
1643 let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
1644 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1645 assert_eq!(
1646 &*c.to_debug_str(),
1647 "\n\
1648 ?????????????\n\
1649 ????????#????\n\
1650 ????????.????\n\
1651 ????????.????\n\
1652 ????????#????\n\
1653 ????????#????\n\
1654 ????????.????\n\
1655 ????????.????\n\
1656 ?#.#....#????\n\
1657 ?????????????\n\
1658 ?????????????\n\
1659 ?????????????\n\
1660 ?????????????"
1661 );
1662 }
1663}
1664
1665static FORMAT_INFOS_QR: [u16; 32] = [
1666 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318,
1667 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06,
1668 0x24b4, 0x2183, 0x2eda, 0x2bed,
1669];
1670
1671static FORMAT_INFOS_MICRO_QR: [u16; 32] = [
1672 0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f,
1673 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51,
1674 0x34e3, 0x31d4, 0x3e8d, 0x3bba,
1675];
1676
1677impl Canvas {
1682 fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 {
1688 let mut total_score = 0;
1689
1690 for i in 0..self.width {
1691 let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) };
1692
1693 let colors = (0..self.width).map(map_fn).chain(Some(Module::Empty).into_iter());
1694 let mut last_color = Module::Empty;
1695 let mut consecutive_len = 1_u16;
1696
1697 for color in colors {
1698 if color == last_color {
1699 consecutive_len += 1;
1700 } else {
1701 last_color = color;
1702 if consecutive_len >= 5 {
1703 total_score += consecutive_len - 2;
1704 }
1705 consecutive_len = 1;
1706 }
1707 }
1708 }
1709
1710 total_score
1711 }
1712
1713 fn compute_block_penalty_score(&self) -> u16 {
1719 let mut total_score = 0;
1720
1721 for i in 0..self.width - 1 {
1722 for j in 0..self.width - 1 {
1723 let this = self.get(i, j);
1724 let right = self.get(i + 1, j);
1725 let bottom = self.get(i, j + 1);
1726 let bottom_right = self.get(i + 1, j + 1);
1727 if this == right && right == bottom && bottom == bottom_right {
1728 total_score += 3;
1729 }
1730 }
1731 }
1732
1733 total_score
1734 }
1735
1736 fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
1742 static PATTERN: [Color; 7] =
1743 [Color::Dark, Color::Light, Color::Dark, Color::Dark, Color::Dark, Color::Light, Color::Dark];
1744
1745 let mut total_score = 0;
1746
1747 for i in 0..self.width {
1748 for j in 0..self.width - 6 {
1749 let get: Box<dyn Fn(i16) -> Color> = if is_horizontal {
1751 Box::new(|k| self.get(k, i).into())
1752 } else {
1753 Box::new(|k| self.get(i, k).into())
1754 };
1755
1756 if (j..(j + 7)).map(&*get).ne(PATTERN.iter().copied()) {
1757 continue;
1758 }
1759
1760 let check = |k| 0 <= k && k < self.width && get(k) != Color::Light;
1761 if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) {
1762 total_score += 40;
1763 }
1764 }
1765 }
1766
1767 total_score - 360
1768 }
1769
1770 fn compute_balance_penalty_score(&self) -> u16 {
1779 let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count();
1780 let total_modules = self.modules.len();
1781 let ratio = dark_modules * 200 / total_modules;
1782 if ratio >= 100 { ratio - 100 } else { 100 - ratio }.as_u16()
1783 }
1784
1785 fn compute_light_side_penalty_score(&self) -> u16 {
1793 let h = (1..self.width).filter(|j| !self.get(*j, -1).is_dark()).count();
1794 let v = (1..self.width).filter(|j| !self.get(-1, *j).is_dark()).count();
1795
1796 (h + v + 15 * max(h, v)).as_u16()
1797 }
1798
1799 fn compute_total_penalty_scores(&self) -> u16 {
1802 match self.version {
1803 Version::Normal(_) => {
1804 let s1_a = self.compute_adjacent_penalty_score(true);
1805 let s1_b = self.compute_adjacent_penalty_score(false);
1806 let s2 = self.compute_block_penalty_score();
1807 let s3_a = self.compute_finder_penalty_score(true);
1808 let s3_b = self.compute_finder_penalty_score(false);
1809 let s4 = self.compute_balance_penalty_score();
1810 s1_a + s1_b + s2 + s3_a + s3_b + s4
1811 }
1812 Version::Micro(_) => self.compute_light_side_penalty_score(),
1813 }
1814 }
1815}
1816
1817#[cfg(test)]
1818mod penalty_tests {
1819 use crate::canvas::{Canvas, MaskPattern};
1820 use crate::cast::As;
1821 use crate::types::{Color, EcLevel, Version};
1822
1823 fn create_test_canvas() -> Canvas {
1824 let mut c = Canvas::new(Version::Normal(1), EcLevel::Q);
1825 c.draw_all_functional_patterns();
1826 c.draw_data(
1827 b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00",
1828 b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10",
1829 );
1830 c.apply_mask(MaskPattern::Checkerboard);
1831 c
1832 }
1833
1834 #[test]
1835 fn check_penalty_canvas() {
1836 let c = create_test_canvas();
1837 assert_eq!(
1838 &*c.to_debug_str(),
1839 "\n\
1840 #######.##....#######\n\
1841 #.....#.#..#..#.....#\n\
1842 #.###.#.#..##.#.###.#\n\
1843 #.###.#.#.....#.###.#\n\
1844 #.###.#.#.#...#.###.#\n\
1845 #.....#...#...#.....#\n\
1846 #######.#.#.#.#######\n\
1847 ........#............\n\
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 #######.....####....#"
1861 );
1862 }
1863
1864 #[test]
1865 fn test_penalty_score_adjacent() {
1866 let c = create_test_canvas();
1867 assert_eq!(c.compute_adjacent_penalty_score(true), 88);
1868 assert_eq!(c.compute_adjacent_penalty_score(false), 92);
1869 }
1870
1871 #[test]
1872 fn test_penalty_score_block() {
1873 let c = create_test_canvas();
1874 assert_eq!(c.compute_block_penalty_score(), 90);
1875 }
1876
1877 #[test]
1878 fn test_penalty_score_finder() {
1879 let c = create_test_canvas();
1880 assert_eq!(c.compute_finder_penalty_score(true), 0);
1881 assert_eq!(c.compute_finder_penalty_score(false), 40);
1882 }
1883
1884 #[test]
1885 fn test_penalty_score_balance() {
1886 let c = create_test_canvas();
1887 assert_eq!(c.compute_balance_penalty_score(), 2);
1888 }
1889
1890 #[test]
1891 fn test_penalty_score_light_sides() {
1892 static HORIZONTAL_SIDE: [Color; 17] = [
1893 Color::Dark,
1894 Color::Light,
1895 Color::Light,
1896 Color::Dark,
1897 Color::Dark,
1898 Color::Dark,
1899 Color::Light,
1900 Color::Light,
1901 Color::Dark,
1902 Color::Light,
1903 Color::Dark,
1904 Color::Light,
1905 Color::Light,
1906 Color::Dark,
1907 Color::Light,
1908 Color::Light,
1909 Color::Light,
1910 ];
1911 static VERTICAL_SIDE: [Color; 17] = [
1912 Color::Dark,
1913 Color::Dark,
1914 Color::Dark,
1915 Color::Light,
1916 Color::Light,
1917 Color::Dark,
1918 Color::Dark,
1919 Color::Light,
1920 Color::Dark,
1921 Color::Light,
1922 Color::Dark,
1923 Color::Light,
1924 Color::Dark,
1925 Color::Light,
1926 Color::Light,
1927 Color::Dark,
1928 Color::Light,
1929 ];
1930
1931 let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
1932 for i in 0_i16..17 {
1933 c.put(i, -1, HORIZONTAL_SIDE[i.as_usize()]);
1934 c.put(-1, i, VERTICAL_SIDE[i.as_usize()]);
1935 }
1936
1937 assert_eq!(c.compute_light_side_penalty_score(), 168);
1938 }
1939}
1940
1941static ALL_PATTERNS_QR: [MaskPattern; 8] = [
1946 MaskPattern::Checkerboard,
1947 MaskPattern::HorizontalLines,
1948 MaskPattern::VerticalLines,
1949 MaskPattern::DiagonalLines,
1950 MaskPattern::LargeCheckerboard,
1951 MaskPattern::Fields,
1952 MaskPattern::Diamonds,
1953 MaskPattern::Meadow,
1954];
1955
1956static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] =
1957 [MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, MaskPattern::Diamonds, MaskPattern::Meadow];
1958
1959impl Canvas {
1960 #[must_use]
1963 pub fn apply_best_mask(&self) -> Self {
1964 match self.version {
1965 Version::Normal(_) => ALL_PATTERNS_QR.iter(),
1966 Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
1967 }
1968 .map(|ptn| {
1969 let mut c = self.clone();
1970 c.apply_mask(*ptn);
1971 c
1972 })
1973 .min_by_key(Self::compute_total_penalty_scores)
1974 .expect("at least one pattern")
1975 }
1976
1977 #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")]
1979 pub fn to_bools(&self) -> Vec<bool> {
1980 self.modules.iter().map(|m| m.is_dark()).collect()
1981 }
1982
1983 pub fn into_colors(self) -> Vec<Color> {
1985 self.modules.into_iter().map(Color::from).collect()
1986 }
1987}
1988
1989