Prison

code39barcode.cpp
1 /*
2  SPDX-FileCopyrightText: 2011 Geoffry Song <[email protected]>
3 
4  SPDX-License-Identifier: MIT
5 */
6 
7 #include "code39barcode.h"
8 #include "barcodeutil.h"
9 #include <QChar>
10 
11 using namespace Prison;
12 
13 static QList<bool> sequenceForChar(ushort c)
14 {
15  switch (QChar::toUpper(c)) {
16  case '0':
17  return BarCodeUtil::barSequence("000110100");
18  case '1':
19  return BarCodeUtil::barSequence("100100001");
20  case '2':
21  return BarCodeUtil::barSequence("001100001");
22  case '3':
23  return BarCodeUtil::barSequence("101100000");
24  case '4':
25  return BarCodeUtil::barSequence("000110001");
26  case '5':
27  return BarCodeUtil::barSequence("100110000");
28  case '6':
29  return BarCodeUtil::barSequence("001110000");
30  case '7':
31  return BarCodeUtil::barSequence("000100101");
32  case '8':
33  return BarCodeUtil::barSequence("100100100");
34  case '9':
35  return BarCodeUtil::barSequence("001100100");
36  case 'A':
37  return BarCodeUtil::barSequence("100001001");
38  case 'B':
39  return BarCodeUtil::barSequence("001001001");
40  case 'C':
41  return BarCodeUtil::barSequence("101001000");
42  case 'D':
43  return BarCodeUtil::barSequence("000011001");
44  case 'E':
45  return BarCodeUtil::barSequence("100011000");
46  case 'F':
47  return BarCodeUtil::barSequence("001011000");
48  case 'G':
49  return BarCodeUtil::barSequence("000001101");
50  case 'H':
51  return BarCodeUtil::barSequence("100001100");
52  case 'I':
53  return BarCodeUtil::barSequence("001001100");
54  case 'J':
55  return BarCodeUtil::barSequence("000011100");
56  case 'K':
57  return BarCodeUtil::barSequence("100000011");
58  case 'L':
59  return BarCodeUtil::barSequence("001000011");
60  case 'M':
61  return BarCodeUtil::barSequence("101000010");
62  case 'N':
63  return BarCodeUtil::barSequence("000010011");
64  case 'O':
65  return BarCodeUtil::barSequence("100010010");
66  case 'P':
67  return BarCodeUtil::barSequence("001010010");
68  case 'Q':
69  return BarCodeUtil::barSequence("000000111");
70  case 'R':
71  return BarCodeUtil::barSequence("100000110");
72  case 'S':
73  return BarCodeUtil::barSequence("001000110");
74  case 'T':
75  return BarCodeUtil::barSequence("000010110");
76  case 'U':
77  return BarCodeUtil::barSequence("110000001");
78  case 'V':
79  return BarCodeUtil::barSequence("011000001");
80  case 'W':
81  return BarCodeUtil::barSequence("111000000");
82  case 'X':
83  return BarCodeUtil::barSequence("010010001");
84  case 'Y':
85  return BarCodeUtil::barSequence("110010000");
86  case 'Z':
87  return BarCodeUtil::barSequence("011010000");
88  case '-':
89  return BarCodeUtil::barSequence("010000101");
90  case '.':
91  return BarCodeUtil::barSequence("110000100");
92  case ' ':
93  return BarCodeUtil::barSequence("011000100");
94  case '$':
95  return BarCodeUtil::barSequence("010101000");
96  case '/':
97  return BarCodeUtil::barSequence("010100010");
98  case '+':
99  return BarCodeUtil::barSequence("010001010");
100  case '%':
101  return BarCodeUtil::barSequence("000101010");
102  default:
103  return QList<bool>(); // unknown character
104  }
105 }
106 
108  : AbstractBarcode(AbstractBarcode::OneDimension)
109 {
110 }
111 Code39Barcode::~Code39Barcode() = default;
112 
114 {
115  Q_UNUSED(size);
116  QList<bool> barcode;
117  // convert text into sequences of wide/narrow bars
118  {
119  // the guard sequence that goes on each end
120  const QList<bool> endSequence = BarCodeUtil::barSequence("010010100");
121  barcode += endSequence;
122  barcode += false;
123  // translate the string
124  const QString str = data().isEmpty() ? QString::fromLatin1(byteArrayData().constData(), byteArrayData().size()) : data();
125  for (int i = 0; i < str.size(); i++) {
126  QList<bool> b = sequenceForChar(str.at(i).unicode());
127  if (!b.empty()) {
128  barcode += b;
129  barcode += false; // add a narrow space between each character
130  }
131  }
132  // ending guard
133  barcode += endSequence;
134  }
135 
136  /*
137  calculate integer bar widths that fit inside `size'
138  each character has 6 narrow bars and 3 wide bars and there is a narrow bar between characters
139  restrictions:
140  *) smallWidth * 2 <= largeWidth <= smallWidth * 3
141  - in other words, the ratio largeWidth:smallWidth is between 3:1 and 2:1
142  *) wide * largeWidth + narrow * smallWidth <= size.width()
143  - the barcode has to fit within the given size
144  */
145  const int wide = barcode.count(true);
146  const int narrow = barcode.count(false);
147  // wide bar width
148  const int largeWidth = 2;
149  // narrow bar width
150  const int smallWidth = 1;
151  Q_ASSERT(largeWidth > smallWidth);
152 
153  const int quietZoneWidth = 10 * smallWidth;
154 
155  // one line of the result image
156  QVector<QRgb> line;
157  line.reserve(wide * largeWidth + narrow * smallWidth + 2 * quietZoneWidth);
158  line.insert(0, quietZoneWidth, backgroundColor().rgba());
159  for (int i = 0; i < barcode.size(); i++) {
160  const QRgb color = (((i & 1) == 0) ? foregroundColor() : backgroundColor()).rgba(); // alternate between foreground and background color
161  const int width = barcode.at(i) ? largeWidth : smallWidth;
162  for (int j = 0; j < width; j++) {
163  line.append(color);
164  }
165  }
166  line.insert(line.size(), quietZoneWidth, backgroundColor().rgba());
167 
168  // build the complete barcode
169  QImage ret(line.size(), 1, QImage::Format_ARGB32);
170  memcpy(ret.scanLine(0), line.data(), line.size() * sizeof(QRgb));
171  return ret;
172 }
int size() const const
void insert(int i, T &&value)
int count(const T &value) const const
void append(const T &value)
QChar toUpper() const const
T * data()
const QColor & backgroundColor() const
Code39Barcode()
creates a Code 39 generator
bool empty() const const
int size() const const
QImage paintImage(const QSizeF &size) override
This function generates the barcode.
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...
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.