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(0b10101101, 8, Color::Dark, Color::Light, &[(0, 0), (0, -1), (-2, -2), (-2, 0)]);
698 assert_eq!(
699 &*c.to_debug_str(),
700 "\n\
701 #????????.?\n\
702 ???????????\n\
703 ???????????\n\
704 ???????????\n\
705 ???????????\n\
706 ???????????\n\
707 ???????????\n\
708 ???????????\n\
709 ???????????\n\
710 ?????????#?\n\
711 .??????????"
712 );
713 }
714
715 #[test]
716 fn test_draw_version_info_1() {
717 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
718 c.draw_version_info_patterns();
719 assert_eq!(
720 &*c.to_debug_str(),
721 "\n\
722 ?????????????????????\n\
723 ?????????????????????\n\
724 ?????????????????????\n\
725 ?????????????????????\n\
726 ?????????????????????\n\
727 ?????????????????????\n\
728 ?????????????????????\n\
729 ?????????????????????\n\
730 ?????????????????????\n\
731 ?????????????????????\n\
732 ?????????????????????\n\
733 ?????????????????????\n\
734 ?????????????????????\n\
735 ?????????????????????\n\
736 ?????????????????????\n\
737 ?????????????????????\n\
738 ?????????????????????\n\
739 ?????????????????????\n\
740 ?????????????????????\n\
741 ?????????????????????\n\
742 ?????????????????????"
743 );
744 }
745
746 #[test]
747 fn test_draw_version_info_7() {
748 let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
749 c.draw_version_info_patterns();
750
751 assert_eq!(
752 &*c.to_debug_str(),
753 "\n\
754 ??????????????????????????????????..#????????\n\
755 ??????????????????????????????????.#.????????\n\
756 ??????????????????????????????????.#.????????\n\
757 ??????????????????????????????????.##????????\n\
758 ??????????????????????????????????###????????\n\
759 ??????????????????????????????????...????????\n\
760 ?????????????????????????????????????????????\n\
761 ?????????????????????????????????????????????\n\
762 ?????????????????????????????????????????????\n\
763 ?????????????????????????????????????????????\n\
764 ?????????????????????????????????????????????\n\
765 ?????????????????????????????????????????????\n\
766 ?????????????????????????????????????????????\n\
767 ?????????????????????????????????????????????\n\
768 ?????????????????????????????????????????????\n\
769 ?????????????????????????????????????????????\n\
770 ?????????????????????????????????????????????\n\
771 ?????????????????????????????????????????????\n\
772 ?????????????????????????????????????????????\n\
773 ?????????????????????????????????????????????\n\
774 ?????????????????????????????????????????????\n\
775 ?????????????????????????????????????????????\n\
776 ?????????????????????????????????????????????\n\
777 ?????????????????????????????????????????????\n\
778 ?????????????????????????????????????????????\n\
779 ?????????????????????????????????????????????\n\
780 ?????????????????????????????????????????????\n\
781 ?????????????????????????????????????????????\n\
782 ?????????????????????????????????????????????\n\
783 ?????????????????????????????????????????????\n\
784 ?????????????????????????????????????????????\n\
785 ?????????????????????????????????????????????\n\
786 ?????????????????????????????????????????????\n\
787 ?????????????????????????????????????????????\n\
788 ....#.???????????????????????????????????????\n\
789 .####.???????????????????????????????????????\n\
790 #..##.???????????????????????????????????????\n\
791 ?????????????????????????????????????????????\n\
792 ?????????????????????????????????????????????\n\
793 ?????????????????????????????????????????????\n\
794 ?????????????????????????????????????????????\n\
795 ?????????????????????????????????????????????\n\
796 ?????????????????????????????????????????????\n\
797 ?????????????????????????????????????????????\n\
798 ?????????????????????????????????????????????"
799 );
800 }
801
802 #[test]
803 fn test_draw_reserved_format_info_patterns_qr() {
804 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
805 c.draw_reserved_format_info_patterns();
806 assert_eq!(
807 &*c.to_debug_str(),
808 "\n\
809 ????????.????????????\n\
810 ????????.????????????\n\
811 ????????.????????????\n\
812 ????????.????????????\n\
813 ????????.????????????\n\
814 ????????.????????????\n\
815 ?????????????????????\n\
816 ????????.????????????\n\
817 ......?..????........\n\
818 ?????????????????????\n\
819 ?????????????????????\n\
820 ?????????????????????\n\
821 ?????????????????????\n\
822 ????????#????????????\n\
823 ????????.????????????\n\
824 ????????.????????????\n\
825 ????????.????????????\n\
826 ????????.????????????\n\
827 ????????.????????????\n\
828 ????????.????????????\n\
829 ????????.????????????"
830 );
831 }
832
833 #[test]
834 fn test_draw_reserved_format_info_patterns_micro_qr() {
835 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
836 c.draw_reserved_format_info_patterns();
837 assert_eq!(
838 &*c.to_debug_str(),
839 "\n\
840 ???????????\n\
841 ????????.??\n\
842 ????????.??\n\
843 ????????.??\n\
844 ????????.??\n\
845 ????????.??\n\
846 ????????.??\n\
847 ????????.??\n\
848 ?........??\n\
849 ???????????\n\
850 ???????????"
851 );
852 }
853}
854
855static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [
856 (5, -9),
857 (5, -10),
858 (5, -11),
859 (4, -9),
860 (4, -10),
861 (4, -11),
862 (3, -9),
863 (3, -10),
864 (3, -11),
865 (2, -9),
866 (2, -10),
867 (2, -11),
868 (1, -9),
869 (1, -10),
870 (1, -11),
871 (0, -9),
872 (0, -10),
873 (0, -11),
874];
875
876static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [
877 (-9, 5),
878 (-10, 5),
879 (-11, 5),
880 (-9, 4),
881 (-10, 4),
882 (-11, 4),
883 (-9, 3),
884 (-10, 3),
885 (-11, 3),
886 (-9, 2),
887 (-10, 2),
888 (-11, 2),
889 (-9, 1),
890 (-10, 1),
891 (-11, 1),
892 (-9, 0),
893 (-10, 0),
894 (-11, 0),
895];
896
897static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [
898 (0, 8),
899 (1, 8),
900 (2, 8),
901 (3, 8),
902 (4, 8),
903 (5, 8),
904 (7, 8),
905 (8, 8),
906 (8, 7),
907 (8, 5),
908 (8, 4),
909 (8, 3),
910 (8, 2),
911 (8, 1),
912 (8, 0),
913];
914
915static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [
916 (8, -1),
917 (8, -2),
918 (8, -3),
919 (8, -4),
920 (8, -5),
921 (8, -6),
922 (8, -7),
923 (-8, 8),
924 (-7, 8),
925 (-6, 8),
926 (-5, 8),
927 (-4, 8),
928 (-3, 8),
929 (-2, 8),
930 (-1, 8),
931];
932
933static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [
934 (1, 8),
935 (2, 8),
936 (3, 8),
937 (4, 8),
938 (5, 8),
939 (6, 8),
940 (7, 8),
941 (8, 8),
942 (8, 7),
943 (8, 6),
944 (8, 5),
945 (8, 4),
946 (8, 3),
947 (8, 2),
948 (8, 1),
949];
950
951static VERSION_INFOS: [u32; 34] = [
952 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78, 0x1145d, 0x12a17,
953 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
954 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 0x27541, 0x28c69,
955];
956
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
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
1352impl Canvas {
1357 fn draw_codewords<I>(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I)
1358 where
1359 I: Iterator<Item = (i16, i16)>,
1360 {
1361 let length = codewords.len();
1362 let last_word = if is_half_codeword_at_end { length - 1 } else { length };
1363 for (i, b) in codewords.iter().enumerate() {
1364 let bits_end = if i == last_word { 4 } else { 0 };
1365 'outside: for j in (bits_end..=7).rev() {
1366 let color = if (*b & (1 << j)) == 0 { Color::Light } else { Color::Dark };
1367 for (x, y) in coords.by_ref() {
1368 let r = self.get_mut(x, y);
1369 if *r == Module::Empty {
1370 *r = Module::Unmasked(color);
1371 continue 'outside;
1372 }
1373 }
1374 return;
1375 }
1376 }
1377 }
1378
1379 pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
1381 let is_half_codeword_at_end =
1382 matches!((self.version, self.ec_level), (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M));
1383 let mut coords = DataModuleIter::new(self.version);
1384 self.draw_codewords(data, is_half_codeword_at_end, &mut coords);
1385 self.draw_codewords(ec, false, &mut coords);
1386 }
1387}
1388
1389#[cfg(test)]
1390mod draw_codewords_test {
1391 use crate::canvas::Canvas;
1392 use crate::types::{EcLevel, Version};
1393
1394 #[test]
1395 fn test_micro_qr_1() {
1396 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1397 c.draw_all_functional_patterns();
1398 c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
1399 assert_eq!(
1400 &*c.to_debug_str(),
1401 "\n\
1402 #######.#.#\n\
1403 #.....#..-*\n\
1404 #.###.#..**\n\
1405 #.###.#..*-\n\
1406 #.###.#..**\n\
1407 #.....#..*-\n\
1408 #######..*-\n\
1409 .........-*\n\
1410 #........**\n\
1411 .***-**---*\n\
1412 #---*-*-**-"
1413 );
1414 }
1415
1416 #[test]
1417 fn test_qr_2() {
1418 let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1419 c.draw_all_functional_patterns();
1420 c.draw_data(
1421 b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\
1422 \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$",
1423 b"",
1424 );
1425 assert_eq!(
1426 &*c.to_debug_str(),
1427 "\n\
1428 #######..--*---*-.#######\n\
1429 #.....#..-*-*-*-*.#.....#\n\
1430 #.###.#..*---*---.#.###.#\n\
1431 #.###.#..--*---*-.#.###.#\n\
1432 #.###.#..-*-*-*-*.#.###.#\n\
1433 #.....#..*---*---.#.....#\n\
1434 #######.#.#.#.#.#.#######\n\
1435 .........--*---*-........\n\
1436 ......#..-*-*-*-*........\n\
1437 --*-*-.-**---*---*--**--*\n\
1438 -*-*--#----*---*---------\n\
1439 *----*.*--*-*-*-*-**--**-\n\
1440 --*-*-#-**---*---*--**--*\n\
1441 -*-*--.----*---*---------\n\
1442 *----*#*--*-*-*-*-**--**-\n\
1443 --*-*-.-**---*---*--**--*\n\
1444 -*-*--#----*---*#####----\n\
1445 ........#-*-*-*-#...#-**-\n\
1446 #######..*---*--#.#.#*--*\n\
1447 #.....#..--*---*#...#----\n\
1448 #.###.#..-*-*-*-#####-**-\n\
1449 #.###.#..*---*--*----*--*\n\
1450 #.###.#..--*------**-----\n\
1451 #.....#..-*-*-**-*--*-**-\n\
1452 #######..*---*--*----*--*"
1453 );
1454 }
1455}
1456#[derive(Debug, Copy, Clone)]
1463pub enum MaskPattern {
1464 Checkerboard = 0b000,
1466
1467 HorizontalLines = 0b001,
1469
1470 VerticalLines = 0b010,
1472
1473 DiagonalLines = 0b011,
1475
1476 LargeCheckerboard = 0b100,
1478
1479 Fields = 0b101,
1481
1482 Diamonds = 0b110,
1484
1485 Meadow = 0b111,
1487}
1488
1489mod mask_functions {
1490 pub fn checkerboard(x: i16, y: i16) -> bool {
1491 (x + y) % 2 == 0
1492 }
1493 pub fn horizontal_lines(_: i16, y: i16) -> bool {
1494 y % 2 == 0
1495 }
1496 pub fn vertical_lines(x: i16, _: i16) -> bool {
1497 x % 3 == 0
1498 }
1499 pub fn diagonal_lines(x: i16, y: i16) -> bool {
1500 (x + y) % 3 == 0
1501 }
1502 pub fn large_checkerboard(x: i16, y: i16) -> bool {
1503 ((y / 2) + (x / 3)) % 2 == 0
1504 }
1505 pub fn fields(x: i16, y: i16) -> bool {
1506 (x * y) % 2 + (x * y) % 3 == 0
1507 }
1508 pub fn diamonds(x: i16, y: i16) -> bool {
1509 ((x * y) % 2 + (x * y) % 3) % 2 == 0
1510 }
1511 pub fn meadow(x: i16, y: i16) -> bool {
1512 ((x + y) % 2 + (x * y) % 3) % 2 == 0
1513 }
1514}
1515
1516fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
1517 match pattern {
1518 MaskPattern::Checkerboard => mask_functions::checkerboard,
1519 MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
1520 MaskPattern::VerticalLines => mask_functions::vertical_lines,
1521 MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
1522 MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
1523 MaskPattern::Fields => mask_functions::fields,
1524 MaskPattern::Diamonds => mask_functions::diamonds,
1525 MaskPattern::Meadow => mask_functions::meadow,
1526 }
1527}
1528
1529impl Canvas {
1530 pub fn apply_mask(&mut self, pattern: MaskPattern) {
1533 let mask_fn = get_mask_function(pattern);
1534 for x in 0..self.width {
1535 for y in 0..self.width {
1536 let module = self.get_mut(x, y);
1537 *module = module.mask(mask_fn(x, y));
1538 }
1539 }
1540
1541 self.draw_format_info_patterns(pattern);
1542 }
1543
1544 fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
1550 let format_number = match self.version {
1551 Version::Normal(_) => {
1552 let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize);
1553 FORMAT_INFOS_QR[simple_format_number]
1554 }
1555 Version::Micro(a) => {
1556 let micro_pattern_number = match pattern {
1557 MaskPattern::HorizontalLines => 0b00,
1558 MaskPattern::LargeCheckerboard => 0b01,
1559 MaskPattern::Diamonds => 0b10,
1560 MaskPattern::Meadow => 0b11,
1561 _ => panic!("Unsupported mask pattern in Micro QR code"),
1562 };
1563 let symbol_number = match (a, self.ec_level) {
1564 (1, EcLevel::L) => 0b000,
1565 (2, EcLevel::L) => 0b001,
1566 (2, EcLevel::M) => 0b010,
1567 (3, EcLevel::L) => 0b011,
1568 (3, EcLevel::M) => 0b100,
1569 (4, EcLevel::L) => 0b101,
1570 (4, EcLevel::M) => 0b110,
1571 (4, EcLevel::Q) => 0b111,
1572 _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
1573 };
1574 let simple_format_number = symbol_number << 2 | micro_pattern_number;
1575 FORMAT_INFOS_MICRO_QR[simple_format_number]
1576 }
1577 };
1578 self.draw_format_info_patterns_with_number(format_number);
1579 }
1580}
1581
1582#[cfg(test)]
1583mod mask_tests {
1584 use crate::canvas::{Canvas, MaskPattern};
1585 use crate::types::{EcLevel, Version};
1586
1587 #[test]
1588 fn test_apply_mask_qr() {
1589 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1590 c.draw_all_functional_patterns();
1591 c.apply_mask(MaskPattern::Checkerboard);
1592
1593 assert_eq!(
1594 &*c.to_debug_str(),
1595 "\n\
1596 #######...#.#.#######\n\
1597 #.....#..#.#..#.....#\n\
1598 #.###.#.#.#.#.#.###.#\n\
1599 #.###.#..#.#..#.###.#\n\
1600 #.###.#...#.#.#.###.#\n\
1601 #.....#..#.#..#.....#\n\
1602 #######.#.#.#.#######\n\
1603 ........##.#.........\n\
1604 ###.#####.#.###...#..\n\
1605 .#.#.#.#.#.#.#.#.#.#.\n\
1606 #.#.#.#.#.#.#.#.#.#.#\n\
1607 .#.#.#.#.#.#.#.#.#.#.\n\
1608 #.#.#.#.#.#.#.#.#.#.#\n\
1609 ........##.#.#.#.#.#.\n\
1610 #######.#.#.#.#.#.#.#\n\
1611 #.....#.##.#.#.#.#.#.\n\
1612 #.###.#.#.#.#.#.#.#.#\n\
1613 #.###.#..#.#.#.#.#.#.\n\
1614 #.###.#.#.#.#.#.#.#.#\n\
1615 #.....#.##.#.#.#.#.#.\n\
1616 #######.#.#.#.#.#.#.#"
1617 );
1618 }
1619
1620 #[test]
1621 fn test_draw_format_info_patterns_qr() {
1622 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1623 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1624 assert_eq!(
1625 &*c.to_debug_str(),
1626 "\n\
1627 ????????#????????????\n\
1628 ????????#????????????\n\
1629 ????????#????????????\n\
1630 ????????#????????????\n\
1631 ????????.????????????\n\
1632 ????????#????????????\n\
1633 ?????????????????????\n\
1634 ????????.????????????\n\
1635 ##..##?..????..#.####\n\
1636 ?????????????????????\n\
1637 ?????????????????????\n\
1638 ?????????????????????\n\
1639 ?????????????????????\n\
1640 ????????#????????????\n\
1641 ????????.????????????\n\
1642 ????????#????????????\n\
1643 ????????#????????????\n\
1644 ????????.????????????\n\
1645 ????????.????????????\n\
1646 ????????#????????????\n\
1647 ????????#????????????"
1648 );
1649 }
1650
1651 #[test]
1652 fn test_draw_format_info_patterns_micro_qr() {
1653 let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
1654 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1655 assert_eq!(
1656 &*c.to_debug_str(),
1657 "\n\
1658 ?????????????\n\
1659 ????????#????\n\
1660 ????????.????\n\
1661 ????????.????\n\
1662 ????????#????\n\
1663 ????????#????\n\
1664 ????????.????\n\
1665 ????????.????\n\
1666 ?#.#....#????\n\
1667 ?????????????\n\
1668 ?????????????\n\
1669 ?????????????\n\
1670 ?????????????"
1671 );
1672 }
1673}
1674
1675static FORMAT_INFOS_QR: [u16; 32] = [
1676 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318,
1677 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06,
1678 0x24b4, 0x2183, 0x2eda, 0x2bed,
1679];
1680
1681static FORMAT_INFOS_MICRO_QR: [u16; 32] = [
1682 0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f,
1683 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51,
1684 0x34e3, 0x31d4, 0x3e8d, 0x3bba,
1685];
1686
1687impl Canvas {
1692 fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 {
1698 let mut total_score = 0;
1699
1700 for i in 0..self.width {
1701 let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) };
1702
1703 let colors = (0..self.width).map(map_fn).chain(Some(Module::Empty).into_iter());
1704 let mut last_color = Module::Empty;
1705 let mut consecutive_len = 1_u16;
1706
1707 for color in colors {
1708 if color == last_color {
1709 consecutive_len += 1;
1710 } else {
1711 last_color = color;
1712 if consecutive_len >= 5 {
1713 total_score += consecutive_len - 2;
1714 }
1715 consecutive_len = 1;
1716 }
1717 }
1718 }
1719
1720 total_score
1721 }
1722
1723 fn compute_block_penalty_score(&self) -> u16 {
1729 let mut total_score = 0;
1730
1731 for i in 0..self.width - 1 {
1732 for j in 0..self.width - 1 {
1733 let this = self.get(i, j);
1734 let right = self.get(i + 1, j);
1735 let bottom = self.get(i, j + 1);
1736 let bottom_right = self.get(i + 1, j + 1);
1737 if this == right && right == bottom && bottom == bottom_right {
1738 total_score += 3;
1739 }
1740 }
1741 }
1742
1743 total_score
1744 }
1745
1746 fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
1752 static PATTERN: [Color; 7] =
1753 [Color::Dark, Color::Light, Color::Dark, Color::Dark, Color::Dark, Color::Light, Color::Dark];
1754
1755 let mut total_score = 0;
1756
1757 for i in 0..self.width {
1758 for j in 0..self.width - 6 {
1759 let get: Box<dyn Fn(i16) -> Color> = if is_horizontal {
1761 Box::new(|k| self.get(k, i).into())
1762 } else {
1763 Box::new(|k| self.get(i, k).into())
1764 };
1765
1766 if (j..(j + 7)).map(&*get).ne(PATTERN.iter().copied()) {
1767 continue;
1768 }
1769
1770 let check = |k| 0 <= k && k < self.width && get(k) != Color::Light;
1771 if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) {
1772 total_score += 40;
1773 }
1774 }
1775 }
1776
1777 total_score - 360
1778 }
1779
1780 fn compute_balance_penalty_score(&self) -> u16 {
1789 let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count();
1790 let total_modules = self.modules.len();
1791 let ratio = dark_modules * 200 / total_modules;
1792 if ratio >= 100 { ratio - 100 } else { 100 - ratio }.as_u16()
1793 }
1794
1795 fn compute_light_side_penalty_score(&self) -> u16 {
1803 let h = (1..self.width).filter(|j| !self.get(*j, -1).is_dark()).count();
1804 let v = (1..self.width).filter(|j| !self.get(-1, *j).is_dark()).count();
1805
1806 (h + v + 15 * max(h, v)).as_u16()
1807 }
1808
1809 fn compute_total_penalty_scores(&self) -> u16 {
1812 match self.version {
1813 Version::Normal(_) => {
1814 let s1_a = self.compute_adjacent_penalty_score(true);
1815 let s1_b = self.compute_adjacent_penalty_score(false);
1816 let s2 = self.compute_block_penalty_score();
1817 let s3_a = self.compute_finder_penalty_score(true);
1818 let s3_b = self.compute_finder_penalty_score(false);
1819 let s4 = self.compute_balance_penalty_score();
1820 s1_a + s1_b + s2 + s3_a + s3_b + s4
1821 }
1822 Version::Micro(_) => self.compute_light_side_penalty_score(),
1823 }
1824 }
1825}
1826
1827#[cfg(test)]
1828mod penalty_tests {
1829 use crate::canvas::{Canvas, MaskPattern};
1830 use crate::types::{Color, EcLevel, Version};
1831
1832 fn create_test_canvas() -> Canvas {
1833 let mut c = Canvas::new(Version::Normal(1), EcLevel::Q);
1834 c.draw_all_functional_patterns();
1835 c.draw_data(
1836 b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00",
1837 b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10",
1838 );
1839 c.apply_mask(MaskPattern::Checkerboard);
1840 c
1841 }
1842
1843 #[test]
1844 fn check_penalty_canvas() {
1845 let c = create_test_canvas();
1846 assert_eq!(
1847 &*c.to_debug_str(),
1848 "\n\
1849 #######.##....#######\n\
1850 #.....#.#..#..#.....#\n\
1851 #.###.#.#..##.#.###.#\n\
1852 #.###.#.#.....#.###.#\n\
1853 #.###.#.#.#...#.###.#\n\
1854 #.....#...#...#.....#\n\
1855 #######.#.#.#.#######\n\
1856 ........#............\n\
1857 .##.#.##....#.#.#####\n\
1858 .#......####....#...#\n\
1859 ..##.###.##...#.##...\n\
1860 .##.##.#..##.#.#.###.\n\
1861 #...#.#.#.###.###.#.#\n\
1862 ........##.#..#...#.#\n\
1863 #######.#.#....#.##..\n\
1864 #.....#..#.##.##.#...\n\
1865 #.###.#.#.#...#######\n\
1866 #.###.#..#.#.#.#...#.\n\
1867 #.###.#.#...####.#..#\n\
1868 #.....#.#.##.#...#.##\n\
1869 #######.....####....#"
1870 );
1871 }
1872
1873 #[test]
1874 fn test_penalty_score_adjacent() {
1875 let c = create_test_canvas();
1876 assert_eq!(c.compute_adjacent_penalty_score(true), 88);
1877 assert_eq!(c.compute_adjacent_penalty_score(false), 92);
1878 }
1879
1880 #[test]
1881 fn test_penalty_score_block() {
1882 let c = create_test_canvas();
1883 assert_eq!(c.compute_block_penalty_score(), 90);
1884 }
1885
1886 #[test]
1887 fn test_penalty_score_finder() {
1888 let c = create_test_canvas();
1889 assert_eq!(c.compute_finder_penalty_score(true), 0);
1890 assert_eq!(c.compute_finder_penalty_score(false), 40);
1891 }
1892
1893 #[test]
1894 fn test_penalty_score_balance() {
1895 let c = create_test_canvas();
1896 assert_eq!(c.compute_balance_penalty_score(), 2);
1897 }
1898
1899 #[test]
1900 fn test_penalty_score_light_sides() {
1901 static HORIZONTAL_SIDE: [Color; 17] = [
1902 Color::Dark,
1903 Color::Light,
1904 Color::Light,
1905 Color::Dark,
1906 Color::Dark,
1907 Color::Dark,
1908 Color::Light,
1909 Color::Light,
1910 Color::Dark,
1911 Color::Light,
1912 Color::Dark,
1913 Color::Light,
1914 Color::Light,
1915 Color::Dark,
1916 Color::Light,
1917 Color::Light,
1918 Color::Light,
1919 ];
1920 static VERTICAL_SIDE: [Color; 17] = [
1921 Color::Dark,
1922 Color::Dark,
1923 Color::Dark,
1924 Color::Light,
1925 Color::Light,
1926 Color::Dark,
1927 Color::Dark,
1928 Color::Light,
1929 Color::Dark,
1930 Color::Light,
1931 Color::Dark,
1932 Color::Light,
1933 Color::Dark,
1934 Color::Light,
1935 Color::Light,
1936 Color::Dark,
1937 Color::Light,
1938 ];
1939
1940 let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
1941 for i in 0_i16..17 {
1942 c.put(i, -1, HORIZONTAL_SIDE[i as usize]);
1943 c.put(-1, i, VERTICAL_SIDE[i as usize]);
1944 }
1945
1946 assert_eq!(c.compute_light_side_penalty_score(), 168);
1947 }
1948}
1949
1950static ALL_PATTERNS_QR: [MaskPattern; 8] = [
1955 MaskPattern::Checkerboard,
1956 MaskPattern::HorizontalLines,
1957 MaskPattern::VerticalLines,
1958 MaskPattern::DiagonalLines,
1959 MaskPattern::LargeCheckerboard,
1960 MaskPattern::Fields,
1961 MaskPattern::Diamonds,
1962 MaskPattern::Meadow,
1963];
1964
1965static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] =
1966 [MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, MaskPattern::Diamonds, MaskPattern::Meadow];
1967
1968impl Canvas {
1969 #[allow(clippy::missing_panics_doc)] #[must_use]
1973 pub fn apply_best_mask(&self) -> Self {
1974 match self.version {
1975 Version::Normal(_) => ALL_PATTERNS_QR.iter(),
1976 Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
1977 }
1978 .map(|ptn| {
1979 let mut c = self.clone();
1980 c.apply_mask(*ptn);
1981 c
1982 })
1983 .min_by_key(Self::compute_total_penalty_scores)
1984 .expect("at least one pattern")
1985 }
1986
1987 #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")]
1989 pub fn to_bools(&self) -> Vec<bool> {
1990 self.modules.iter().map(|m| m.is_dark()).collect()
1991 }
1992
1993 pub fn into_colors(self) -> Vec<Color> {
1995 self.modules.into_iter().map(Color::from).collect()
1996 }
1997}
1998
1999