Prison

code93barcode.cpp
1 /*
2  SPDX-FileCopyrightText: 2011 Geoffry Song <[email protected]>
3 
4  SPDX-License-Identifier: MIT
5 */
6 
7 #include "code93barcode.h"
8 #include "barcodeutil.h"
9 #include <QChar>
10 
11 using namespace Prison;
12 
13 // returns a list of 9 bar colors, where `true' means foreground and `false' means background color
14 static QList<bool> sequenceForID(int id)
15 {
16  switch (id) {
17  case 0:
18  return BarCodeUtil::barSequence("100010100"); // 0-9
19  case 1:
20  return BarCodeUtil::barSequence("101001000");
21  case 2:
22  return BarCodeUtil::barSequence("101000100");
23  case 3:
24  return BarCodeUtil::barSequence("101000010");
25  case 4:
26  return BarCodeUtil::barSequence("100101000");
27  case 5:
28  return BarCodeUtil::barSequence("100100100");
29  case 6:
30  return BarCodeUtil::barSequence("100100010");
31  case 7:
32  return BarCodeUtil::barSequence("101010000");
33  case 8:
34  return BarCodeUtil::barSequence("100010010");
35  case 9:
36  return BarCodeUtil::barSequence("100001010");
37  case 10:
38  return BarCodeUtil::barSequence("110101000"); // A-Z
39  case 11:
40  return BarCodeUtil::barSequence("110100100");
41  case 12:
42  return BarCodeUtil::barSequence("110100010");
43  case 13:
44  return BarCodeUtil::barSequence("110010100");
45  case 14:
46  return BarCodeUtil::barSequence("110010010");
47  case 15:
48  return BarCodeUtil::barSequence("110001010");
49  case 16:
50  return BarCodeUtil::barSequence("101101000");
51  case 17:
52  return BarCodeUtil::barSequence("101100100");
53  case 18:
54  return BarCodeUtil::barSequence("101100010");
55  case 19:
56  return BarCodeUtil::barSequence("100110100");
57  case 20:
58  return BarCodeUtil::barSequence("100011010");
59  case 21:
60  return BarCodeUtil::barSequence("101011000");
61  case 22:
62  return BarCodeUtil::barSequence("101001100");
63  case 23:
64  return BarCodeUtil::barSequence("101000110");
65  case 24:
66  return BarCodeUtil::barSequence("100101100");
67  case 25:
68  return BarCodeUtil::barSequence("100010110");
69  case 26:
70  return BarCodeUtil::barSequence("110110100");
71  case 27:
72  return BarCodeUtil::barSequence("110110010");
73  case 28:
74  return BarCodeUtil::barSequence("110101100");
75  case 29:
76  return BarCodeUtil::barSequence("110100110");
77  case 30:
78  return BarCodeUtil::barSequence("110010110");
79  case 31:
80  return BarCodeUtil::barSequence("110011010");
81  case 32:
82  return BarCodeUtil::barSequence("101101100");
83  case 33:
84  return BarCodeUtil::barSequence("101100110");
85  case 34:
86  return BarCodeUtil::barSequence("100110110");
87  case 35:
88  return BarCodeUtil::barSequence("100111010");
89  case 36:
90  return BarCodeUtil::barSequence("100101110"); // -
91  case 37:
92  return BarCodeUtil::barSequence("111010100"); // .
93  case 38:
94  return BarCodeUtil::barSequence("111010010"); // space
95  case 39:
96  return BarCodeUtil::barSequence("111001010"); // $
97  case 40:
98  return BarCodeUtil::barSequence("101101110"); // /
99  case 41:
100  return BarCodeUtil::barSequence("101110110"); // +
101  case 42:
102  return BarCodeUtil::barSequence("110101110"); // $
103  case 43:
104  return BarCodeUtil::barSequence("100100110"); // ($)
105  case 44:
106  return BarCodeUtil::barSequence("111011010"); // (%)
107  case 45:
108  return BarCodeUtil::barSequence("111010110"); // (/)
109  case 46:
110  return BarCodeUtil::barSequence("100110010"); // (+)
111  case 47:
112  return BarCodeUtil::barSequence("101011110"); // stop sequence
113  default:
114  // unknown ID... shouldn't happen
115  qWarning("Code93Barcode::sequenceForID called with unknown ID");
116  return QList<bool>();
117  }
118 }
119 
120 // returns the list of IDs that represent a character
121 static QList<int> codesForChar(uint c)
122 {
123  QList<int> ret;
124  switch (c) {
125  case 0:
126  ret += 44;
127  ret += 30;
128  break;
129  case 1:
130  ret += 43;
131  ret += 10;
132  break;
133  case 2:
134  ret += 43;
135  ret += 11;
136  break;
137  case 3:
138  ret += 43;
139  ret += 12;
140  break;
141  case 4:
142  ret += 43;
143  ret += 13;
144  break;
145  case 5:
146  ret += 43;
147  ret += 14;
148  break;
149  case 6:
150  ret += 43;
151  ret += 15;
152  break;
153  case 7:
154  ret += 43;
155  ret += 16;
156  break;
157  case 8:
158  ret += 43;
159  ret += 17;
160  break;
161  case 9:
162  ret += 43;
163  ret += 18;
164  break;
165  case 10:
166  ret += 43;
167  ret += 19;
168  break;
169  case 11:
170  ret += 43;
171  ret += 20;
172  break;
173  case 12:
174  ret += 43;
175  ret += 21;
176  break;
177  case 13:
178  ret += 43;
179  ret += 22;
180  break;
181  case 14:
182  ret += 43;
183  ret += 23;
184  break;
185  case 15:
186  ret += 43;
187  ret += 24;
188  break;
189  case 16:
190  ret += 43;
191  ret += 25;
192  break;
193  case 17:
194  ret += 43;
195  ret += 26;
196  break;
197  case 18:
198  ret += 43;
199  ret += 27;
200  break;
201  case 19:
202  ret += 43;
203  ret += 28;
204  break;
205  case 20:
206  ret += 43;
207  ret += 29;
208  break;
209  case 21:
210  ret += 43;
211  ret += 30;
212  break;
213  case 22:
214  ret += 43;
215  ret += 31;
216  break;
217  case 23:
218  ret += 43;
219  ret += 32;
220  break;
221  case 24:
222  ret += 43;
223  ret += 33;
224  break;
225  case 25:
226  ret += 43;
227  ret += 34;
228  break;
229  case 26:
230  ret += 43;
231  ret += 35;
232  break;
233  case 27:
234  ret += 44;
235  ret += 10;
236  break;
237  case 28:
238  ret += 44;
239  ret += 11;
240  break;
241  case 29:
242  ret += 44;
243  ret += 12;
244  break;
245  case 30:
246  ret += 44;
247  ret += 13;
248  break;
249  case 31:
250  ret += 44;
251  ret += 14;
252  break;
253  case 32:
254  ret += 38;
255  break;
256  case 33:
257  ret += 45;
258  ret += 10;
259  break;
260  case 34:
261  ret += 45;
262  ret += 11;
263  break;
264  case 35:
265  ret += 45;
266  ret += 12;
267  break;
268  case 36:
269  ret += 39;
270  break;
271  case 37:
272  ret += 42;
273  break;
274  case 38:
275  ret += 45;
276  ret += 15;
277  break;
278  case 39:
279  ret += 45;
280  ret += 16;
281  break;
282  case 40:
283  ret += 45;
284  ret += 17;
285  break;
286  case 41:
287  ret += 45;
288  ret += 18;
289  break;
290  case 42:
291  ret += 45;
292  ret += 19;
293  break;
294  case 43:
295  ret += 41;
296  break;
297  case 44:
298  ret += 45;
299  ret += 21;
300  break;
301  case 45:
302  ret += 36;
303  break;
304  case 46:
305  ret += 37;
306  break;
307  case 47:
308  ret += 40;
309  break;
310  case 48:
311  ret += 0;
312  break;
313  case 49:
314  ret += 1;
315  break;
316  case 50:
317  ret += 2;
318  break;
319  case 51:
320  ret += 3;
321  break;
322  case 52:
323  ret += 4;
324  break;
325  case 53:
326  ret += 5;
327  break;
328  case 54:
329  ret += 6;
330  break;
331  case 55:
332  ret += 7;
333  break;
334  case 56:
335  ret += 8;
336  break;
337  case 57:
338  ret += 9;
339  break;
340  case 58:
341  ret += 45;
342  ret += 35;
343  break;
344  case 59:
345  ret += 44;
346  ret += 15;
347  break;
348  case 60:
349  ret += 44;
350  ret += 16;
351  break;
352  case 61:
353  ret += 44;
354  ret += 17;
355  break;
356  case 62:
357  ret += 44;
358  ret += 18;
359  break;
360  case 63:
361  ret += 44;
362  ret += 19;
363  break;
364  case 64:
365  ret += 44;
366  ret += 31;
367  break;
368  case 65:
369  ret += 10;
370  break;
371  case 66:
372  ret += 11;
373  break;
374  case 67:
375  ret += 12;
376  break;
377  case 68:
378  ret += 13;
379  break;
380  case 69:
381  ret += 14;
382  break;
383  case 70:
384  ret += 15;
385  break;
386  case 71:
387  ret += 16;
388  break;
389  case 72:
390  ret += 17;
391  break;
392  case 73:
393  ret += 18;
394  break;
395  case 74:
396  ret += 19;
397  break;
398  case 75:
399  ret += 20;
400  break;
401  case 76:
402  ret += 21;
403  break;
404  case 77:
405  ret += 22;
406  break;
407  case 78:
408  ret += 23;
409  break;
410  case 79:
411  ret += 24;
412  break;
413  case 80:
414  ret += 25;
415  break;
416  case 81:
417  ret += 26;
418  break;
419  case 82:
420  ret += 27;
421  break;
422  case 83:
423  ret += 28;
424  break;
425  case 84:
426  ret += 29;
427  break;
428  case 85:
429  ret += 30;
430  break;
431  case 86:
432  ret += 31;
433  break;
434  case 87:
435  ret += 32;
436  break;
437  case 88:
438  ret += 33;
439  break;
440  case 89:
441  ret += 34;
442  break;
443  case 90:
444  ret += 35;
445  break;
446  case 91:
447  ret += 44;
448  ret += 20;
449  break;
450  case 92:
451  ret += 44;
452  ret += 21;
453  break;
454  case 93:
455  ret += 44;
456  ret += 22;
457  break;
458  case 94:
459  ret += 44;
460  ret += 23;
461  break;
462  case 95:
463  ret += 44;
464  ret += 24;
465  break;
466  case 96:
467  ret += 44;
468  ret += 32;
469  break;
470  case 97:
471  ret += 46;
472  ret += 10;
473  break;
474  case 98:
475  ret += 46;
476  ret += 11;
477  break;
478  case 99:
479  ret += 46;
480  ret += 12;
481  break;
482  case 100:
483  ret += 46;
484  ret += 13;
485  break;
486  case 101:
487  ret += 46;
488  ret += 14;
489  break;
490  case 102:
491  ret += 46;
492  ret += 15;
493  break;
494  case 103:
495  ret += 46;
496  ret += 16;
497  break;
498  case 104:
499  ret += 46;
500  ret += 17;
501  break;
502  case 105:
503  ret += 46;
504  ret += 18;
505  break;
506  case 106:
507  ret += 46;
508  ret += 19;
509  break;
510  case 107:
511  ret += 46;
512  ret += 20;
513  break;
514  case 108:
515  ret += 46;
516  ret += 21;
517  break;
518  case 109:
519  ret += 46;
520  ret += 22;
521  break;
522  case 110:
523  ret += 46;
524  ret += 23;
525  break;
526  case 111:
527  ret += 46;
528  ret += 24;
529  break;
530  case 112:
531  ret += 46;
532  ret += 25;
533  break;
534  case 113:
535  ret += 46;
536  ret += 26;
537  break;
538  case 114:
539  ret += 46;
540  ret += 27;
541  break;
542  case 115:
543  ret += 46;
544  ret += 28;
545  break;
546  case 116:
547  ret += 46;
548  ret += 29;
549  break;
550  case 117:
551  ret += 46;
552  ret += 30;
553  break;
554  case 118:
555  ret += 46;
556  ret += 31;
557  break;
558  case 119:
559  ret += 46;
560  ret += 32;
561  break;
562  case 120:
563  ret += 46;
564  ret += 33;
565  break;
566  case 121:
567  ret += 46;
568  ret += 34;
569  break;
570  case 122:
571  ret += 46;
572  ret += 35;
573  break;
574  case 123:
575  ret += 44;
576  ret += 25;
577  break;
578  case 124:
579  ret += 44;
580  ret += 26;
581  break;
582  case 125:
583  ret += 44;
584  ret += 27;
585  break;
586  case 126:
587  ret += 44;
588  ret += 28;
589  break;
590  case 127:
591  ret += 44;
592  ret += 29;
593  break;
594  }
595  return ret; // return an empty list for a non-ascii character code
596 }
597 
598 // calculate a checksum
599 static int checksum(const QList<int> &codes, int wrap)
600 {
601  int check = 0;
602  for (int i = 0; i < codes.size(); i++) {
603  // weight goes from 1 to wrap, right-to-left, then repeats
604  const int weight = (codes.size() - i - 1) % wrap + 1;
605  check += codes.at(i) * weight;
606  }
607  return check % 47;
608 }
609 
611  : AbstractBarcode(AbstractBarcode::OneDimension)
612 {
613 }
614 Code93Barcode::~Code93Barcode() = default;
615 
617 {
618  Q_UNUSED(size);
619  QList<bool> barcode;
620  // convert text into sequences of fg/bg bars
621  {
622  // translate the string into a code sequence
623  QList<int> codes;
624  const QString str = data().isEmpty() ? QString::fromLatin1(byteArrayData().constData(), byteArrayData().size()) : data();
625  for (int i = 0; i < str.size(); i++) {
626  codes += codesForChar(str.at(i).unicode());
627  }
628 
629  // calculate checksums
630  codes.append(checksum(codes, 20)); // "C" checksum
631  codes.append(checksum(codes, 15)); // "K" checksum: includes previous checksum
632 
633  // now generate the barcode
634  // the guard sequence that goes on each end
635  const QList<bool> endSequence = sequenceForID(47);
636  barcode += endSequence;
637  // translate codes into bars
638  for (int i = 0; i < codes.size(); i++) {
639  barcode += sequenceForID(codes.at(i));
640  }
641  // ending guard
642  barcode += endSequence;
643  // termination bar
644  barcode += true;
645  }
646 
647  const int barWidth = 1;
648  const int quietZoneWidth = 10 * barWidth;
649 
650  // build one line of the result image
651  QVector<QRgb> line;
652  line.reserve(barWidth * barcode.size() + 2 * quietZoneWidth);
653  line.insert(0, quietZoneWidth, backgroundColor().rgba());
654  for (int i = 0; i < barcode.size(); i++) {
655  const QRgb color = (barcode.at(i) ? foregroundColor() : backgroundColor()).rgba();
656  for (int j = 0; j < barWidth; j++) {
657  line.append(color);
658  }
659  }
660  line.insert(line.size(), quietZoneWidth, backgroundColor().rgba());
661 
662  // build the complete barcode
663  QImage ret(line.size(), 1, QImage::Format_ARGB32);
664  memcpy(ret.scanLine(0), line.data(), line.size() * sizeof(QRgb));
665  return ret;
666 }
void append(const T &value)
QImage paintImage(const QSizeF &size) override
This function generates the barcode.
int size() const const
void insert(int i, T &&value)
void append(const T &value)
T * data()
const QColor & backgroundColor() const
int size() const const
bool isEmpty() const const
const T & at(int i) const const
void reserve(int size)
uchar * scanLine(int i)
base class for barcode generators To add your own barcode generator, subclass this class and reimplem...
Code93Barcode()
creates a Code 93 generator
QString fromLatin1(const char *str, int size)
QByteArray byteArrayData() const
Binary data encoded in this barcode.
const QChar at(int position) const const
int size() const const
const QColor & foregroundColor() const
QString data() const
Textual content encoded in this barcode.
QRgb rgba() const const
ushort unicode() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 03:59:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.