use super::Canvas;
use crate::{
cast::As,
types::{Color, EcLevel, Version},
};
impl Canvas {
fn draw_number(
&mut self,
number: u32,
bits: u32,
on_color: Color,
off_color: Color,
coords: &[(i16, i16)],
) {
let mut mask = 1 << (bits - 1);
for &(x, y) in coords {
let color = if (mask & number) == 0 {
off_color
} else {
on_color
};
self.put(x, y, color);
mask >>= 1;
}
}
pub(super) fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
let format_info = u32::from(format_info);
match self.version {
Version::Micro(_) => {
self.draw_number(
format_info,
15,
Color::Dark,
Color::Light,
&FORMAT_INFO_COORDS_MICRO_QR,
);
}
Version::Normal(_) => {
self.draw_number(
format_info,
15,
Color::Dark,
Color::Light,
&FORMAT_INFO_COORDS_QR_MAIN,
);
self.draw_number(
format_info,
15,
Color::Dark,
Color::Light,
&FORMAT_INFO_COORDS_QR_SIDE,
);
self.put(8, -8, Color::Dark);
}
Version::RectMicro(..) => {}
}
}
pub(super) fn draw_reserved_format_info_patterns(&mut self) {
self.draw_format_info_patterns_with_number(0);
}
pub(super) fn draw_version_info_patterns(&mut self) {
match self.version {
Version::Micro(_) | Version::Normal(1..=6) => {}
Version::Normal(a) => {
let version_info = VERSION_INFOS[(a - 7).as_usize()];
self.draw_number(
version_info,
18,
Color::Dark,
Color::Light,
&VERSION_INFO_COORDS_BL,
);
self.draw_number(
version_info,
18,
Color::Dark,
Color::Light,
&VERSION_INFO_COORDS_TR,
);
}
Version::RectMicro(..) => {
let index = self.version.rect_micro_index().unwrap();
let ec_level = usize::from(self.ec_level != EcLevel::M);
let version_info_left = RMQR_VERSION_INFOS_L[index][ec_level];
let version_info_right = RMQR_VERSION_INFOS_R[index][ec_level];
self.draw_number(
version_info_left,
18,
Color::Dark,
Color::Light,
&RMQR_VERSION_INFO_COORDS_L,
);
self.draw_number(
version_info_right,
18,
Color::Dark,
Color::Light,
&RMQR_VERSION_INFO_COORDS_R,
);
}
}
}
}
static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [
(5, -9),
(5, -10),
(5, -11),
(4, -9),
(4, -10),
(4, -11),
(3, -9),
(3, -10),
(3, -11),
(2, -9),
(2, -10),
(2, -11),
(1, -9),
(1, -10),
(1, -11),
(0, -9),
(0, -10),
(0, -11),
];
static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [
(-9, 5),
(-10, 5),
(-11, 5),
(-9, 4),
(-10, 4),
(-11, 4),
(-9, 3),
(-10, 3),
(-11, 3),
(-9, 2),
(-10, 2),
(-11, 2),
(-9, 1),
(-10, 1),
(-11, 1),
(-9, 0),
(-10, 0),
(-11, 0),
];
static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [
(0, 8),
(1, 8),
(2, 8),
(3, 8),
(4, 8),
(5, 8),
(7, 8),
(8, 8),
(8, 7),
(8, 5),
(8, 4),
(8, 3),
(8, 2),
(8, 1),
(8, 0),
];
static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [
(8, -1),
(8, -2),
(8, -3),
(8, -4),
(8, -5),
(8, -6),
(8, -7),
(-8, 8),
(-7, 8),
(-6, 8),
(-5, 8),
(-4, 8),
(-3, 8),
(-2, 8),
(-1, 8),
];
static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [
(1, 8),
(2, 8),
(3, 8),
(4, 8),
(5, 8),
(6, 8),
(7, 8),
(8, 8),
(8, 7),
(8, 6),
(8, 5),
(8, 4),
(8, 3),
(8, 2),
(8, 1),
];
static VERSION_INFOS: [u32; 34] = [
0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
0x2542E, 0x26A64, 0x27541, 0x28C69,
];
static RMQR_VERSION_INFO_COORDS_L: [(i16, i16); 18] = [
(11, 3),
(11, 2),
(11, 1),
(10, 5),
(10, 4),
(10, 3),
(10, 2),
(10, 1),
(9, 5),
(9, 4),
(9, 3),
(9, 2),
(9, 1),
(8, 5),
(8, 4),
(8, 3),
(8, 2),
(8, 1),
];
static RMQR_VERSION_INFO_COORDS_R: [(i16, i16); 18] = [
(-3, -6),
(-4, -6),
(-5, -6),
(-6, -2),
(-6, -3),
(-6, -4),
(-6, -5),
(-6, -6),
(-7, -2),
(-7, -3),
(-7, -4),
(-7, -5),
(-7, -6),
(-8, -2),
(-8, -3),
(-8, -4),
(-8, -5),
(-8, -6),
];
static RMQR_VERSION_INFOS_L: [[u32; 2]; 32] = [
[0x1FAB2, 0x3F367],
[0x1E597, 0x3EC42],
[0x1DBDD, 0x3D208],
[0x1C4F8, 0x3CD2D],
[0x1B86C, 0x3B1B9],
[0x1A749, 0x3AE9C],
[0x19903, 0x390D6],
[0x18626, 0x38FF3],
[0x17F0E, 0x376DB],
[0x1602B, 0x369FE],
[0x15E61, 0x357B4],
[0x14144, 0x34891],
[0x13DD0, 0x33405],
[0x122F5, 0x32B20],
[0x11CBF, 0x3156A],
[0x1039A, 0x30A4F],
[0xF1CA, 0x2F81F],
[0xEEEF, 0x2E73A],
[0xD0A5, 0x2D970],
[0xCF80, 0x2C655],
[0xB314, 0x2BAC1],
[0xAC31, 0x2A5E4],
[0x927B, 0x29BAE],
[0x8D5E, 0x2848B],
[0x7476, 0x27DA3],
[0x6B53, 0x26286],
[0x5519, 0x25CCC],
[0x4A3C, 0x243E9],
[0x36A8, 0x23F7D],
[0x298D, 0x22058],
[0x17C7, 0x21E12],
[0x8E2, 0x20137],
];
static RMQR_VERSION_INFOS_R: [[u32; 2]; 32] = [
[0x20A7B, 0x3AE],
[0x2155E, 0x1C8B],
[0x22B14, 0x22C1],
[0x23431, 0x3DE4],
[0x248A5, 0x4170],
[0x25780, 0x5E55],
[0x269CA, 0x601F],
[0x276EF, 0x7F3A],
[0x28FC7, 0x8612],
[0x290E2, 0x9937],
[0x2AEA8, 0xA77D],
[0x2B18D, 0xB858],
[0x2CD19, 0xC4CC],
[0x2D23C, 0xDBE9],
[0x2EC76, 0xE5A3],
[0x2F353, 0xFA86],
[0x30103, 0x108D6],
[0x31E26, 0x117F3],
[0x3206C, 0x129B9],
[0x33F49, 0x1369C],
[0x343DD, 0x14A08],
[0x35CF8, 0x1552D],
[0x362B2, 0x16B67],
[0x37D97, 0x17442],
[0x384BF, 0x18D6A],
[0x39B9A, 0x1924F],
[0x3A5D0, 0x1AC05],
[0x3BAF5, 0x1B320],
[0x3C661, 0x1CFB4],
[0x3D944, 0x1D091],
[0x3E70E, 0x1EEDB],
[0x3F82B, 0x1F1FE],
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_draw_number() {
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
c.draw_number(
0b1010_1101,
8,
Color::Dark,
Color::Light,
&[(0, 0), (0, -1), (-2, -2), (-2, 0)],
);
assert_eq!(
c.to_debug_str(),
concat!(
"\n",
"#????????.?\n",
"???????????\n",
"???????????\n",
"???????????\n",
"???????????\n",
"???????????\n",
"???????????\n",
"???????????\n",
"???????????\n",
"?????????#?\n",
".??????????"
)
);
}
#[test]
fn test_draw_version_info_1() {
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
c.draw_version_info_patterns();
assert_eq!(
c.to_debug_str(),
concat!(
"\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????"
)
);
}
#[test]
fn test_draw_version_info_7() {
let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
c.draw_version_info_patterns();
assert_eq!(
c.to_debug_str(),
concat!(
"\n",
"??????????????????????????????????..#????????\n",
"??????????????????????????????????.#.????????\n",
"??????????????????????????????????.#.????????\n",
"??????????????????????????????????.##????????\n",
"??????????????????????????????????###????????\n",
"??????????????????????????????????...????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"....#.???????????????????????????????????????\n",
".####.???????????????????????????????????????\n",
"#..##.???????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????\n",
"?????????????????????????????????????????????"
)
);
}
#[test]
fn test_draw_reserved_format_info_patterns_qr() {
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
c.draw_reserved_format_info_patterns();
assert_eq!(
c.to_debug_str(),
concat!(
"\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"?????????????????????\n",
"????????.????????????\n",
"......?..????........\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"?????????????????????\n",
"????????#????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????\n",
"????????.????????????"
)
);
}
#[test]
fn test_draw_reserved_format_info_patterns_micro_qr() {
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
c.draw_reserved_format_info_patterns();
assert_eq!(
c.to_debug_str(),
concat!(
"\n",
"???????????\n",
"????????.??\n",
"????????.??\n",
"????????.??\n",
"????????.??\n",
"????????.??\n",
"????????.??\n",
"????????.??\n",
"?........??\n",
"???????????\n",
"???????????"
)
);
}
}