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 pub fn mask(self, should_invert: bool) -> Self {
61 match (self, should_invert) {
62 (Module::Empty, true) => Module::Masked(Color::Dark),
63 (Module::Empty, false) => Module::Masked(Color::Light),
64 (Module::Unmasked(c), true) => Module::Masked(!c),
65 (Module::Unmasked(c), false) | (Module::Masked(c), _) => Module::Masked(c),
66 }
67 }
68}
69
70#[derive(Clone)]
77pub struct Canvas {
78 width: i16,
80
81 version: Version,
83
84 ec_level: EcLevel,
86
87 modules: Vec<Module>,
90}
91
92impl Canvas {
93 pub fn new(version: Version, ec_level: EcLevel) -> Self {
95 let width = version.width();
96 Self { width, version, ec_level, modules: vec![Module::Empty; (width * width).as_usize()] }
97 }
98
99 #[cfg(test)]
101 fn to_debug_str(&self) -> String {
102 let width = self.width;
103 let mut res = String::with_capacity((width * (width + 1)) as usize);
104 for y in 0..width {
105 res.push('\n');
106 for x in 0..width {
107 res.push(match self.get(x, y) {
108 Module::Empty => '?',
109 Module::Masked(Color::Light) => '.',
110 Module::Masked(Color::Dark) => '#',
111 Module::Unmasked(Color::Light) => '-',
112 Module::Unmasked(Color::Dark) => '*',
113 });
114 }
115 }
116 res
117 }
118
119 fn coords_to_index(&self, x: i16, y: i16) -> usize {
120 let x = if x < 0 { x + self.width } else { x }.as_usize();
121 let y = if y < 0 { y + self.width } else { y }.as_usize();
122 y * self.width.as_usize() + x
123 }
124
125 pub fn get(&self, x: i16, y: i16) -> Module {
128 self.modules[self.coords_to_index(x, y)]
129 }
130
131 pub fn get_mut(&mut self, x: i16, y: i16) -> &mut Module {
134 let index = self.coords_to_index(x, y);
135 &mut self.modules[index]
136 }
137
138 pub fn put(&mut self, x: i16, y: i16, color: Color) {
141 *self.get_mut(x, y) = Module::Masked(color);
142 }
143}
144
145#[cfg(test)]
146mod basic_canvas_tests {
147 use crate::canvas::{Canvas, Module};
148 use crate::types::{Color, EcLevel, Version};
149
150 #[test]
151 fn test_index() {
152 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
153
154 assert_eq!(c.get(0, 4), Module::Empty);
155 assert_eq!(c.get(-1, -7), Module::Empty);
156 assert_eq!(c.get(21 - 1, 21 - 7), Module::Empty);
157
158 c.put(0, 0, Color::Dark);
159 c.put(-1, -7, Color::Light);
160 assert_eq!(c.get(0, 0), Module::Masked(Color::Dark));
161 assert_eq!(c.get(21 - 1, -7), Module::Masked(Color::Light));
162 assert_eq!(c.get(-1, 21 - 7), Module::Masked(Color::Light));
163 }
164
165 #[test]
166 fn test_debug_str() {
167 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
168
169 for i in 3_i16..20 {
170 for j in 3_i16..20 {
171 *c.get_mut(i, j) = match ((i * 3) ^ j) % 5 {
172 0 => Module::Empty,
173 1 => Module::Masked(Color::Light),
174 2 => Module::Masked(Color::Dark),
175 3 => Module::Unmasked(Color::Light),
176 4 => Module::Unmasked(Color::Dark),
177 _ => unreachable!(),
178 };
179 }
180 }
181
182 assert_eq!(
183 &*c.to_debug_str(),
184 "\n\
185 ?????????????????????\n\
186 ?????????????????????\n\
187 ?????????????????????\n\
188 ?????####****....---?\n\
189 ???--.##-..##?..#??.?\n\
190 ???#*?-.*?#.-*#?-*.??\n\
191 ?????*?*?****-*-*---?\n\
192 ???*.-.-.-?-?#?#?#*#?\n\
193 ???.*#.*.*#.*#*#.*#*?\n\
194 ?????.#-#--??.?.#---?\n\
195 ???-.?*.-#?-.?#*-#?.?\n\
196 ???##*??*..##*--*..??\n\
197 ?????-???--??---?---?\n\
198 ???*.#.*.#**.#*#.#*#?\n\
199 ???##.-##..##..?#..??\n\
200 ???.-?*.-?#.-?#*-?#*?\n\
201 ????-.#?-.**#?-.#?-.?\n\
202 ???**?-**??--**?-**??\n\
203 ???#?*?#?*#.*-.-*-.-?\n\
204 ???..-...--??###?###?\n\
205 ?????????????????????"
206 );
207 }
208}
209
210impl Canvas {
215 fn draw_finder_pattern_at(&mut self, x: i16, y: i16) {
217 let (dx_left, dx_right) = if x >= 0 { (-3, 4) } else { (-4, 3) };
218 let (dy_top, dy_bottom) = if y >= 0 { (-3, 4) } else { (-4, 3) };
219 for j in dy_top..=dy_bottom {
220 for i in dx_left..=dx_right {
221 self.put(
222 x + i,
223 y + j,
224 #[allow(clippy::match_same_arms)]
225 match (i, j) {
226 (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light,
227 (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark,
228 (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light,
229 _ => Color::Dark,
230 },
231 );
232 }
233 }
234 }
235
236 fn draw_finder_patterns(&mut self) {
242 self.draw_finder_pattern_at(3, 3);
243
244 match self.version {
245 Version::Micro(_) => {}
246 Version::Normal(_) => {
247 self.draw_finder_pattern_at(-4, 3);
248 self.draw_finder_pattern_at(3, -4);
249 }
250 }
251 }
252}
253
254#[cfg(test)]
255mod finder_pattern_tests {
256 use crate::canvas::Canvas;
257 use crate::types::{EcLevel, Version};
258
259 #[test]
260 fn test_qr() {
261 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
262 c.draw_finder_patterns();
263 assert_eq!(
264 &*c.to_debug_str(),
265 "\n\
266 #######.?????.#######\n\
267 #.....#.?????.#.....#\n\
268 #.###.#.?????.#.###.#\n\
269 #.###.#.?????.#.###.#\n\
270 #.###.#.?????.#.###.#\n\
271 #.....#.?????.#.....#\n\
272 #######.?????.#######\n\
273 ........?????........\n\
274 ?????????????????????\n\
275 ?????????????????????\n\
276 ?????????????????????\n\
277 ?????????????????????\n\
278 ?????????????????????\n\
279 ........?????????????\n\
280 #######.?????????????\n\
281 #.....#.?????????????\n\
282 #.###.#.?????????????\n\
283 #.###.#.?????????????\n\
284 #.###.#.?????????????\n\
285 #.....#.?????????????\n\
286 #######.?????????????"
287 );
288 }
289
290 #[test]
291 fn test_micro_qr() {
292 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
293 c.draw_finder_patterns();
294 assert_eq!(
295 &*c.to_debug_str(),
296 "\n\
297 #######.???\n\
298 #.....#.???\n\
299 #.###.#.???\n\
300 #.###.#.???\n\
301 #.###.#.???\n\
302 #.....#.???\n\
303 #######.???\n\
304 ........???\n\
305 ???????????\n\
306 ???????????\n\
307 ???????????"
308 );
309 }
310}
311
312impl Canvas {
317 fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) {
319 if self.get(x, y) != Module::Empty {
320 return;
321 }
322 for j in -2..=2 {
323 for i in -2..=2 {
324 self.put(
325 x + i,
326 y + j,
327 match (i, j) {
328 (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark,
329 _ => Color::Light,
330 },
331 );
332 }
333 }
334 }
335
336 fn draw_alignment_patterns(&mut self) {
341 match self.version {
342 Version::Micro(_) | Version::Normal(1) => {}
343 Version::Normal(2..=6) => self.draw_alignment_pattern_at(-7, -7),
344 Version::Normal(a) => {
345 let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
346 for x in positions.iter() {
347 for y in positions.iter() {
348 self.draw_alignment_pattern_at(*x, *y);
349 }
350 }
351 }
352 }
353 }
354}
355
356#[cfg(test)]
357mod alignment_pattern_tests {
358 use crate::canvas::Canvas;
359 use crate::types::{EcLevel, Version};
360
361 #[test]
362 fn test_draw_alignment_patterns_1() {
363 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
364 c.draw_finder_patterns();
365 c.draw_alignment_patterns();
366 assert_eq!(
367 &*c.to_debug_str(),
368 "\n\
369 #######.?????.#######\n\
370 #.....#.?????.#.....#\n\
371 #.###.#.?????.#.###.#\n\
372 #.###.#.?????.#.###.#\n\
373 #.###.#.?????.#.###.#\n\
374 #.....#.?????.#.....#\n\
375 #######.?????.#######\n\
376 ........?????........\n\
377 ?????????????????????\n\
378 ?????????????????????\n\
379 ?????????????????????\n\
380 ?????????????????????\n\
381 ?????????????????????\n\
382 ........?????????????\n\
383 #######.?????????????\n\
384 #.....#.?????????????\n\
385 #.###.#.?????????????\n\
386 #.###.#.?????????????\n\
387 #.###.#.?????????????\n\
388 #.....#.?????????????\n\
389 #######.?????????????"
390 );
391 }
392
393 #[test]
394 fn test_draw_alignment_patterns_3() {
395 let mut c = Canvas::new(Version::Normal(3), EcLevel::L);
396 c.draw_finder_patterns();
397 c.draw_alignment_patterns();
398 assert_eq!(
399 &*c.to_debug_str(),
400 "\n\
401 #######.?????????????.#######\n\
402 #.....#.?????????????.#.....#\n\
403 #.###.#.?????????????.#.###.#\n\
404 #.###.#.?????????????.#.###.#\n\
405 #.###.#.?????????????.#.###.#\n\
406 #.....#.?????????????.#.....#\n\
407 #######.?????????????.#######\n\
408 ........?????????????........\n\
409 ?????????????????????????????\n\
410 ?????????????????????????????\n\
411 ?????????????????????????????\n\
412 ?????????????????????????????\n\
413 ?????????????????????????????\n\
414 ?????????????????????????????\n\
415 ?????????????????????????????\n\
416 ?????????????????????????????\n\
417 ?????????????????????????????\n\
418 ?????????????????????????????\n\
419 ?????????????????????????????\n\
420 ?????????????????????????????\n\
421 ????????????????????#####????\n\
422 ........????????????#...#????\n\
423 #######.????????????#.#.#????\n\
424 #.....#.????????????#...#????\n\
425 #.###.#.????????????#####????\n\
426 #.###.#.?????????????????????\n\
427 #.###.#.?????????????????????\n\
428 #.....#.?????????????????????\n\
429 #######.?????????????????????"
430 );
431 }
432
433 #[test]
434 fn test_draw_alignment_patterns_7() {
435 let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
436 c.draw_finder_patterns();
437 c.draw_alignment_patterns();
438 assert_eq!(
439 &*c.to_debug_str(),
440 "\n\
441 #######.?????????????????????????????.#######\n\
442 #.....#.?????????????????????????????.#.....#\n\
443 #.###.#.?????????????????????????????.#.###.#\n\
444 #.###.#.?????????????????????????????.#.###.#\n\
445 #.###.#.????????????#####????????????.#.###.#\n\
446 #.....#.????????????#...#????????????.#.....#\n\
447 #######.????????????#.#.#????????????.#######\n\
448 ........????????????#...#????????????........\n\
449 ????????????????????#####????????????????????\n\
450 ?????????????????????????????????????????????\n\
451 ?????????????????????????????????????????????\n\
452 ?????????????????????????????????????????????\n\
453 ?????????????????????????????????????????????\n\
454 ?????????????????????????????????????????????\n\
455 ?????????????????????????????????????????????\n\
456 ?????????????????????????????????????????????\n\
457 ?????????????????????????????????????????????\n\
458 ?????????????????????????????????????????????\n\
459 ?????????????????????????????????????????????\n\
460 ?????????????????????????????????????????????\n\
461 ????#####???????????#####???????????#####????\n\
462 ????#...#???????????#...#???????????#...#????\n\
463 ????#.#.#???????????#.#.#???????????#.#.#????\n\
464 ????#...#???????????#...#???????????#...#????\n\
465 ????#####???????????#####???????????#####????\n\
466 ?????????????????????????????????????????????\n\
467 ?????????????????????????????????????????????\n\
468 ?????????????????????????????????????????????\n\
469 ?????????????????????????????????????????????\n\
470 ?????????????????????????????????????????????\n\
471 ?????????????????????????????????????????????\n\
472 ?????????????????????????????????????????????\n\
473 ?????????????????????????????????????????????\n\
474 ?????????????????????????????????????????????\n\
475 ?????????????????????????????????????????????\n\
476 ?????????????????????????????????????????????\n\
477 ????????????????????#####???????????#####????\n\
478 ........????????????#...#???????????#...#????\n\
479 #######.????????????#.#.#???????????#.#.#????\n\
480 #.....#.????????????#...#???????????#...#????\n\
481 #.###.#.????????????#####???????????#####????\n\
482 #.###.#.?????????????????????????????????????\n\
483 #.###.#.?????????????????????????????????????\n\
484 #.....#.?????????????????????????????????????\n\
485 #######.?????????????????????????????????????"
486 );
487 }
488}
489
490static ALIGNMENT_PATTERN_POSITIONS: [&[i16]; 34] = [
494 &[6, 22, 38],
495 &[6, 24, 42],
496 &[6, 26, 46],
497 &[6, 28, 50],
498 &[6, 30, 54],
499 &[6, 32, 58],
500 &[6, 34, 62],
501 &[6, 26, 46, 66],
502 &[6, 26, 48, 70],
503 &[6, 26, 50, 74],
504 &[6, 30, 54, 78],
505 &[6, 30, 56, 82],
506 &[6, 30, 58, 86],
507 &[6, 34, 62, 90],
508 &[6, 28, 50, 72, 94],
509 &[6, 26, 50, 74, 98],
510 &[6, 30, 54, 78, 102],
511 &[6, 28, 54, 80, 106],
512 &[6, 32, 58, 84, 110],
513 &[6, 30, 58, 86, 114],
514 &[6, 34, 62, 90, 118],
515 &[6, 26, 50, 74, 98, 122],
516 &[6, 30, 54, 78, 102, 126],
517 &[6, 26, 52, 78, 104, 130],
518 &[6, 30, 56, 82, 108, 134],
519 &[6, 34, 60, 86, 112, 138],
520 &[6, 30, 58, 86, 114, 142],
521 &[6, 34, 62, 90, 118, 146],
522 &[6, 30, 54, 78, 102, 126, 150],
523 &[6, 24, 50, 76, 102, 128, 154],
524 &[6, 28, 54, 80, 106, 132, 158],
525 &[6, 32, 58, 84, 110, 136, 162],
526 &[6, 26, 54, 82, 110, 138, 166],
527 &[6, 30, 58, 86, 114, 142, 170],
528];
529
530impl Canvas {
535 fn draw_line(&mut self, x1: i16, y1: i16, x2: i16, y2: i16, color_even: Color, color_odd: Color) {
546 debug_assert!(x1 == x2 || y1 == y2);
547
548 if y1 == y2 {
549 for x in x1..=x2 {
551 self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd });
552 }
553 } else {
554 for y in y1..=y2 {
556 self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd });
557 }
558 }
559 }
560
561 fn draw_timing_patterns(&mut self) {
567 let width = self.width;
568 let (y, x1, x2) = match self.version {
569 Version::Micro(_) => (0, 8, width - 1),
570 Version::Normal(_) => (6, 8, width - 9),
571 };
572 self.draw_line(x1, y, x2, y, Color::Dark, Color::Light);
573 self.draw_line(y, x1, y, x2, Color::Dark, Color::Light);
574 }
575}
576
577#[cfg(test)]
578mod timing_pattern_tests {
579 use crate::canvas::Canvas;
580 use crate::types::{EcLevel, Version};
581
582 #[test]
583 fn test_draw_timing_patterns_qr() {
584 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
585 c.draw_timing_patterns();
586 assert_eq!(
587 &*c.to_debug_str(),
588 "\n\
589 ?????????????????????\n\
590 ?????????????????????\n\
591 ?????????????????????\n\
592 ?????????????????????\n\
593 ?????????????????????\n\
594 ?????????????????????\n\
595 ????????#.#.#????????\n\
596 ?????????????????????\n\
597 ??????#??????????????\n\
598 ??????.??????????????\n\
599 ??????#??????????????\n\
600 ??????.??????????????\n\
601 ??????#??????????????\n\
602 ?????????????????????\n\
603 ?????????????????????\n\
604 ?????????????????????\n\
605 ?????????????????????\n\
606 ?????????????????????\n\
607 ?????????????????????\n\
608 ?????????????????????\n\
609 ?????????????????????"
610 );
611 }
612
613 #[test]
614 fn test_draw_timing_patterns_micro_qr() {
615 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
616 c.draw_timing_patterns();
617 assert_eq!(
618 &*c.to_debug_str(),
619 "\n\
620 ????????#.#\n\
621 ???????????\n\
622 ???????????\n\
623 ???????????\n\
624 ???????????\n\
625 ???????????\n\
626 ???????????\n\
627 ???????????\n\
628 #??????????\n\
629 .??????????\n\
630 #??????????"
631 );
632 }
633}
634
635impl Canvas {
640 fn draw_number(&mut self, number: u32, bits: u32, on_color: Color, off_color: Color, coords: &[(i16, i16)]) {
647 let mut mask = 1 << (bits - 1);
648 for &(x, y) in coords {
649 let color = if (mask & number) == 0 { off_color } else { on_color };
650 self.put(x, y, color);
651 mask >>= 1;
652 }
653 }
654
655 fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
657 let format_info = u32::from(format_info);
658 match self.version {
659 Version::Micro(_) => {
660 self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_MICRO_QR);
661 }
662 Version::Normal(_) => {
663 self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_MAIN);
664 self.draw_number(format_info, 15, Color::Dark, Color::Light, &FORMAT_INFO_COORDS_QR_SIDE);
665 self.put(8, -8, Color::Dark); }
667 }
668 }
669
670 fn draw_reserved_format_info_patterns(&mut self) {
672 self.draw_format_info_patterns_with_number(0);
673 }
674
675 fn draw_version_info_patterns(&mut self) {
677 match self.version {
678 Version::Micro(_) | Version::Normal(1..=6) => {}
679 Version::Normal(a) => {
680 let version_info = VERSION_INFOS[(a - 7).as_usize()];
681 self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_BL);
682 self.draw_number(version_info, 18, Color::Dark, Color::Light, &VERSION_INFO_COORDS_TR);
683 }
684 }
685 }
686}
687
688#[cfg(test)]
689mod draw_version_info_tests {
690 use crate::canvas::Canvas;
691 use crate::types::{Color, EcLevel, Version};
692
693 #[test]
694 fn test_draw_number() {
695 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
696 c.draw_number(0b10101101, 8, Color::Dark, Color::Light, &[(0, 0), (0, -1), (-2, -2), (-2, 0)]);
697 assert_eq!(
698 &*c.to_debug_str(),
699 "\n\
700 #????????.?\n\
701 ???????????\n\
702 ???????????\n\
703 ???????????\n\
704 ???????????\n\
705 ???????????\n\
706 ???????????\n\
707 ???????????\n\
708 ???????????\n\
709 ?????????#?\n\
710 .??????????"
711 );
712 }
713
714 #[test]
715 fn test_draw_version_info_1() {
716 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
717 c.draw_version_info_patterns();
718 assert_eq!(
719 &*c.to_debug_str(),
720 "\n\
721 ?????????????????????\n\
722 ?????????????????????\n\
723 ?????????????????????\n\
724 ?????????????????????\n\
725 ?????????????????????\n\
726 ?????????????????????\n\
727 ?????????????????????\n\
728 ?????????????????????\n\
729 ?????????????????????\n\
730 ?????????????????????\n\
731 ?????????????????????\n\
732 ?????????????????????\n\
733 ?????????????????????\n\
734 ?????????????????????\n\
735 ?????????????????????\n\
736 ?????????????????????\n\
737 ?????????????????????\n\
738 ?????????????????????\n\
739 ?????????????????????\n\
740 ?????????????????????\n\
741 ?????????????????????"
742 );
743 }
744
745 #[test]
746 fn test_draw_version_info_7() {
747 let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
748 c.draw_version_info_patterns();
749
750 assert_eq!(
751 &*c.to_debug_str(),
752 "\n\
753 ??????????????????????????????????..#????????\n\
754 ??????????????????????????????????.#.????????\n\
755 ??????????????????????????????????.#.????????\n\
756 ??????????????????????????????????.##????????\n\
757 ??????????????????????????????????###????????\n\
758 ??????????????????????????????????...????????\n\
759 ?????????????????????????????????????????????\n\
760 ?????????????????????????????????????????????\n\
761 ?????????????????????????????????????????????\n\
762 ?????????????????????????????????????????????\n\
763 ?????????????????????????????????????????????\n\
764 ?????????????????????????????????????????????\n\
765 ?????????????????????????????????????????????\n\
766 ?????????????????????????????????????????????\n\
767 ?????????????????????????????????????????????\n\
768 ?????????????????????????????????????????????\n\
769 ?????????????????????????????????????????????\n\
770 ?????????????????????????????????????????????\n\
771 ?????????????????????????????????????????????\n\
772 ?????????????????????????????????????????????\n\
773 ?????????????????????????????????????????????\n\
774 ?????????????????????????????????????????????\n\
775 ?????????????????????????????????????????????\n\
776 ?????????????????????????????????????????????\n\
777 ?????????????????????????????????????????????\n\
778 ?????????????????????????????????????????????\n\
779 ?????????????????????????????????????????????\n\
780 ?????????????????????????????????????????????\n\
781 ?????????????????????????????????????????????\n\
782 ?????????????????????????????????????????????\n\
783 ?????????????????????????????????????????????\n\
784 ?????????????????????????????????????????????\n\
785 ?????????????????????????????????????????????\n\
786 ?????????????????????????????????????????????\n\
787 ....#.???????????????????????????????????????\n\
788 .####.???????????????????????????????????????\n\
789 #..##.???????????????????????????????????????\n\
790 ?????????????????????????????????????????????\n\
791 ?????????????????????????????????????????????\n\
792 ?????????????????????????????????????????????\n\
793 ?????????????????????????????????????????????\n\
794 ?????????????????????????????????????????????\n\
795 ?????????????????????????????????????????????\n\
796 ?????????????????????????????????????????????\n\
797 ?????????????????????????????????????????????"
798 );
799 }
800
801 #[test]
802 fn test_draw_reserved_format_info_patterns_qr() {
803 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
804 c.draw_reserved_format_info_patterns();
805 assert_eq!(
806 &*c.to_debug_str(),
807 "\n\
808 ????????.????????????\n\
809 ????????.????????????\n\
810 ????????.????????????\n\
811 ????????.????????????\n\
812 ????????.????????????\n\
813 ????????.????????????\n\
814 ?????????????????????\n\
815 ????????.????????????\n\
816 ......?..????........\n\
817 ?????????????????????\n\
818 ?????????????????????\n\
819 ?????????????????????\n\
820 ?????????????????????\n\
821 ????????#????????????\n\
822 ????????.????????????\n\
823 ????????.????????????\n\
824 ????????.????????????\n\
825 ????????.????????????\n\
826 ????????.????????????\n\
827 ????????.????????????\n\
828 ????????.????????????"
829 );
830 }
831
832 #[test]
833 fn test_draw_reserved_format_info_patterns_micro_qr() {
834 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
835 c.draw_reserved_format_info_patterns();
836 assert_eq!(
837 &*c.to_debug_str(),
838 "\n\
839 ???????????\n\
840 ????????.??\n\
841 ????????.??\n\
842 ????????.??\n\
843 ????????.??\n\
844 ????????.??\n\
845 ????????.??\n\
846 ????????.??\n\
847 ?........??\n\
848 ???????????\n\
849 ???????????"
850 );
851 }
852}
853
854static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [
855 (5, -9),
856 (5, -10),
857 (5, -11),
858 (4, -9),
859 (4, -10),
860 (4, -11),
861 (3, -9),
862 (3, -10),
863 (3, -11),
864 (2, -9),
865 (2, -10),
866 (2, -11),
867 (1, -9),
868 (1, -10),
869 (1, -11),
870 (0, -9),
871 (0, -10),
872 (0, -11),
873];
874
875static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [
876 (-9, 5),
877 (-10, 5),
878 (-11, 5),
879 (-9, 4),
880 (-10, 4),
881 (-11, 4),
882 (-9, 3),
883 (-10, 3),
884 (-11, 3),
885 (-9, 2),
886 (-10, 2),
887 (-11, 2),
888 (-9, 1),
889 (-10, 1),
890 (-11, 1),
891 (-9, 0),
892 (-10, 0),
893 (-11, 0),
894];
895
896static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [
897 (0, 8),
898 (1, 8),
899 (2, 8),
900 (3, 8),
901 (4, 8),
902 (5, 8),
903 (7, 8),
904 (8, 8),
905 (8, 7),
906 (8, 5),
907 (8, 4),
908 (8, 3),
909 (8, 2),
910 (8, 1),
911 (8, 0),
912];
913
914static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [
915 (8, -1),
916 (8, -2),
917 (8, -3),
918 (8, -4),
919 (8, -5),
920 (8, -6),
921 (8, -7),
922 (-8, 8),
923 (-7, 8),
924 (-6, 8),
925 (-5, 8),
926 (-4, 8),
927 (-3, 8),
928 (-2, 8),
929 (-1, 8),
930];
931
932static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [
933 (1, 8),
934 (2, 8),
935 (3, 8),
936 (4, 8),
937 (5, 8),
938 (6, 8),
939 (7, 8),
940 (8, 8),
941 (8, 7),
942 (8, 6),
943 (8, 5),
944 (8, 4),
945 (8, 3),
946 (8, 2),
947 (8, 1),
948];
949
950static VERSION_INFOS: [u32; 34] = [
951 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78, 0x1145d, 0x12a17,
952 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
953 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 0x27541, 0x28c69,
954];
955
956impl Canvas {
961 pub fn draw_all_functional_patterns(&mut self) {
968 self.draw_finder_patterns();
969 self.draw_alignment_patterns();
970 self.draw_reserved_format_info_patterns();
971 self.draw_timing_patterns();
972 self.draw_version_info_patterns();
973 }
974}
975
976pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool {
979 debug_assert!(width == version.width());
980
981 let x = if x < 0 { x + width } else { x };
982 let y = if y < 0 { y + width } else { y };
983
984 match version {
985 Version::Micro(_) => x == 0 || y == 0 || (x < 9 && y < 9),
986 Version::Normal(a) => {
987 let non_alignment_test = x == 6 || y == 6 || (x < 9 && y < 9) || (x < 9 && y >= width-8) || (x >= width-8 && y < 9); if non_alignment_test {
992 true
993 } else if a == 1 {
994 false
995 } else if 2 <= a && a <= 6 {
996 (width - 7 - x).abs() <= 2 && (width - 7 - y).abs() <= 2
997 } else {
998 let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()];
999 let last = positions.len() - 1;
1000 for (i, align_x) in positions.iter().enumerate() {
1001 for (j, align_y) in positions.iter().enumerate() {
1002 if i == 0 && (j == 0 || j == last) || (i == last && j == 0) {
1003 continue;
1004 }
1005 if (*align_x - x).abs() <= 2 && (*align_y - y).abs() <= 2 {
1006 return true;
1007 }
1008 }
1009 }
1010 false
1011 }
1012 }
1013 }
1014}
1015
1016#[cfg(test)]
1017mod all_functional_patterns_tests {
1018 use crate::canvas::{is_functional, Canvas};
1019 use crate::types::{EcLevel, Version};
1020
1021 #[test]
1022 fn test_all_functional_patterns_qr() {
1023 let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1024 c.draw_all_functional_patterns();
1025 assert_eq!(
1026 &*c.to_debug_str(),
1027 "\n\
1028 #######..????????.#######\n\
1029 #.....#..????????.#.....#\n\
1030 #.###.#..????????.#.###.#\n\
1031 #.###.#..????????.#.###.#\n\
1032 #.###.#..????????.#.###.#\n\
1033 #.....#..????????.#.....#\n\
1034 #######.#.#.#.#.#.#######\n\
1035 .........????????........\n\
1036 ......#..????????........\n\
1037 ??????.??????????????????\n\
1038 ??????#??????????????????\n\
1039 ??????.??????????????????\n\
1040 ??????#??????????????????\n\
1041 ??????.??????????????????\n\
1042 ??????#??????????????????\n\
1043 ??????.??????????????????\n\
1044 ??????#?????????#####????\n\
1045 ........#???????#...#????\n\
1046 #######..???????#.#.#????\n\
1047 #.....#..???????#...#????\n\
1048 #.###.#..???????#####????\n\
1049 #.###.#..????????????????\n\
1050 #.###.#..????????????????\n\
1051 #.....#..????????????????\n\
1052 #######..????????????????"
1053 );
1054 }
1055
1056 #[test]
1057 fn test_all_functional_patterns_micro_qr() {
1058 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1059 c.draw_all_functional_patterns();
1060 assert_eq!(
1061 &*c.to_debug_str(),
1062 "\n\
1063 #######.#.#\n\
1064 #.....#..??\n\
1065 #.###.#..??\n\
1066 #.###.#..??\n\
1067 #.###.#..??\n\
1068 #.....#..??\n\
1069 #######..??\n\
1070 .........??\n\
1071 #........??\n\
1072 .??????????\n\
1073 #??????????"
1074 );
1075 }
1076
1077 #[test]
1078 fn test_is_functional_qr_1() {
1079 let version = Version::Normal(1);
1080 assert!(is_functional(version, version.width(), 0, 0));
1081 assert!(is_functional(version, version.width(), 10, 6));
1082 assert!(!is_functional(version, version.width(), 10, 5));
1083 assert!(!is_functional(version, version.width(), 14, 14));
1084 assert!(is_functional(version, version.width(), 6, 11));
1085 assert!(!is_functional(version, version.width(), 4, 11));
1086 assert!(is_functional(version, version.width(), 4, 13));
1087 assert!(is_functional(version, version.width(), 17, 7));
1088 assert!(!is_functional(version, version.width(), 17, 17));
1089 }
1090
1091 #[test]
1092 fn test_is_functional_qr_3() {
1093 let version = Version::Normal(3);
1094 assert!(is_functional(version, version.width(), 0, 0));
1095 assert!(!is_functional(version, version.width(), 25, 24));
1096 assert!(is_functional(version, version.width(), 24, 24));
1097 assert!(!is_functional(version, version.width(), 9, 25));
1098 assert!(!is_functional(version, version.width(), 20, 0));
1099 assert!(is_functional(version, version.width(), 21, 0));
1100 }
1101
1102 #[test]
1103 fn test_is_functional_qr_7() {
1104 let version = Version::Normal(7);
1105 assert!(is_functional(version, version.width(), 21, 4));
1106 assert!(is_functional(version, version.width(), 7, 21));
1107 assert!(is_functional(version, version.width(), 22, 22));
1108 assert!(is_functional(version, version.width(), 8, 8));
1109 assert!(!is_functional(version, version.width(), 19, 5));
1110 assert!(!is_functional(version, version.width(), 36, 3));
1111 assert!(!is_functional(version, version.width(), 4, 36));
1112 assert!(is_functional(version, version.width(), 38, 38));
1113 }
1114
1115 #[test]
1116 fn test_is_functional_micro() {
1117 let version = Version::Micro(1);
1118 assert!(is_functional(version, version.width(), 8, 0));
1119 assert!(is_functional(version, version.width(), 10, 0));
1120 assert!(!is_functional(version, version.width(), 10, 1));
1121 assert!(is_functional(version, version.width(), 8, 8));
1122 assert!(is_functional(version, version.width(), 0, 9));
1123 assert!(!is_functional(version, version.width(), 1, 9));
1124 }
1125}
1126
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 while let Some((x, y)) = coords.next() {
1368 let r = self.get_mut(x, y);
1369 if *r == Module::Empty {
1370 *r = Module::Unmasked(color);
1371 continue 'outside;
1372 }
1373 }
1374 return;
1375 }
1376 }
1377 }
1378
1379 pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
1381 let is_half_codeword_at_end = match (self.version, self.ec_level) {
1382 (Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M) => true,
1383 _ => false,
1384 };
1385
1386 let mut coords = DataModuleIter::new(self.version);
1387 self.draw_codewords(data, is_half_codeword_at_end, &mut coords);
1388 self.draw_codewords(ec, false, &mut coords);
1389 }
1390}
1391
1392#[cfg(test)]
1393mod draw_codewords_test {
1394 use crate::canvas::Canvas;
1395 use crate::types::{EcLevel, Version};
1396
1397 #[test]
1398 fn test_micro_qr_1() {
1399 let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
1400 c.draw_all_functional_patterns();
1401 c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
1402 assert_eq!(
1403 &*c.to_debug_str(),
1404 "\n\
1405 #######.#.#\n\
1406 #.....#..-*\n\
1407 #.###.#..**\n\
1408 #.###.#..*-\n\
1409 #.###.#..**\n\
1410 #.....#..*-\n\
1411 #######..*-\n\
1412 .........-*\n\
1413 #........**\n\
1414 .***-**---*\n\
1415 #---*-*-**-"
1416 );
1417 }
1418
1419 #[test]
1420 fn test_qr_2() {
1421 let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
1422 c.draw_all_functional_patterns();
1423 c.draw_data(
1424 b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\
1425 \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$",
1426 b"",
1427 );
1428 assert_eq!(
1429 &*c.to_debug_str(),
1430 "\n\
1431 #######..--*---*-.#######\n\
1432 #.....#..-*-*-*-*.#.....#\n\
1433 #.###.#..*---*---.#.###.#\n\
1434 #.###.#..--*---*-.#.###.#\n\
1435 #.###.#..-*-*-*-*.#.###.#\n\
1436 #.....#..*---*---.#.....#\n\
1437 #######.#.#.#.#.#.#######\n\
1438 .........--*---*-........\n\
1439 ......#..-*-*-*-*........\n\
1440 --*-*-.-**---*---*--**--*\n\
1441 -*-*--#----*---*---------\n\
1442 *----*.*--*-*-*-*-**--**-\n\
1443 --*-*-#-**---*---*--**--*\n\
1444 -*-*--.----*---*---------\n\
1445 *----*#*--*-*-*-*-**--**-\n\
1446 --*-*-.-**---*---*--**--*\n\
1447 -*-*--#----*---*#####----\n\
1448 ........#-*-*-*-#...#-**-\n\
1449 #######..*---*--#.#.#*--*\n\
1450 #.....#..--*---*#...#----\n\
1451 #.###.#..-*-*-*-#####-**-\n\
1452 #.###.#..*---*--*----*--*\n\
1453 #.###.#..--*------**-----\n\
1454 #.....#..-*-*-**-*--*-**-\n\
1455 #######..*---*--*----*--*"
1456 );
1457 }
1458}
1459#[derive(Debug, Copy, Clone)]
1466pub enum MaskPattern {
1467 Checkerboard = 0b000,
1469
1470 HorizontalLines = 0b001,
1472
1473 VerticalLines = 0b010,
1475
1476 DiagonalLines = 0b011,
1478
1479 LargeCheckerboard = 0b100,
1481
1482 Fields = 0b101,
1484
1485 Diamonds = 0b110,
1487
1488 Meadow = 0b111,
1490}
1491
1492mod mask_functions {
1493 pub fn checkerboard(x: i16, y: i16) -> bool {
1494 (x + y) % 2 == 0
1495 }
1496 pub fn horizontal_lines(_: i16, y: i16) -> bool {
1497 y % 2 == 0
1498 }
1499 pub fn vertical_lines(x: i16, _: i16) -> bool {
1500 x % 3 == 0
1501 }
1502 pub fn diagonal_lines(x: i16, y: i16) -> bool {
1503 (x + y) % 3 == 0
1504 }
1505 pub fn large_checkerboard(x: i16, y: i16) -> bool {
1506 ((y / 2) + (x / 3)) % 2 == 0
1507 }
1508 pub fn fields(x: i16, y: i16) -> bool {
1509 (x * y) % 2 + (x * y) % 3 == 0
1510 }
1511 pub fn diamonds(x: i16, y: i16) -> bool {
1512 ((x * y) % 2 + (x * y) % 3) % 2 == 0
1513 }
1514 pub fn meadow(x: i16, y: i16) -> bool {
1515 ((x + y) % 2 + (x * y) % 3) % 2 == 0
1516 }
1517}
1518
1519fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
1520 match pattern {
1521 MaskPattern::Checkerboard => mask_functions::checkerboard,
1522 MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
1523 MaskPattern::VerticalLines => mask_functions::vertical_lines,
1524 MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
1525 MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
1526 MaskPattern::Fields => mask_functions::fields,
1527 MaskPattern::Diamonds => mask_functions::diamonds,
1528 MaskPattern::Meadow => mask_functions::meadow,
1529 }
1530}
1531
1532impl Canvas {
1533 pub fn apply_mask(&mut self, pattern: MaskPattern) {
1536 let mask_fn = get_mask_function(pattern);
1537 for x in 0..self.width {
1538 for y in 0..self.width {
1539 let module = self.get_mut(x, y);
1540 *module = module.mask(mask_fn(x, y));
1541 }
1542 }
1543
1544 self.draw_format_info_patterns(pattern);
1545 }
1546
1547 fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
1553 let format_number = match self.version {
1554 Version::Normal(_) => {
1555 let simple_format_number = ((self.ec_level as usize) ^ 1) << 3 | (pattern as usize);
1556 FORMAT_INFOS_QR[simple_format_number]
1557 }
1558 Version::Micro(a) => {
1559 let micro_pattern_number = match pattern {
1560 MaskPattern::HorizontalLines => 0b00,
1561 MaskPattern::LargeCheckerboard => 0b01,
1562 MaskPattern::Diamonds => 0b10,
1563 MaskPattern::Meadow => 0b11,
1564 _ => panic!("Unsupported mask pattern in Micro QR code"),
1565 };
1566 let symbol_number = match (a, self.ec_level) {
1567 (1, EcLevel::L) => 0b000,
1568 (2, EcLevel::L) => 0b001,
1569 (2, EcLevel::M) => 0b010,
1570 (3, EcLevel::L) => 0b011,
1571 (3, EcLevel::M) => 0b100,
1572 (4, EcLevel::L) => 0b101,
1573 (4, EcLevel::M) => 0b110,
1574 (4, EcLevel::Q) => 0b111,
1575 _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
1576 };
1577 let simple_format_number = symbol_number << 2 | micro_pattern_number;
1578 FORMAT_INFOS_MICRO_QR[simple_format_number]
1579 }
1580 };
1581 self.draw_format_info_patterns_with_number(format_number);
1582 }
1583}
1584
1585#[cfg(test)]
1586mod mask_tests {
1587 use crate::canvas::{Canvas, MaskPattern};
1588 use crate::types::{EcLevel, Version};
1589
1590 #[test]
1591 fn test_apply_mask_qr() {
1592 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1593 c.draw_all_functional_patterns();
1594 c.apply_mask(MaskPattern::Checkerboard);
1595
1596 assert_eq!(
1597 &*c.to_debug_str(),
1598 "\n\
1599 #######...#.#.#######\n\
1600 #.....#..#.#..#.....#\n\
1601 #.###.#.#.#.#.#.###.#\n\
1602 #.###.#..#.#..#.###.#\n\
1603 #.###.#...#.#.#.###.#\n\
1604 #.....#..#.#..#.....#\n\
1605 #######.#.#.#.#######\n\
1606 ........##.#.........\n\
1607 ###.#####.#.###...#..\n\
1608 .#.#.#.#.#.#.#.#.#.#.\n\
1609 #.#.#.#.#.#.#.#.#.#.#\n\
1610 .#.#.#.#.#.#.#.#.#.#.\n\
1611 #.#.#.#.#.#.#.#.#.#.#\n\
1612 ........##.#.#.#.#.#.\n\
1613 #######.#.#.#.#.#.#.#\n\
1614 #.....#.##.#.#.#.#.#.\n\
1615 #.###.#.#.#.#.#.#.#.#\n\
1616 #.###.#..#.#.#.#.#.#.\n\
1617 #.###.#.#.#.#.#.#.#.#\n\
1618 #.....#.##.#.#.#.#.#.\n\
1619 #######.#.#.#.#.#.#.#"
1620 );
1621 }
1622
1623 #[test]
1624 fn test_draw_format_info_patterns_qr() {
1625 let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
1626 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1627 assert_eq!(
1628 &*c.to_debug_str(),
1629 "\n\
1630 ????????#????????????\n\
1631 ????????#????????????\n\
1632 ????????#????????????\n\
1633 ????????#????????????\n\
1634 ????????.????????????\n\
1635 ????????#????????????\n\
1636 ?????????????????????\n\
1637 ????????.????????????\n\
1638 ##..##?..????..#.####\n\
1639 ?????????????????????\n\
1640 ?????????????????????\n\
1641 ?????????????????????\n\
1642 ?????????????????????\n\
1643 ????????#????????????\n\
1644 ????????.????????????\n\
1645 ????????#????????????\n\
1646 ????????#????????????\n\
1647 ????????.????????????\n\
1648 ????????.????????????\n\
1649 ????????#????????????\n\
1650 ????????#????????????"
1651 );
1652 }
1653
1654 #[test]
1655 fn test_draw_format_info_patterns_micro_qr() {
1656 let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
1657 c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
1658 assert_eq!(
1659 &*c.to_debug_str(),
1660 "\n\
1661 ?????????????\n\
1662 ????????#????\n\
1663 ????????.????\n\
1664 ????????.????\n\
1665 ????????#????\n\
1666 ????????#????\n\
1667 ????????.????\n\
1668 ????????.????\n\
1669 ?#.#....#????\n\
1670 ?????????????\n\
1671 ?????????????\n\
1672 ?????????????\n\
1673 ?????????????"
1674 );
1675 }
1676}
1677
1678static FORMAT_INFOS_QR: [u16; 32] = [
1679 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318,
1680 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06,
1681 0x24b4, 0x2183, 0x2eda, 0x2bed,
1682];
1683
1684static FORMAT_INFOS_MICRO_QR: [u16; 32] = [
1685 0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f,
1686 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51,
1687 0x34e3, 0x31d4, 0x3e8d, 0x3bba,
1688];
1689
1690impl Canvas {
1695 fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 {
1701 let mut total_score = 0;
1702
1703 for i in 0..self.width {
1704 let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) };
1705
1706 let colors = (0..self.width).map(map_fn).chain(Some(Module::Empty).into_iter());
1707 let mut last_color = Module::Empty;
1708 let mut consecutive_len = 1_u16;
1709
1710 for color in colors {
1711 if color == last_color {
1712 consecutive_len += 1;
1713 } else {
1714 last_color = color;
1715 if consecutive_len >= 5 {
1716 total_score += consecutive_len - 2;
1717 }
1718 consecutive_len = 1;
1719 }
1720 }
1721 }
1722
1723 total_score
1724 }
1725
1726 fn compute_block_penalty_score(&self) -> u16 {
1732 let mut total_score = 0;
1733
1734 for i in 0..self.width - 1 {
1735 for j in 0..self.width - 1 {
1736 let this = self.get(i, j);
1737 let right = self.get(i + 1, j);
1738 let bottom = self.get(i, j + 1);
1739 let bottom_right = self.get(i + 1, j + 1);
1740 if this == right && right == bottom && bottom == bottom_right {
1741 total_score += 3;
1742 }
1743 }
1744 }
1745
1746 total_score
1747 }
1748
1749 fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
1755 static PATTERN: [Color; 7] =
1756 [Color::Dark, Color::Light, Color::Dark, Color::Dark, Color::Dark, Color::Light, Color::Dark];
1757
1758 let mut total_score = 0;
1759
1760 for i in 0..self.width {
1761 for j in 0..self.width - 6 {
1762 let get: Box<dyn Fn(i16) -> Color> = if is_horizontal {
1764 Box::new(|k| self.get(k, i).into())
1765 } else {
1766 Box::new(|k| self.get(i, k).into())
1767 };
1768
1769 if (j..(j + 7)).map(&*get).ne(PATTERN.iter().cloned()) {
1770 continue;
1771 }
1772
1773 let check = |k| 0 <= k && k < self.width && get(k) != Color::Light;
1774 if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) {
1775 total_score += 40;
1776 }
1777 }
1778 }
1779
1780 total_score - 360
1781 }
1782
1783 fn compute_balance_penalty_score(&self) -> u16 {
1792 let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count();
1793 let total_modules = self.modules.len();
1794 let ratio = dark_modules * 200 / total_modules;
1795 if ratio >= 100 { ratio - 100 } else { 100 - ratio }.as_u16()
1796 }
1797
1798 fn compute_light_side_penalty_score(&self) -> u16 {
1806 let h = (1..self.width).filter(|j| !self.get(*j, -1).is_dark()).count();
1807 let v = (1..self.width).filter(|j| !self.get(-1, *j).is_dark()).count();
1808
1809 (h + v + 15 * max(h, v)).as_u16()
1810 }
1811
1812 fn compute_total_penalty_scores(&self) -> u16 {
1815 match self.version {
1816 Version::Normal(_) => {
1817 let s1_a = self.compute_adjacent_penalty_score(true);
1818 let s1_b = self.compute_adjacent_penalty_score(false);
1819 let s2 = self.compute_block_penalty_score();
1820 let s3_a = self.compute_finder_penalty_score(true);
1821 let s3_b = self.compute_finder_penalty_score(false);
1822 let s4 = self.compute_balance_penalty_score();
1823 s1_a + s1_b + s2 + s3_a + s3_b + s4
1824 }
1825 Version::Micro(_) => self.compute_light_side_penalty_score(),
1826 }
1827 }
1828}
1829
1830#[cfg(test)]
1831mod penalty_tests {
1832 use crate::canvas::{Canvas, MaskPattern};
1833 use crate::types::{Color, EcLevel, Version};
1834
1835 fn create_test_canvas() -> Canvas {
1836 let mut c = Canvas::new(Version::Normal(1), EcLevel::Q);
1837 c.draw_all_functional_patterns();
1838 c.draw_data(
1839 b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00",
1840 b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10",
1841 );
1842 c.apply_mask(MaskPattern::Checkerboard);
1843 c
1844 }
1845
1846 #[test]
1847 fn check_penalty_canvas() {
1848 let c = create_test_canvas();
1849 assert_eq!(
1850 &*c.to_debug_str(),
1851 "\n\
1852 #######.##....#######\n\
1853 #.....#.#..#..#.....#\n\
1854 #.###.#.#..##.#.###.#\n\
1855 #.###.#.#.....#.###.#\n\
1856 #.###.#.#.#...#.###.#\n\
1857 #.....#...#...#.....#\n\
1858 #######.#.#.#.#######\n\
1859 ........#............\n\
1860 .##.#.##....#.#.#####\n\
1861 .#......####....#...#\n\
1862 ..##.###.##...#.##...\n\
1863 .##.##.#..##.#.#.###.\n\
1864 #...#.#.#.###.###.#.#\n\
1865 ........##.#..#...#.#\n\
1866 #######.#.#....#.##..\n\
1867 #.....#..#.##.##.#...\n\
1868 #.###.#.#.#...#######\n\
1869 #.###.#..#.#.#.#...#.\n\
1870 #.###.#.#...####.#..#\n\
1871 #.....#.#.##.#...#.##\n\
1872 #######.....####....#"
1873 );
1874 }
1875
1876 #[test]
1877 fn test_penalty_score_adjacent() {
1878 let c = create_test_canvas();
1879 assert_eq!(c.compute_adjacent_penalty_score(true), 88);
1880 assert_eq!(c.compute_adjacent_penalty_score(false), 92);
1881 }
1882
1883 #[test]
1884 fn test_penalty_score_block() {
1885 let c = create_test_canvas();
1886 assert_eq!(c.compute_block_penalty_score(), 90);
1887 }
1888
1889 #[test]
1890 fn test_penalty_score_finder() {
1891 let c = create_test_canvas();
1892 assert_eq!(c.compute_finder_penalty_score(true), 0);
1893 assert_eq!(c.compute_finder_penalty_score(false), 40);
1894 }
1895
1896 #[test]
1897 fn test_penalty_score_balance() {
1898 let c = create_test_canvas();
1899 assert_eq!(c.compute_balance_penalty_score(), 2);
1900 }
1901
1902 #[test]
1903 fn test_penalty_score_light_sides() {
1904 static HORIZONTAL_SIDE: [Color; 17] = [
1905 Color::Dark,
1906 Color::Light,
1907 Color::Light,
1908 Color::Dark,
1909 Color::Dark,
1910 Color::Dark,
1911 Color::Light,
1912 Color::Light,
1913 Color::Dark,
1914 Color::Light,
1915 Color::Dark,
1916 Color::Light,
1917 Color::Light,
1918 Color::Dark,
1919 Color::Light,
1920 Color::Light,
1921 Color::Light,
1922 ];
1923 static VERTICAL_SIDE: [Color; 17] = [
1924 Color::Dark,
1925 Color::Dark,
1926 Color::Dark,
1927 Color::Light,
1928 Color::Light,
1929 Color::Dark,
1930 Color::Dark,
1931 Color::Light,
1932 Color::Dark,
1933 Color::Light,
1934 Color::Dark,
1935 Color::Light,
1936 Color::Dark,
1937 Color::Light,
1938 Color::Light,
1939 Color::Dark,
1940 Color::Light,
1941 ];
1942
1943 let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
1944 for i in 0_i16..17 {
1945 c.put(i, -1, HORIZONTAL_SIDE[i as usize]);
1946 c.put(-1, i, VERTICAL_SIDE[i as usize]);
1947 }
1948
1949 assert_eq!(c.compute_light_side_penalty_score(), 168);
1950 }
1951}
1952
1953static ALL_PATTERNS_QR: [MaskPattern; 8] = [
1958 MaskPattern::Checkerboard,
1959 MaskPattern::HorizontalLines,
1960 MaskPattern::VerticalLines,
1961 MaskPattern::DiagonalLines,
1962 MaskPattern::LargeCheckerboard,
1963 MaskPattern::Fields,
1964 MaskPattern::Diamonds,
1965 MaskPattern::Meadow,
1966];
1967
1968static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] =
1969 [MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, MaskPattern::Diamonds, MaskPattern::Meadow];
1970
1971impl Canvas {
1972 pub fn apply_best_mask(&self) -> Self {
1975 match self.version {
1976 Version::Normal(_) => ALL_PATTERNS_QR.iter(),
1977 Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
1978 }
1979 .map(|ptn| {
1980 let mut c = self.clone();
1981 c.apply_mask(*ptn);
1982 c
1983 })
1984 .min_by_key(Self::compute_total_penalty_scores)
1985 .expect("at least one pattern")
1986 }
1987
1988 #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")]
1990 pub fn to_bools(&self) -> Vec<bool> {
1991 self.modules.iter().map(|m| m.is_dark()).collect()
1992 }
1993
1994 pub fn into_colors(self) -> Vec<Color> {
1996 self.modules.into_iter().map(Color::from).collect()
1997 }
1998}
1999
2000