7#include "code128barcode_p.h"
9#include "barcodeutil_p.h"
10#include "bitvector_p.h"
11#include "prison_debug.h"
25enum CodeSet : uint8_t {
32enum CodeSetOp : uint8_t {
43Code128Barcode::Code128Barcode()
44 : AbstractBarcodePrivate(
Barcode::OneDimension)
47Code128Barcode::~Code128Barcode() =
default;
49QImage Code128Barcode::paintImage()
51 const auto bits = encode(BarCodeUtil::asLatin1ByteArray(m_data));
52 const auto width = bits.size() + 2 * QuietZone;
55 img.fill(m_background);
57 for (
int i = 0; i < bits.size(); ++i) {
59 img.setPixel(QuietZone + i, 0, m_foreground.rgb());
67static const uint16_t code128_symbols[] = {
179static uint8_t symbolForCharacter(
const QByteArray &data,
int index, CodeSet set)
181 const auto c1 = data.
at(index);
184 return (c1 <
' ') ? c1 + 64 : c1 -
' ';
188 const auto c2 = data.
at(index + 1);
189 return ((c1 -
'0') * 10) + c2 -
'0';
199struct CodeSetChange {
204static bool isInCodeSetA(
char c)
209static bool isInCodeSetB(
char c)
215static CodeSetChange opForData(
const QByteArray &data,
int index, CodeSet currentSet)
219 for (
int i = index; i < data.
size(); ++i, ++codeC) {
220 if (data.
at(i) <
'0' || data.
at(i) >
'9') {
224 if (currentSet == CodeSetC && codeC >= 2) {
225 return {CodeSetC,
None};
228 || (index == 0 && codeC >= 4)
229 || (index + codeC == data.
size() && codeC >= 4)
230 || (codeC == data.
size() && codeC == 2)
231 || (codeC == data.
size() && codeC == 4))
233 return currentSet == CodeSetUnknown ? CodeSetChange{CodeSetC, StartC} : CodeSetChange{CodeSetC, LatchC};
238 if ((currentSet == CodeSetA && isInCodeSetA(data.
at(index))) || (currentSet == CodeSetB && isInCodeSetB(data.
at(index)))) {
239 return {currentSet,
None};
243 const auto nextA = isInCodeSetA(data.
at(index));
244 const auto nextB = isInCodeSetB(data.
at(index));
248 for (
int i = index + 1; i < data.
size(); ++i, ++countA) {
249 if (!isInCodeSetA(data.
at(i))) {
254 for (
int i = index + 1; i < data.
size(); ++i, ++countB) {
255 if (!isInCodeSetB(data.
at(i))) {
261 switch (currentSet) {
264 if (nextA && nextB) {
265 return countA > countB ? CodeSetChange{CodeSetA, StartA} : CodeSetChange{CodeSetB, StartB};
267 return nextA ? CodeSetChange{CodeSetA, StartA} : CodeSetChange{CodeSetB, StartB};
270 if (nextA && nextB) {
271 return countA > countB ? CodeSetChange{CodeSetA, LatchA} : CodeSetChange{CodeSetB, LatchB};
273 return nextA ? CodeSetChange{CodeSetA, LatchA} : CodeSetChange{CodeSetB, LatchB};
276 return CodeSetChange{CodeSetB, countB >= countA ? LatchB : Shift};
279 return CodeSetChange{CodeSetA, countA > countB ? LatchA : Shift};
283 return CodeSetChange{currentSet,
None};
286BitVector Code128Barcode::encode(
const QByteArray &data)
const
294 const auto op = opForData(data, 0, CodeSetUnknown);
295 auto currentSet = op.set;
298 qCDebug(
Log) <<
"start symbol:" << op.symbol << code128_symbols[op.symbol];
299 v.appendMSB(code128_symbols[op.symbol], SymbolSize);
301 uint32_t checksum = op.symbol;
302 uint32_t checksumWeight = 1;
304 for (
int i = 0; i < data.
size(); i += currentSet == CodeSetC ? 2 : 1) {
305 if (
static_cast<uint8_t
>(data.
at(i)) > 127) {
310 const auto op = opForData(data, i, currentSet);
311 if (op.symbol != None) {
312 qCDebug(
Log) <<
"op symbol:" << op.symbol << code128_symbols[op.symbol];
313 v.appendMSB(code128_symbols[op.symbol], SymbolSize);
314 checksum += op.symbol * checksumWeight++;
318 const auto symbol = symbolForCharacter(data, i, op.set);
319 qCDebug(
Log) <<
"data symbol:" << symbol << code128_symbols[symbol];
320 v.appendMSB(code128_symbols[symbol], SymbolSize);
321 checksum += symbol * checksumWeight++;
324 if (op.symbol != Shift) {
330 qCDebug(
Log) <<
"checksum:" << checksum << code128_symbols[checksum % 103];
331 v.appendMSB(code128_symbols[checksum % 103], SymbolSize);
334 v.appendMSB(code128_symbols[StopPattern], StopPatternSize);
A barcode generator for a fixed barcode format.
Provides classes and methods for generating barcodes.
char at(qsizetype i) const const
bool isEmpty() const const
qsizetype size() const const