1use krilla::{
74 color::luma,
75 geom::{PathBuilder, Point, Transform},
76 num::NormalizedF32,
77 paint::Fill,
78 surface::Surface
79};
80use rxing::{
81 aztec::AztecWriter, common::BitMatrix, datamatrix::DataMatrixWriter,
82 pdf417::PDF417Writer, qrcode::QRCodeWriter, BarcodeFormat, Writer
83};
84
85pub type Result<T = (), E = rxing::Exceptions> = std::result::Result<T, E>;
86
87pub struct Barcode {
88 bit_matrix: BitMatrix,
89 bit_size: f32,
90 border: f32
91}
92
93impl Barcode {
94 fn new(bit_matrix: BitMatrix, width: f32, border: f32) -> Self {
97 Self {
98 border,
99 bit_size: width / (bit_matrix.width() as f32 + 2.0 * border),
100 bit_matrix
101 }
102 }
103
104 pub fn new_aztec(text: &str, width: f32) -> Result<Self> {
106 let bit_matrix = AztecWriter.encode(text, &BarcodeFormat::AZTEC, 0, 0)?;
107 Ok(Self::new(bit_matrix, width, 0.0))
108 }
109
110 pub fn new_data_matrix(text: &str, width: f32) -> Result<Self> {
112 let bit_matrix =
113 DataMatrixWriter.encode(text, &BarcodeFormat::DATA_MATRIX, 0, 0)?;
114 Ok(Self::new(bit_matrix, width, 1.0))
115 }
116
117 pub fn new_pdf417(text: &str, width: f32) -> Result<Self> {
119 let bit_matrix = PDF417Writer.encode(text, &BarcodeFormat::PDF_417, 0, 0)?;
120 Ok(Self::new(bit_matrix, width, 0.0))
121 }
122
123 pub fn new_qr_code(text: &str, width: f32) -> Result<Self> {
125 let bit_matrix = QRCodeWriter.encode(text, &BarcodeFormat::QR_CODE, 0, 0)?;
126 Ok(Self::new(bit_matrix, width, 0.0))
127 }
128
129 pub fn width(&self) -> f32 {
132 self.bit_size * (self.bit_matrix.width() as f32 + 2.0 * self.border)
133 }
134
135 pub fn height(&self) -> f32 {
138 self.bit_size * (self.bit_matrix.height() as f32 + 2.0 * self.border)
139 }
140}
141
142struct RleBits {
145 x: u32,
146 y: u32,
147 w: u32,
148 h: u32
149}
150
151struct Rle {
154 bits: Vec<RleBits>
155}
156
157impl Rle {
158 fn new_horiz(bit_matrix: &BitMatrix) -> Self {
160 let mut bits = Vec::new();
161 let mut y = 0;
162 for row in 0 .. bit_matrix.height() {
163 let mut x = 0;
164 let mut col = 0;
165 while col < bit_matrix.width() {
166 if !bit_matrix.get(col, row) {
167 col += 1;
168 x += 1;
169 continue;
170 }
171 let col_start = col;
172 while col < bit_matrix.width() && bit_matrix.get(col, row) {
173 col += 1;
174 }
175 let colspan = col - col_start;
176 bits.push(RleBits {
177 x,
178 y,
179 w: colspan,
180 h: 1
181 });
182 x += colspan;
183 }
184 y += 1;
185 }
186 Self { bits }
187 }
188
189 fn new_vert(bit_matrix: &BitMatrix) -> Self {
191 let mut bits = Vec::new();
192 let mut x = 0;
193 for col in 0 .. bit_matrix.width() {
194 let mut y = 0;
195 let mut row = 0;
196 while row < bit_matrix.height() {
197 if !bit_matrix.get(col, row) {
198 row += 1;
199 y += 1;
200 continue;
201 }
202 let row_start = row;
203 while row < bit_matrix.height() && bit_matrix.get(col, row) {
204 row += 1;
205 }
206 let rowspan = row - row_start;
207 bits.push(RleBits {
208 x,
209 y,
210 w: 1,
211 h: rowspan
212 });
213 y += rowspan;
214 }
215 x += 1;
216 }
217 Self { bits }
218 }
219
220 fn len(&self) -> usize {
222 self.bits.len()
223 }
224}
225
226impl Barcode {
227 fn draw(&self, surface: &mut Surface<'_>, x: f32, y: f32) {
229 let width = self.bit_matrix.width() as f32 + 2.0 * self.border;
230 let height = self.bit_matrix.height() as f32 + 2.0 * self.border;
231
232 surface.push_transform(&Transform::from_translate(x, y));
237 surface.push_transform(&Transform::from_scale(self.bit_size, self.bit_size));
238
239 surface.set_stroke(None);
241 surface.set_fill(Some(Fill {
242 paint: luma::Color::white().into(),
243 opacity: NormalizedF32::new(0.9).unwrap(),
244 ..Default::default()
245 }));
246 let mut bg = PathBuilder::new();
247 bg.move_to(0.0, 0.0);
248 bg.line_to(width, 0.0);
249 bg.line_to(width, height);
250 bg.line_to(0.0, height);
251 bg.close();
252 let bg = bg.finish().unwrap();
253 surface.draw_path(&bg);
254
255 surface.set_stroke(None);
257 surface.set_fill(Some(Fill {
258 paint: luma::Color::black().into(),
259 ..Default::default()
260 }));
261
262 let rle_horiz = Rle::new_horiz(&self.bit_matrix);
265 let rle_vert = Rle::new_vert(&self.bit_matrix);
266 let rle = if rle_horiz.len() > rle_vert.len() {
267 rle_vert
268 } else {
269 rle_horiz
270 };
271
272 for bit in rle.bits {
274 surface.push_transform(&Transform::from_translate(
275 self.border + bit.x as f32,
276 self.border + bit.y as f32
277 ));
278 let mut path = PathBuilder::new();
279 path.move_to(0.0, 0.0);
280 path.line_to(bit.w as f32, 0.0);
281 path.line_to(bit.w as f32, bit.h as f32);
282 path.line_to(0.0, bit.h as f32);
283 path.close();
284 let path = path.finish().unwrap();
285 surface.draw_path(&path);
286 surface.pop();
287 }
288
289 surface.pop();
291 surface.pop();
292 }
293}
294
295pub trait SurfaceExt {
307 fn draw_aztec(&mut self, text: &str, top_left: Point, width: f32) -> Result {
309 let barcode = Barcode::new_aztec(text, width)?;
310 self.draw_barcode(&barcode, top_left);
311 Ok(())
312 }
313
314 fn draw_data_matrix(&mut self, text: &str, top_left: Point, width: f32) -> Result {
316 let barcode = Barcode::new_data_matrix(text, width)?;
317 self.draw_barcode(&barcode, top_left);
318 Ok(())
319 }
320
321 fn draw_pdf417(&mut self, text: &str, top_left: Point, width: f32) -> Result {
323 let barcode = Barcode::new_pdf417(text, width)?;
324 self.draw_barcode(&barcode, top_left);
325 Ok(())
326 }
327
328 fn draw_qr_code(&mut self, text: &str, top_left: Point, width: f32) -> Result {
330 let barcode = Barcode::new_qr_code(text, width)?;
331 self.draw_barcode(&barcode, top_left);
332 Ok(())
333 }
334
335 fn draw_barcode(&mut self, barcode: &Barcode, top_left: Point);
336}
337
338impl SurfaceExt for Surface<'_> {
339 fn draw_barcode(&mut self, barcode: &Barcode, top_left: Point) {
340 barcode.draw(self, top_left.x, top_left.y);
341 }
342}