KReport

3of9paint.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 <QString>
25 #include <QPainter>
26 #include <QPen>
27 #include <QBrush>
28 
29 #include "kreportplugin_debug.h"
30 
31 struct code3of9 {
32  char code;
33  int values[9];
34 };
35 
36 const struct code3of9 _3of9codes[] = {
37  { '0', { 0, 0, 0, 1, 1, 0, 1, 0, 0 } },
38  { '1', { 1, 0, 0, 1, 0, 0, 0, 0, 1 } },
39  { '2', { 0, 0, 1, 1, 0, 0, 0, 0, 1 } },
40  { '3', { 1, 0, 1, 1, 0, 0, 0, 0, 0 } },
41  { '4', { 0, 0, 0, 1, 1, 0, 0, 0, 1 } },
42  { '5', { 1, 0, 0, 1, 1, 0, 0, 0, 0 } },
43  { '6', { 0, 0, 1, 1, 1, 0, 0, 0, 0 } },
44  { '7', { 0, 0, 0, 1, 0, 0, 1, 0, 1 } },
45  { '8', { 1, 0, 0, 1, 0, 0, 1, 0, 0 } },
46  { '9', { 0, 0, 1, 1, 0, 0, 1, 0, 0 } },
47 
48  { 'A', { 1, 0, 0, 0, 0, 1, 0, 0, 1 } },
49  { 'B', { 0, 0, 1, 0, 0, 1, 0, 0, 1 } },
50  { 'C', { 1, 0, 1, 0, 0, 1, 0, 0, 0 } },
51  { 'D', { 0, 0, 0, 0, 1, 1, 0, 0, 1 } },
52  { 'E', { 1, 0, 0, 0, 1, 1, 0, 0, 0 } },
53  { 'F', { 0, 0, 1, 0, 1, 1, 0, 0, 0 } },
54  { 'G', { 0, 0, 0, 0, 0, 1, 1, 0, 1 } },
55  { 'H', { 1, 0, 0, 0, 0, 1, 1, 0, 0 } },
56  { 'I', { 0, 0, 1, 0, 0, 1, 1, 0, 0 } },
57  { 'J', { 0, 0, 0, 0, 1, 1, 1, 0, 0 } },
58  { 'K', { 1, 0, 0, 0, 0, 0, 0, 1, 1 } },
59  { 'L', { 0, 0, 1, 0, 0, 0, 0, 1, 1 } },
60  { 'M', { 1, 0, 1, 0, 0, 0, 0, 1, 0 } },
61  { 'N', { 0, 0, 0, 0, 1, 0, 0, 1, 1 } },
62  { 'O', { 1, 0, 0, 0, 1, 0, 0, 1, 0 } },
63  { 'P', { 0, 0, 1, 0, 1, 0, 0, 1, 0 } },
64  { 'Q', { 0, 0, 0, 0, 0, 0, 1, 1, 1 } },
65  { 'R', { 1, 0, 0, 0, 0, 0, 1, 1, 0 } },
66  { 'S', { 0, 0, 1, 0, 0, 0, 1, 1, 0 } },
67  { 'T', { 0, 0, 0, 0, 1, 0, 1, 1, 0 } },
68  { 'U', { 1, 1, 0, 0, 0, 0, 0, 0, 1 } },
69  { 'V', { 0, 1, 1, 0, 0, 0, 0, 0, 1 } },
70  { 'W', { 1, 1, 1, 0, 0, 0, 0, 0, 0 } },
71  { 'X', { 0, 1, 0, 0, 1, 0, 0, 0, 1 } },
72  { 'Y', { 1, 1, 0, 0, 1, 0, 0, 0, 0 } },
73  { 'Z', { 0, 1, 1, 0, 1, 0, 0, 0, 0 } },
74 
75  { '-', { 0, 1, 0, 0, 0, 0, 1, 0, 1 } },
76  { '.', { 1, 1, 0, 0, 0, 0, 1, 0, 0 } },
77  { ' ', { 0, 1, 1, 0, 0, 0, 1, 0, 0 } },
78  { '$', { 0, 1, 0, 1, 0, 1, 0, 0, 0 } },
79  { '/', { 0, 1, 0, 1, 0, 0, 0, 1, 0 } },
80  { '+', { 0, 1, 0, 0, 0, 1, 0, 1, 0 } },
81  { '%', { 0, 0, 0, 1, 0, 1, 0, 1, 0 } },
82 
83  { '*', { 0, 1, 0, 0, 1, 0, 1, 0, 0 } }, // this is a special start/stop character
84 
85  { '\0', { 0, 0, 0, 0, 0, 0, 0, 0, 0 } } // null termininator of list
86 };
87 
88 int codeIndexP(QChar code)
89 {
90  // we are a case insensitive search
91  const char latin1Code = code.toUpper().toLatin1();
92  for (int idx = 0; _3of9codes[idx].code != '\0'; idx++) {
93  if (_3of9codes[idx].code == latin1Code) return idx;
94  }
95  return -1; // couldn't find it
96 }
97 
98 void render3of9(const QRect & r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
99 {
100  QString str = _str;
101  // lets determine some core attributes about this barcode
102  int narrow_bar = 1; // a narrow bar is 1px wide
103  int interchange_gap = narrow_bar; // the space between each 'set' of bars
104  int bar_width_mult = 2; // the wide bar width multiple of the narrow bar
105 
106  // this is are mandatory minimum quiet zone
107  int quiet_zone = narrow_bar * 10;
108  //if (quiet_zone < 10) quiet_zone = 10;
109 
110  // what kind of area do we have to work with
111  int draw_width = r.width();
112  int draw_height = r.height();
113 
114  // how long is the value we need to encode?
115  int val_length = str.length();
116 
117  // L = (C + 2)(3N + 6)X + (C + 1)I
118  // L length of barcode (excluding quite zone) in units same as X and I
119  // C the number of characters in the value excluding the start/stop
120  // N the bar width multiple for wide bars
121  // X the width of a bar (pixels in our case)
122  // I the interchange gap in the same units as X (value is same as X for our case)
123  int L;
124 
125  int C = val_length;
126  int N = bar_width_mult;
127  int X = narrow_bar;
128  int I = interchange_gap;
129 
130  L = ((C + 2) * (3 * N + 6) * X) + ((C + 1) * I);
131 
132  // now we have the actual width the barcode will be so can determine the actual
133  // size of the quiet zone (we assume we center the barcode in the given area
134  // what should we do if the area is too small????
135  // At the moment the way the code is written is we will always start at the minimum
136  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
137  // to the right
138  //
139  // calculate the starting position based on the alignment option
140  // for left align we don't need to do anything as the values are already setup for it
141  if (align == Qt::AlignHCenter) {
142  int nqz = (draw_width - L) / 2;
143  if (nqz > quiet_zone) quiet_zone = nqz;
144  } else if (align == Qt::AlignRight) {
145  quiet_zone = draw_width - (L + quiet_zone);
146  }
147  // left : do nothing
148 
149  int pos = r.left() + quiet_zone;
150  int top = r.top();
151 
152  // ok we need to prepend and append the str with a *
153  str = QLatin1Char('*') + str + QLatin1Char('*');
154 
155  if (pPainter) {
156  pPainter->save();
157 
158  QPen oneWide(pPainter->pen());
159  oneWide.setWidth(1);
160 #ifndef Q_OS_WIN32
161  oneWide.setJoinStyle(Qt::MiterJoin);
162 #endif
163  pPainter->setPen(oneWide);
164  pPainter->setBrush(pPainter->pen().color());
165  }
166  for (int i = 0; i < str.length(); i++) {
167  // loop through each char and render the barcode
168  QChar c = str.at(i);
169  int idx = codeIndexP(c);
170  if (idx == -1) {
171  kreportpluginWarning() << "Encountered a non-compliant character while rendering a 3of9 barcode -- skipping";
172  continue;
173  }
174 
175  bool space = false;
176  for (int b = 0; b < 9; b++, space = !space) {
177  int w = (_3of9codes[idx].values[b] == 1 ? narrow_bar * bar_width_mult : narrow_bar);
178  if (!space && pPainter) {
179  pPainter->fillRect(pos, top, w, draw_height, pPainter->pen().color());
180  }
181  pos += w;
182  }
183  pos += interchange_gap;
184  }
185  if (pPainter) {
186  pPainter->restore();
187  }
188 }
typedef Alignment
void setPen(const QColor &color)
MiterJoin
QChar toUpper() const const
int width() const const
const QPen & pen() const const
void fillRect(const QRectF &rectangle, const QBrush &brush)
int left() const const
int top() const const
int length() const const
void setBrush(const QBrush &brush)
int height() const const
QColor color() const const
const QChar at(int position) const const
void restore()
void save()
char toLatin1() const const
QVector< V > values(const QMultiHash< K, V > &c)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:17:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.