KReport

3of9.cpp
1/* This file is part of the KDE project
2 * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
3 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * This file contains the implementation of the 3of9 barcode renderer.
21 * All this code assumes a 100dpi rendering surface for it's calculations.
22 */
23
24#include "KReportRenderObjects.h"
25
26#include <QString>
27#include <QRectF>
28#include <QPen>
29#include <QBrush>
30#include "kreportplugin_debug.h"
31
32struct code3of9 {
33 char code;
34 int values[9];
35};
36
37const struct code3of9 _3of9codes[] = {
38 { '0', { 0, 0, 0, 1, 1, 0, 1, 0, 0 } },
39 { '1', { 1, 0, 0, 1, 0, 0, 0, 0, 1 } },
40 { '2', { 0, 0, 1, 1, 0, 0, 0, 0, 1 } },
41 { '3', { 1, 0, 1, 1, 0, 0, 0, 0, 0 } },
42 { '4', { 0, 0, 0, 1, 1, 0, 0, 0, 1 } },
43 { '5', { 1, 0, 0, 1, 1, 0, 0, 0, 0 } },
44 { '6', { 0, 0, 1, 1, 1, 0, 0, 0, 0 } },
45 { '7', { 0, 0, 0, 1, 0, 0, 1, 0, 1 } },
46 { '8', { 1, 0, 0, 1, 0, 0, 1, 0, 0 } },
47 { '9', { 0, 0, 1, 1, 0, 0, 1, 0, 0 } },
48
49 { 'A', { 1, 0, 0, 0, 0, 1, 0, 0, 1 } },
50 { 'B', { 0, 0, 1, 0, 0, 1, 0, 0, 1 } },
51 { 'C', { 1, 0, 1, 0, 0, 1, 0, 0, 0 } },
52 { 'D', { 0, 0, 0, 0, 1, 1, 0, 0, 1 } },
53 { 'E', { 1, 0, 0, 0, 1, 1, 0, 0, 0 } },
54 { 'F', { 0, 0, 1, 0, 1, 1, 0, 0, 0 } },
55 { 'G', { 0, 0, 0, 0, 0, 1, 1, 0, 1 } },
56 { 'H', { 1, 0, 0, 0, 0, 1, 1, 0, 0 } },
57 { 'I', { 0, 0, 1, 0, 0, 1, 1, 0, 0 } },
58 { 'J', { 0, 0, 0, 0, 1, 1, 1, 0, 0 } },
59 { 'K', { 1, 0, 0, 0, 0, 0, 0, 1, 1 } },
60 { 'L', { 0, 0, 1, 0, 0, 0, 0, 1, 1 } },
61 { 'M', { 1, 0, 1, 0, 0, 0, 0, 1, 0 } },
62 { 'N', { 0, 0, 0, 0, 1, 0, 0, 1, 1 } },
63 { 'O', { 1, 0, 0, 0, 1, 0, 0, 1, 0 } },
64 { 'P', { 0, 0, 1, 0, 1, 0, 0, 1, 0 } },
65 { 'Q', { 0, 0, 0, 0, 0, 0, 1, 1, 1 } },
66 { 'R', { 1, 0, 0, 0, 0, 0, 1, 1, 0 } },
67 { 'S', { 0, 0, 1, 0, 0, 0, 1, 1, 0 } },
68 { 'T', { 0, 0, 0, 0, 1, 0, 1, 1, 0 } },
69 { 'U', { 1, 1, 0, 0, 0, 0, 0, 0, 1 } },
70 { 'V', { 0, 1, 1, 0, 0, 0, 0, 0, 1 } },
71 { 'W', { 1, 1, 1, 0, 0, 0, 0, 0, 0 } },
72 { 'X', { 0, 1, 0, 0, 1, 0, 0, 0, 1 } },
73 { 'Y', { 1, 1, 0, 0, 1, 0, 0, 0, 0 } },
74 { 'Z', { 0, 1, 1, 0, 1, 0, 0, 0, 0 } },
75
76 { '-', { 0, 1, 0, 0, 0, 0, 1, 0, 1 } },
77 { '.', { 1, 1, 0, 0, 0, 0, 1, 0, 0 } },
78 { ' ', { 0, 1, 1, 0, 0, 0, 1, 0, 0 } },
79 { '$', { 0, 1, 0, 1, 0, 1, 0, 0, 0 } },
80 { '/', { 0, 1, 0, 1, 0, 0, 0, 1, 0 } },
81 { '+', { 0, 1, 0, 0, 0, 1, 0, 1, 0 } },
82 { '%', { 0, 0, 0, 1, 0, 1, 0, 1, 0 } },
83
84 { '*', { 0, 1, 0, 0, 1, 0, 1, 0, 0 } }, // this is a special start/stop character
85
86 { '\0', { 0, 0, 0, 0, 0, 0, 0, 0, 0 } } // null termininator of list
87};
88
89int codeIndex(QChar code)
90{
91 // we are a case insensitive search
92 const char latin1Code = code.toUpper().toLatin1();
93 for (int idx = 0; _3of9codes[idx].code != '\0'; idx++) {
94 if (_3of9codes[idx].code == latin1Code) return idx;
95 }
96 return -1; // couldn't find it
97}
98
99
100void render3of9(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
101{
102 QString str = _str;
103 // lets determine some core attributes about this barcode
104 qreal narrow_bar = 1; // a narrow bar is 1/100th inch wide
105 qreal interchange_gap = narrow_bar; // the space between each 'set' of bars
106 int bar_width_mult = 2; // the wide bar width multiple of the narrow bar
107
108 // this is our mandatory minimum quiet zone
109 qreal quiet_zone = narrow_bar * 10;
110 if (quiet_zone < 0.1)
111 quiet_zone = 0.1;
112
113 // what kind of area do we have to work with
114 qreal draw_width = r.width();
115 qreal draw_height = r.height();
116
117 // how long is the value we need to encode?
118 int val_length = str.length();
119
120 // L = (C + 2)(3N + 6)X + (C + 1)I
121 // L length of barcode (excluding quite zone) in units same as X and I
122 // C the number of characters in the value excluding the start/stop
123 // N the bar width multiple for wide bars
124 // X the width of a bar (pixels in our case)
125 // I the interchange gap in the same units as X (value is same as X for our case)
126 qreal L;
127
128 qreal C = val_length;
129 qreal N = bar_width_mult;
130 qreal X = narrow_bar;
131 qreal I = interchange_gap;
132
133 L = ((C + 2.0) * (3.0 * N + 6.0) * X) + ((C + 1.0) * I);
134
135 // now we have the actual width the barcode will be so can determine the actual
136 // size of the quiet zone (we assume we center the barcode in the given area
137 // what should we do if the area is too small????
138 // At the moment the way the code is written is we will always start at the minimum
139 // required quiet zone if we don't have enough space.... I guess we'll just have over-run
140 // to the right
141 //
142 // calculate the starting position based on the alignment option
143 // for left align we don't need to do anything as the values are already setup for it
144 if (align == Qt::AlignHCenter) {
145 qreal nqz = (draw_width - L) / 2.0;
146 if (nqz > quiet_zone)
147 quiet_zone = nqz;
148 } else if (align == Qt::AlignRight) {
149 quiet_zone = draw_width - (L + quiet_zone);
150 }
151 //else if(align < 1) {} // left : do nothing
152
153 qreal pos = r.left() + quiet_zone;
154 qreal top = r.top();
155
156 // ok we need to prepend and append the str with a *
157 //str = QString().sprintf("*%s*",(const char*)str);
158 str = QLatin1Char('*') + str + QLatin1Char('*');
159
160 QPen pen(Qt::NoPen);
161 QBrush brush(QColor("black"));
162 for (int i = 0; i < str.length(); i++) {
163 // loop through each char and render the barcode
164 QChar c = str.at(i);
165 int idx = codeIndex(c);
166 //kreportpluginDebug() << idx;
167 if (idx == -1) {
168 kreportpluginWarning() << "Encountered a non-compliant character while rendering a 3of9 barcode -- skipping";
169 continue;
170 }
171
172 bool space = false;
173 for (int b = 0; b < 9; b++, space = !space) {
174 qreal w = (_3of9codes[idx].values[b] == 1 ? narrow_bar * bar_width_mult : narrow_bar);
175 //kreportpluginDebug() << w << space;
176 if (!space) {
177 ORORect * rect = new ORORect();
178 rect->setPen(pen);
179 rect->setBrush(brush);
180 rect->setRect(QRectF(pos, top, w, draw_height));
181 page->insertPrimitive(rect);
182 }
183 pos += w;
184 }
185 pos += interchange_gap;
186 }
187}
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
Defines a rectangle.
char32_t toUpper(char32_t ucs4)
qreal height() const const
qreal left() const const
qreal top() const const
qreal width() const const
const QChar at(qsizetype position) const const
qsizetype length() const const
typedef Alignment
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:21:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.