qrcode_generator_evcxr/
lib.rs1pub use qrcode_generator::QrCodeEcc;
2
3pub trait QrCodeable {
5 fn to_matrix(&self, ec_level: QrCodeEcc) -> Vec<Vec<bool>>;
6}
7
8impl QrCodeable for str {
9 fn to_matrix(&self, ec_level: QrCodeEcc) -> Vec<Vec<bool>> {
10 qrcode_generator::to_matrix_from_str(self, ec_level)
11 .expect("Failed to generate QR code matrix")
12 }
13}
14
15impl QrCodeable for String {
16 fn to_matrix(&self, ec_level: QrCodeEcc) -> Vec<Vec<bool>> {
17 qrcode_generator::to_matrix_from_str(self, ec_level)
18 .expect("Failed to generate QR code matrix")
19 }
20}
21
22impl QrCodeable for Vec<Vec<bool>> {
23 fn to_matrix(&self, _ec_level: QrCodeEcc) -> Vec<Vec<bool>> {
24 self.clone()
25 }
26}
27
28impl<T: QrCodeable + ?Sized> QrCodeable for &T {
30 fn to_matrix(&self, ec_level: QrCodeEcc) -> Vec<Vec<bool>> {
31 (**self).to_matrix(ec_level)
32 }
33}
34
35pub struct QrConfig {
37 pub ec_level: QrCodeEcc,
39 pub size: usize,
41 pub margin: usize,
43}
44
45impl Default for QrConfig {
46 fn default() -> Self {
47 QrConfig {
48 ec_level: QrCodeEcc::Medium,
49 size: 256,
50 margin: 4,
51 }
52 }
53}
54
55pub fn render_svg(matrix: &[Vec<bool>], size: usize, margin: usize) -> String {
61 let data_modules = matrix.len();
62 let total_modules = data_modules + 2 * margin;
63
64 if total_modules == 0 {
65 return format!(
66 "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{size}\" height=\"{size}\"></svg>"
67 );
68 }
69
70 let cell_size = size as f64 / total_modules as f64;
71
72 let mut svg = format!(
73 "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{size}\" height=\"{size}\" \
74 viewBox=\"0 0 {size} {size}\">\
75 <rect width=\"{size}\" height=\"{size}\" fill=\"white\"/>"
76 );
77
78 for (row_idx, row) in matrix.iter().enumerate() {
79 for (col_idx, &cell) in row.iter().enumerate() {
80 if cell {
81 let x = ((col_idx + margin) as f64 * cell_size).round() as usize;
82 let y = ((row_idx + margin) as f64 * cell_size).round() as usize;
83 let w = (((col_idx + margin + 1) as f64 * cell_size).round() as usize) - x;
84 let h = (((row_idx + margin + 1) as f64 * cell_size).round() as usize) - y;
85 svg.push_str(&format!(
86 "<rect x=\"{x}\" y=\"{y}\" width=\"{w}\" height=\"{h}\" fill=\"black\"/>"
87 ));
88 }
89 }
90 }
91
92 svg.push_str("</svg>");
93 svg
94}
95
96pub fn draw_qrcode(input: impl QrCodeable) {
100 draw_qrcode_with_config(input, QrConfig::default());
101}
102
103pub fn draw_qrcode_with_config(input: impl QrCodeable, config: QrConfig) {
107 let matrix = input.to_matrix(config.ec_level);
108 let svg = render_svg(&matrix, config.size, config.margin);
109 println!("EVCXR_BEGIN_CONTENT image/svg+xml");
110 println!("{}", svg);
111 println!("EVCXR_END_CONTENT");
112}