1use core::fmt::Write;
4
5use qrcode_rust_shared::{
6 qr_8bit_byte::QR8bitByte,
7 qr_bit_buffer::BitBuffer,
8 qr_code_model::{get_type_number, QRErrorCorrectLevel, QRMode, PATTERN_POSITION_TABLE},
9 qr_polynomial::Polynomial,
10 qr_rs_block::get_rs_blocks,
11 qr_util::{get_bch_digit, get_length_in_bits},
12};
13
14#[derive(Clone)]
16pub struct QRCodeOptions {
17 pub width: i32,
18 pub height: i32,
19 pub color_dark: String,
20 pub color_light: String,
21 pub correct_level: QRErrorCorrectLevel,
22}
23
24impl Default for QRCodeOptions {
25 fn default() -> Self {
26 QRCodeOptions {
27 width: 256,
28 height: 256,
29 color_dark: String::from("#000000"),
30 color_light: String::from("#ffffff"),
31 correct_level: QRErrorCorrectLevel::H,
32 }
33 }
34}
35
36pub struct QRCode {
38 pub options: QRCodeOptions,
39 pub type_number: i32,
40 pub module_count: i32,
41 pub modules: Vec<Vec<Option<bool>>>,
42 pub data_cache: Option<Vec<i32>>,
43 pub data_list: Vec<QR8bitByte>,
44}
45
46impl QRCode {
47 pub fn new() -> Self {
48 QRCode {
49 options: QRCodeOptions::default(),
50 type_number: 0,
51 module_count: 0,
52 modules: Vec::new(),
53 data_cache: None,
54 data_list: Vec::new(),
55 }
56 }
57
58 pub fn with_options(options: QRCodeOptions) -> Self {
59 QRCode {
60 options,
61 type_number: 0,
62 module_count: 0,
63 modules: Vec::new(),
64 data_cache: None,
65 data_list: Vec::new(),
66 }
67 }
68
69 pub fn add_data(&mut self, data: &str) {
70 self.data_list.push(QR8bitByte::new(data));
71 self.data_cache = None;
72 }
73
74 pub fn is_dark(&self, row: i32, col: i32) -> bool {
75 if row < 0 || self.module_count <= row || col < 0 || self.module_count <= col {
76 panic!("isDark: out of range");
77 }
78 self.modules[row as usize][col as usize].unwrap_or(false)
79 }
80
81 pub fn get_module_count(&self) -> i32 {
82 self.module_count
83 }
84
85 pub fn get_modules(&self) -> Option<&Vec<Vec<Option<bool>>>> {
86 if self.modules.is_empty() {
87 None
88 } else {
89 Some(&self.modules)
90 }
91 }
92
93 pub fn make_code(&mut self, text: &str) {
94 self.data_list.clear();
95 self.add_data(text);
96 self.make();
97 }
98
99 fn make(&mut self) {
100 self.make_impl(false);
101 }
102
103 fn make_impl(&mut self, test: bool) {
104 if self.type_number == 0 {
106 let mut type_num = 1;
107 for data in &self.data_list {
108 type_num = type_num.max(get_type_number(&data.data, self.options.correct_level));
109 }
110 self.type_number = type_num;
111 }
112
113 self.module_count = self.type_number * 4 + 17;
114 self.modules = vec![vec![None; self.module_count as usize]; self.module_count as usize];
115
116 self.setup_position_probe_pattern(0, 0);
117 self.setup_position_probe_pattern(self.module_count - 7, 0);
118 self.setup_position_probe_pattern(0, self.module_count - 7);
119 self.setup_position_adjust_pattern();
120 self.setup_timing_pattern();
121 self.setup_type_info(test);
122
123 if self.type_number >= 7 {
124 self.setup_type_number(test);
125 }
126
127 if self.data_cache.is_none() {
128 self.data_cache = Some(self.create_data());
129 }
130
131 let data = self.data_cache.as_ref().unwrap().clone();
132 self.map_data(&data);
133 }
134
135 fn setup_position_probe_pattern(&mut self, row: i32, col: i32) {
136 for r in -1..=7 {
137 if row + r <= -1 || self.module_count <= row + r {
138 continue;
139 }
140 for c in -1..=7 {
141 if col + c <= -1 || self.module_count <= col + c {
142 continue;
143 }
144 let is_dark = ((0..=6).contains(&r) && (c == 0 || c == 6))
145 || ((0..=6).contains(&c) && (r == 0 || r == 6))
146 || ((2..=4).contains(&r) && (2..=4).contains(&c));
147 self.modules[(row + r) as usize][(col + c) as usize] = Some(is_dark);
148 }
149 }
150 }
151
152 fn setup_position_adjust_pattern(&mut self) {
153 let pos = PATTERN_POSITION_TABLE[(self.type_number - 1) as usize];
154 for i in 0..pos.len() {
155 for j in 0..pos.len() {
156 let row = pos[i];
157 let col = pos[j];
158
159 if row == 0 || col == 0 {
161 continue;
162 }
163
164 if row <= 8 && col <= 8 {
168 continue; }
170 if row <= 8 && col >= self.module_count - 8 {
171 continue; }
173 if row >= self.module_count - 8 && col <= 8 {
174 continue; }
176
177 if self.modules[row as usize][col as usize].is_some() {
179 continue;
180 }
181
182 for r in -2..=2 {
183 for c in -2..=2 {
184 let new_row = row + r;
185 let new_col = col + c;
186 if new_row < 0
188 || new_row >= self.module_count
189 || new_col < 0
190 || new_col >= self.module_count
191 {
192 continue;
193 }
194 let is_dark = r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0);
195 self.modules[new_row as usize][new_col as usize] = Some(is_dark);
196 }
197 }
198 }
199 }
200 }
201
202 fn setup_timing_pattern(&mut self) {
203 for r in 8..self.module_count - 8 {
204 if self.modules[r as usize][6].is_none() {
205 self.modules[r as usize][6] = Some(r % 2 == 0);
206 }
207 }
208 for c in 8..self.module_count - 8 {
209 if self.modules[6][c as usize].is_none() {
210 self.modules[6][c as usize] = Some(c % 2 == 0);
211 }
212 }
213 }
214
215 fn setup_type_info(&mut self, test: bool) {
216 let g15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
217 let g15_mask = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
218
219 let mask_pattern = 0; let correct_level = match self.options.correct_level {
221 QRErrorCorrectLevel::L => 1,
222 QRErrorCorrectLevel::M => 0,
223 QRErrorCorrectLevel::Q => 3,
224 QRErrorCorrectLevel::H => 2,
225 };
226
227 let mut data = (correct_level << 3) | mask_pattern;
228 let mut d = data << 10;
229
230 while get_bch_digit(d) - get_bch_digit(g15) >= 0 {
231 d ^= g15 << (get_bch_digit(d) - get_bch_digit(g15));
232 }
233
234 data = ((data << 10) | d) ^ g15_mask;
235
236 for i in 0..15 {
238 let bit = !test && ((data >> i) & 1) == 1;
240
241 if i < 6 {
242 self.modules[i as usize][8] = Some(bit);
244 } else if i < 8 {
245 self.modules[(i + 1) as usize][8] = Some(bit);
247 } else {
248 self.modules[(self.module_count - 15 + i) as usize][8] = Some(bit);
250 }
251 }
252
253 for i in 0..15 {
255 let bit = !test && ((data >> i) & 1) == 1;
256
257 if i < 8 {
258 self.modules[8][(self.module_count - 1 - i) as usize] = Some(bit);
260 } else if i < 9 {
261 self.modules[8][(15 - i - 1 + 1) as usize] = Some(bit);
263 } else {
264 self.modules[8][(15 - i - 1) as usize] = Some(bit);
266 }
267 }
268
269 self.modules[(self.module_count - 8) as usize][8] = Some(!test);
271 }
272
273 fn setup_type_number(&mut self, _test: bool) {
274 }
276
277 fn map_data(&mut self, data: &[i32]) {
278 let mut inc = -1;
279 let mut row = self.module_count - 1;
280 let mut bit_index = 7;
281 let mut byte_index = 0;
282
283 let mut col = self.module_count - 1;
284 while col > 0 {
285 if col == 6 {
287 col -= 1;
288 }
289
290 loop {
291 for c in 0..2 {
292 let col_idx = col - c;
293 if col_idx < 0 || col_idx >= self.module_count {
294 continue;
295 }
296 if self.modules[row as usize][col_idx as usize].is_none() {
297 let mut dark = false;
298 if byte_index < data.len() {
299 dark = ((data[byte_index] >> bit_index) & 1) == 1;
300 }
301
302 let mask = (row + col_idx) % 2 == 0;
304 if mask {
305 dark = !dark;
306 }
307
308 self.modules[row as usize][col_idx as usize] = Some(dark);
309
310 if bit_index == 0 {
311 bit_index = 7;
312 byte_index += 1;
313 } else {
314 bit_index -= 1;
315 }
316 }
317 }
318
319 row += inc;
320
321 if row < 0 || self.module_count <= row {
322 row -= inc;
323 inc = -inc;
324 break;
325 }
326 }
327
328 col -= 2;
329 }
330 }
331
332 fn create_data(&self) -> Vec<i32> {
333 let rs_blocks = get_rs_blocks(self.type_number, self.options.correct_level);
334
335 let mut buffer = BitBuffer::new();
336
337 for data in &self.data_list {
338 buffer.put(QRMode::MODE_8BIT_BYTE, 4);
339 buffer.put(
340 data.get_length() as i32,
341 get_length_in_bits(QRMode::MODE_8BIT_BYTE, self.type_number),
342 );
343 data.write(&mut buffer);
344 }
345
346 let mut total_data_count = 0;
347 for block in &rs_blocks {
348 total_data_count += block.data_count;
349 }
350
351 if buffer.length + 4 <= total_data_count as usize * 8 {
352 buffer.put(0, 4);
353 }
354
355 while !buffer.length.is_multiple_of(8) {
356 buffer.put_bit(false);
357 }
358
359 loop {
360 if buffer.length >= total_data_count as usize * 8 {
361 break;
362 }
363 buffer.put(0xEC, 8);
364 if buffer.length >= total_data_count as usize * 8 {
365 break;
366 }
367 buffer.put(0x11, 8);
368 }
369
370 #[cfg(test)]
371 eprintln!(
372 "DEBUG: buffer.length={}, buffer.buffer.len={}, total_data_count*8={}",
373 buffer.length,
374 buffer.buffer.len(),
375 total_data_count as usize * 8
376 );
377
378 let data = buffer.buffer;
379
380 let mut offset = 0;
381 let max_dc_count = rs_blocks.iter().map(|b| b.data_count).max().unwrap_or(0);
382 let max_ec_count = rs_blocks
383 .iter()
384 .map(|b| b.total_count - b.data_count)
385 .max()
386 .unwrap_or(0);
387
388 let mut dcdata: Vec<Vec<i32>> = Vec::new();
389 let mut ecdata: Vec<Vec<i32>> = Vec::new();
390
391 for block in &rs_blocks {
392 let dc_count = block.data_count;
393 let ec_count = block.total_count - dc_count;
394
395 dcdata.push(data[offset as usize..(offset + dc_count) as usize].to_vec());
396 offset += dc_count;
397
398 let rs_poly = Polynomial::generate_rs_poly(ec_count);
402
403 let dc = dcdata.last().unwrap();
406 let mut raw_coeff = dc.clone();
407 raw_coeff.extend(std::iter::repeat_n(0, ec_count as usize));
408 let raw_poly = Polynomial::new(raw_coeff, 0);
409
410 let mod_poly = raw_poly.r#mod(&rs_poly);
412
413 let mut ec: Vec<i32> = Vec::with_capacity(ec_count as usize);
417 for i in 0..ec_count {
418 let mod_index = i + mod_poly.len() as i32 - ec_count;
419 let val = if mod_index >= 0 {
420 mod_poly.get(mod_index as usize)
421 } else {
422 0
423 };
424 #[cfg(test)]
425 if i < 5 {
426 eprintln!("DEBUG: ec[{}] = {} (mod_index={})", i, val, mod_index);
427 }
428 ec.push(val);
429 }
430 ecdata.push(ec);
431 }
432
433 let mut result: Vec<i32> = Vec::new();
434
435 for i in 0..max_dc_count {
436 for (_r, item) in dcdata.iter().enumerate().take(rs_blocks.len()) {
437 if i < item.len() as i32 {
438 result.push(item[i as usize]);
439 }
440 }
441 }
442
443 for i in 0..max_ec_count {
444 for (_r, item) in ecdata.iter().enumerate().take(rs_blocks.len()) {
445 if i < item.len() as i32 {
446 result.push(item[i as usize]);
447 }
448 }
449 }
450
451 result
452 }
453}
454
455impl QRCode {
456 pub fn get_svg(&self) -> String {
458 let count = self.module_count;
459 if count == 0 {
460 return String::new();
461 }
462
463 let size = 256;
464 let cell_size = size / count;
465 let actual_size = cell_size * count;
466 let offset = (size - actual_size) / 2;
467
468 let estimated_dark = (count * count) as usize / 2;
470 let mut svg = String::with_capacity(350 + estimated_dark * 25);
471
472 write!(
474 svg,
475 r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {0} {0}" width="{0}" height="{0}"><path d="M0 0h{0}v{0}H0z" fill="{1}"/><path fill="{2}" d=""#,
476 size, self.options.color_light, self.options.color_dark
477 ).unwrap();
478
479 let modules_flat: Vec<bool> = self
482 .modules
483 .iter()
484 .flat_map(|row| row.iter().map(|&m| m.unwrap_or(false)))
485 .collect();
486
487 let count_i32 = count;
488 for (idx, is_dark) in modules_flat.iter().enumerate() {
489 if *is_dark {
490 let row = (idx as i32) / count_i32;
491 let col = (idx as i32) % count_i32;
492 let x = col * cell_size + offset;
493 let y = row * cell_size + offset;
494 write!(svg, "M{x} {y}h{cell_size}v{cell_size}h-{cell_size}z").unwrap();
495 }
496 }
497
498 svg.push_str(r#""/></svg>"#);
499 svg
500 }
501}
502
503impl Default for QRCode {
504 fn default() -> Self {
505 Self::new()
506 }
507}