Prison

code39barcode.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Geoffry Song <goffrie@gmail.com>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include "barcodeutil_p.h"
8#include "code39barcode_p.h"
9#include <QChar>
10
11using namespace Prison;
12
13static 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
107Code39Barcode::Code39Barcode()
108 : AbstractBarcodePrivate(Barcode::OneDimension)
109{
110}
111Code39Barcode::~Code39Barcode() = default;
112
113QImage Code39Barcode::paintImage()
114{
115 QList<bool> barcode;
116 // convert text into sequences of wide/narrow bars
117 {
118 // the guard sequence that goes on each end
119 const QList<bool> endSequence = BarCodeUtil::barSequence("010010100");
120 barcode += endSequence;
121 barcode += false;
122 // translate the string
123 const auto str = BarCodeUtil::asLatin1ByteArray(m_data);
124 for (int i = 0; i < str.size(); i++) {
125 QList<bool> b = sequenceForChar(str.at(i));
126 if (!b.empty()) {
127 barcode += b;
128 barcode += false; // add a narrow space between each character
129 }
130 }
131 // ending guard
132 barcode += endSequence;
133 }
134
135 /*
136 calculate integer bar widths that fit inside `size'
137 each character has 6 narrow bars and 3 wide bars and there is a narrow bar between characters
138 restrictions:
139 *) smallWidth * 2 <= largeWidth <= smallWidth * 3
140 - in other words, the ratio largeWidth:smallWidth is between 3:1 and 2:1
141 *) wide * largeWidth + narrow * smallWidth <= size.width()
142 - the barcode has to fit within the given size
143 */
144 const int wide = barcode.count(true);
145 const int narrow = barcode.count(false);
146 // wide bar width
147 const int largeWidth = 2;
148 // narrow bar width
149 const int smallWidth = 1;
150 Q_ASSERT(largeWidth > smallWidth);
151
152 const int quietZoneWidth = 10 * smallWidth;
153
154 // one line of the result image
155 QList<QRgb> line;
156 line.reserve(wide * largeWidth + narrow * smallWidth + 2 * quietZoneWidth);
157 line.insert(0, quietZoneWidth, m_background.rgba());
158 for (int i = 0; i < barcode.size(); i++) {
159 const QRgb color = (((i & 1) == 0) ? m_foreground : m_background).rgba(); // alternate between foreground and background color
160 const int width = barcode.at(i) ? largeWidth : smallWidth;
161 for (int j = 0; j < width; j++) {
162 line.append(color);
163 }
164 }
165 line.insert(line.size(), quietZoneWidth, m_background.rgba());
166
167 // build the complete barcode
168 QImage ret(line.size(), 1, QImage::Format_ARGB32);
169 memcpy(ret.scanLine(0), line.data(), line.size() * sizeof(QRgb));
170 return ret;
171}
A barcode generator for a fixed barcode format.
Definition barcode.h:40
Provides classes and methods for generating barcodes.
Definition barcode.h:24
QChar toUpper() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
pointer data()
bool empty() const const
iterator insert(const_iterator before, parameter_type value)
void reserve(qsizetype size)
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:16:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.