KReport

i2of5paint.cpp
1 /* This file is part of the KDE project
2  * Copyright (C) 2001-2012 by OpenMFG, LLC
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  * Please contact [email protected] with any questions on this license.
18  */
19 
20 /*
21  * This file contains the implementation of the interleaved 2 of 5 barcode renderer.
22  * All this code assumes a 100dpi rendering surface for it's calculations.
23  */
24 
25 #include <QString>
26 #include <QRectF>
27 #include <QPainter>
28 #include <QPen>
29 #include <QBrush>
30 
31 const char* __i2of5charmap[] = {
32  "NNWWN",
33  "WNNNW",
34  "NWNNW",
35  "WWNNN",
36  "NNWNW",
37  "WNWNN",
38  "NWWNN",
39  "NNNWW",
40  "WNNWN",
41  "NWNWN"
42 };
43 
44 
45 static QPointF addElement(const QRectF &r, QPointF startPos, qreal width, bool isSpace, QPainter * pPainter)
46 {
47  if (!isSpace && pPainter) {
48  pPainter->fillRect(startPos.x(),startPos.y(), width, r.height(), pPainter->pen().color());
49  }
50 
51  return QPointF(startPos.x() + width, startPos.y());
52 }
53 
54 static QPointF addBar(const QRectF &r, QPointF startPos, qreal width, QPainter * pPainter)
55 {
56  return addElement(r, startPos, width, false, pPainter);
57 }
58 static QPointF addSpace(const QRectF &r, QPointF startPos, qreal width, QPainter * pPainter)
59 {
60  return addElement(r, startPos, width, true, pPainter);
61 }
62 
63 
64 void renderI2of5(const QRectF &r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
65 {
66  QString str = _str;
67  qreal narrow_bar = 1; // a narrow bar is 1/100th inch wide
68  qreal bar_width_mult = 2.5; // the wide bar width multiple of the narrow bar
69  qreal wide_bar = narrow_bar * bar_width_mult;
70 
71  if (str.length() % 2) {
72  str = QLatin1Char('0')+ str; // padding zero if number of characters is not even
73  }
74 
75  // this is our mandatory minimum quiet zone
76  qreal quiet_zone = narrow_bar * 10;
77  if(quiet_zone < 0.1) {
78  quiet_zone = 0.1;
79  }
80 
81  // what kind of area do we have to work with
82  int draw_width = r.width();
83 
84  // how long is the value we need to encode?
85  int val_length = str.length();
86 
87  // L = (C(2N+3)+6+N)X
88  // L length of barcode (excluding quite zone
89  // C the number of characters in the value excluding the start/stop
90  // N the bar width multiple for wide bars
91  // X the width of a bar (pixels in our case)
92  int L;
93  int C = val_length;
94  qreal N = bar_width_mult;
95  qreal X = narrow_bar;
96 
97  L = (C * (2.0*N + 3.0) + 6.0 + N) * X;
98 
99  // now we have the actual width the barcode will be so can determine the actual
100  // size of the quiet zone (we assume we center the barcode in the given area)
101  // At the moment the way the code is written is we will always start at the minimum
102  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
103  // to the right
104  //
105  // calculate the starting position based on the alignment option
106  if (align == Qt::AlignHCenter) {
107  int nqz = (draw_width - L) / 2.0;
108  if (nqz > quiet_zone) {
109  quiet_zone = nqz;
110  }
111  }
112  else if (align == Qt::AlignRight) {
113  quiet_zone = draw_width - (L + quiet_zone);
114  }
115  // left : do nothing
116 
117  if (pPainter) {
118  pPainter->save();
119 
120  QPen oneWide(pPainter->pen());
121  oneWide.setWidth(1);
122 #ifndef Q_OS_WIN32
123  oneWide.setJoinStyle(Qt::MiterJoin);
124 #endif
125  pPainter->setPen(oneWide);
126  pPainter->setBrush(pPainter->pen().color());
127  }
128 
129  QPointF pos(r.left() + quiet_zone, r.top());
130 
131  // start character
132  pos = addBar(r, pos, narrow_bar,pPainter);
133  pos = addSpace(r, pos, narrow_bar, pPainter);
134  pos = addBar(r, pos, narrow_bar, pPainter);
135  pos = addSpace(r, pos, narrow_bar, pPainter);
136 
137  for (int i = 0; i < str.length()-1; i+=2) {
138  for (int iElt = 0; __i2of5charmap [0][iElt] != '\0'; iElt++) {
139  for (int offset=0; offset<=1; offset++) {
140  QChar c = str.at(i+offset);
141  if (!c.isDigit()) {
142  break; // invalid character
143  }
144 
145  int iChar = c.digitValue();
146  int width = __i2of5charmap[iChar][iElt] == 'W' ? wide_bar : narrow_bar;
147  pos = addElement(r, pos, width, offset==1, pPainter);
148  }
149  }
150  }
151 
152  // stop character
153  pos = addBar(r, pos, wide_bar, pPainter);
154  pos = addSpace(r, pos, narrow_bar, pPainter);
155  pos = addBar(r, pos, narrow_bar, pPainter);
156 }
qreal left() const const
typedef Alignment
void setPen(const QColor &color)
MiterJoin
bool isDigit() const const
const QPen & pen() const const
void fillRect(const QRectF &rectangle, const QBrush &brush)
int length() const const
int digitValue() const const
void setBrush(const QBrush &brush)
qreal top() const const
qreal x() const const
qreal y() const const
qreal width() const const
QColor color() const const
const QChar at(int position) const const
void save()
qreal height() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Feb 8 2023 04:21:47 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.