KReport

3of9.cpp
1 /* This file is part of the KDE project
2  * Copyright (C) 2001-2007 by OpenMFG, LLC ([email protected])
3  * Copyright (C) 2007-2008 by Adam Pigg ([email protected])
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 
32 struct code3of9 {
33  char code;
34  int values[9];
35 };
36 
37 const 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 
89 int 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 
100 void 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 }
qreal left() const const
typedef Alignment
QChar toUpper() const const
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
Defines a rectangle.
int length() const const
qreal top() const const
qreal width() const const
const QChar at(int position) const const
char toLatin1() const const
QVector< V > values(const QMultiHash< K, V > &c)
qreal height() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Sep 30 2023 04:06:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.