KReport

codeean.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 Code EAN and similar
21  * formats for rendering purposes. All this code assumes a 100dpi
22  * rendering surface for it's calculations.
23  */
24 
25 #include <QString>
26 #include <QRect>
27 #include <QPen>
28 #include <QBrush>
29 
30 #include "KReportRenderObjects.h"
31 
32 static const int LEFTHAND_ODD = 0;
33 static const int LEFTHAND_EVEN = 1;
34 static const int RIGHTHAND = 2;
35 
36 static const int _encodings[10][3][7] = {
37  /* LEFTHAND_ODD */ /* LEFTHAND_EVEN */ /* RIGHTHAND */
38  { { 0, 0, 0, 1, 1, 0, 1}, { 0, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0 } }, // 0
39  { { 0, 0, 1, 1, 0, 0, 1}, { 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0 } }, // 1
40  { { 0, 0, 1, 0, 0, 1, 1}, { 0, 0, 1, 1, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 0 } }, // 2
41  { { 0, 1, 1, 1, 1, 0, 1}, { 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1, 0 } }, // 3
42  { { 0, 1, 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1, 0, 1 }, { 1, 0, 1, 1, 1, 0, 0 } }, // 4
43  { { 0, 1, 1, 0, 0, 0, 1}, { 0, 1, 1, 1, 0, 0, 1 }, { 1, 0, 0, 1, 1, 1, 0 } }, // 5
44  { { 0, 1, 0, 1, 1, 1, 1}, { 0, 0, 0, 0, 1, 0, 1 }, { 1, 0, 1, 0, 0, 0, 0 } }, // 6
45  { { 0, 1, 1, 1, 0, 1, 1}, { 0, 0, 1, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1, 0, 0 } }, // 7
46  { { 0, 1, 1, 0, 1, 1, 1}, { 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 0, 1, 0, 0, 0 } }, // 8
47  { { 0, 0, 0, 1, 0, 1, 1}, { 0, 0, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 0, 0 } } // 9
48 };
49 
50 static const int odd = LEFTHAND_ODD;
51 static const int even = LEFTHAND_EVEN;
52 
53 static const int _parity[10][6] = {
54  { odd, odd, odd, odd, odd, odd }, // 0
55  { odd, odd, even, odd, even, even }, // 1
56  { odd, odd, even, even, odd, even }, // 2
57  { odd, odd, even, even, even, odd }, // 3
58  { odd, even, odd, odd, even, even }, // 4
59  { odd, even, even, odd, odd, even }, // 5
60  { odd, even, even, even, odd, odd }, // 6
61  { odd, even, odd, even, odd, even }, // 7
62  { odd, even, odd, even, even, odd }, // 8
63  { odd, even, even, odd, even, odd } // 9
64 };
65 
66 static const int _upcparenc[10][2][6] = {
67  /* PARITY 0 */ /* PARITY 1 */
68  { { even, even, even, odd, odd, odd }, { odd, odd, odd, even, even, even } }, // 0
69  { { even, even, odd, even, odd, odd }, { odd, odd, even, odd, even, even } }, // 1
70  { { even, even, odd, odd, even, odd }, { odd, odd, even, even, odd, even } }, // 2
71  { { even, even, odd, odd, odd, even }, { odd, odd, even, even, even, odd } }, // 3
72  { { even, odd, even, even, odd, odd }, { odd, even, odd, odd, even, even } }, // 4
73  { { even, odd, odd, even, even, odd }, { odd, even, even, odd, odd, even } }, // 5
74  { { even, odd, odd, odd, even, even }, { odd, even, even, even, odd, odd } }, // 6
75  { { even, odd, even, odd, even, odd }, { odd, even, odd, even, odd, even } }, // 7
76  { { even, odd, even, odd, odd, even }, { odd, even, odd, even, even, odd } }, // 8
77  { { even, odd, odd, even, odd, even }, { odd, even, even, odd, even, odd } } // 9
78 };
79 
80 
81 
82 //
83 //! @todo New Renderer Functions
84 ////////////////////////////////////////////////////////
85 
86 void renderCodeEAN13(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
87 {
88  int val[13];
89 
90  // initialize all the values just so we can be predictable
91  for (int i = 0; i < 13; ++i)
92  val[i] = -1;
93 
94  // verify that the passed in string is valid
95  // if it's not either twelve or thirteen characters
96  // then it must be invalid to begin with
97  if (_str.length() != 12 && _str.length() != 13)
98  return;
99  // loop through and convert each char to a digit.
100  // if we can't convert all characters then this is
101  // an invalid number
102  for (int i = 0; i < _str.length(); ++i) {
103  val[i] = ((QChar)_str.at(i)).digitValue();
104  if (val[i] == -1)
105  return;
106  }
107 
108  // calculate and append the checksum value
109  int old_sum = val[12]; // get the old check sum value (-1 if none was set)
110  int checksum = 0;
111  for (int i = 0; i < 12; ++i) {
112  checksum += val[i] * ((i % 2) ? 3 : 1);
113  }
114  checksum = (checksum % 10);
115  if (checksum) checksum = 10 - checksum;
116  val[12] = checksum;
117 
118  // if we had an old checksum value and if it doesn't match what we came
119  // up with then the string must be invalid so we will bail
120  if (old_sum != -1 && old_sum != checksum)
121  return;
122 
123 
124  // lets determine some core attributes about this barcode
125  qreal bar_width = 1; // the width of the base unit bar 1/100 inch
126 
127  // this is are mandatory minimum quiet zone
128  qreal quiet_zone = bar_width * 10;
129  if (quiet_zone < 10)
130  quiet_zone = 10;
131 
132  // what kind of area do we have to work with
133  qreal draw_width = r.width();
134  qreal draw_height = r.height() - 2;
135 
136  // L = 95X
137  // L length of barcode (excluding quite zone) in units same as X and I
138  // X the width of a bar (pixels in our case)
139  qreal L;
140 
141  qreal X = bar_width;
142 
143  L = (95.0 * X);
144 
145  // now we have the actual width the barcode will be so can determine the actual
146  // size of the quiet zone (we assume we center the barcode in the given area
147  // what should we do if the area is too small????
148  // At the moment the way the code is written is we will always start at the minimum
149  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
150  // to the right
151  //
152  // calculate the starting position based on the alignment option
153  // for left align we don't need to do anything as the values are already setup for it
154  if (align == Qt::AlignHCenter) {
155  qreal nqz = (draw_width - L) / 2;
156  if (nqz > quiet_zone)
157  quiet_zone = nqz;
158  } else if (align == Qt::AlignRight) {
159  quiet_zone = draw_width - (L + quiet_zone);
160  }
161  // left : do nothing
162 
163  qreal pos = r.left() + quiet_zone;
164  qreal top = r.top();
165 
166 
167  QPen pen(Qt::NoPen);
168  QBrush brush(QColor("black"));
169 
170  // render open guard
171  ORORect * rect = new ORORect();
172  rect->setPen(pen);
173  rect->setBrush(brush);
174  rect->setRect(QRectF(pos, top, bar_width, draw_height));
175  page->insertPrimitive(rect);
176 
177  pos += (bar_width * 2.0);
178 
179  rect = new ORORect();
180  rect->setPen(pen);
181  rect->setBrush(brush);
182  rect->setRect(QRectF(pos, top, bar_width, draw_height));
183  page->insertPrimitive(rect);
184 
185  pos += bar_width;
186 
187  // render first set
188  for (int i = 0; i < 6; ++i) {
189  int b = val[i+1];
190  for (int w = 0; w < 7; ++w) {
191  if (_encodings[b][_parity[val[0]][i]][w]) {
192  rect = new ORORect();
193  rect->setPen(pen);
194  rect->setBrush(brush);
195  rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.07));
196  page->insertPrimitive(rect);
197  }
198  pos += bar_width;
199  }
200  }
201 
202  // render center guard
203  pos += bar_width;
204 
205  rect = new ORORect();
206  rect->setPen(pen);
207  rect->setBrush(brush);
208  rect->setRect(QRectF(pos, top, bar_width, draw_height));
209  page->insertPrimitive(rect);
210 
211  pos += (bar_width * 2.0);
212 
213  rect = new ORORect();
214  rect->setPen(pen);
215  rect->setBrush(brush);
216  rect->setRect(QRectF(pos, top, bar_width, draw_height));
217  page->insertPrimitive(rect);
218 
219  pos += (bar_width * 2.0);
220 
221  // render last set
222  for (int i = 0; i < 6; ++i) {
223  int b = val[i+7];
224  for (int w = 0; w < 7; ++w) {
225  if (_encodings[b][RIGHTHAND][w]) {
226  rect = new ORORect();
227  rect->setPen(pen);
228  rect->setBrush(brush);
229  rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.07));
230  page->insertPrimitive(rect);
231  }
232  pos += bar_width;
233  }
234  }
235 
236  // render close guard
237  rect = new ORORect();
238  rect->setPen(pen);
239  rect->setBrush(brush);
240  rect->setRect(QRectF(pos, top, bar_width, draw_height));
241  page->insertPrimitive(rect);
242 
243  pos += (bar_width * 2.0);
244 
245  rect = new ORORect();
246  rect->setPen(pen);
247  rect->setBrush(brush);
248  rect->setRect(QRectF(pos, top, bar_width, draw_height));
249  page->insertPrimitive(rect);
250 
251  QString parstr = QString::fromLatin1("%1").arg(val[0]);
252  QString leftstr = QString().sprintf("%d%d%d%d%d%d",
253  val[1], val[2], val[3], val[4], val[5], val[6]);
254  QString rightstr = QString().sprintf("%d%d%d%d%d%d",
255  val[7], val[8], val[9], val[10], val[11], val[12]);
256  QFont font(QLatin1String("Arial"), 6);
257 
258  OROTextBox * tb = new OROTextBox();
259  tb->setPosition(QPointF(r.left(), r.top() + draw_height - 0.12));
260  tb->setSize(QSizeF(quiet_zone - 0.02, 0.12));
261  tb->setFont(font);
262  tb->setText(parstr);
263  tb->setFlags(Qt::AlignRight | Qt::AlignTop);
264  page->insertPrimitive(tb);
265 
266  tb = new OROTextBox();
267  tb->setPosition(QPointF(r.left() + quiet_zone + 0.03, (r.top() + draw_height) - 0.07));
268  tb->setSize(QSizeF(0.42, 0.1));
269  tb->setFont(font);
270  tb->setText(leftstr);
271  tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
272  page->insertPrimitive(tb);
273 
274  tb = new OROTextBox();
275  tb->setPosition(QPointF(r.left() + quiet_zone + 0.5, (r.top() + draw_height) - 0.07));
276  tb->setSize(QSizeF(0.42, 0.1));
277  tb->setFont(font);
278  tb->setText(rightstr);
279  tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
280  page->insertPrimitive(tb);
281 }
282 
283 void renderCodeUPCA(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
284 {
285  int val[13];
286 
287  // initialize all the values just so we can be predictable
288  for (int i = 0; i < 13; ++i) {
289  val[i] = -1;
290  }
291 
292  // verify that the passed in string is valid
293  // if it's not either twelve or thirteen characters
294  // then it must be invalid to begin with
295  if (_str.length() != 11 && _str.length() != 12)
296  return;
297  // loop through and convert each char to a digit.
298  // if we can't convert all characters then this is
299  // an invalid number
300  val[0] = 0;
301  for (int i = 0; i < _str.length(); ++i) {
302  val[i+1] = ((QChar)_str.at(i)).digitValue();
303  if (val[i+1] == -1)
304  return;
305  }
306 
307  // calculate and append the checksum value
308  int old_sum = val[12]; // get the old check sum value (-1 if none was set)
309  int checksum = 0;
310  for (int i = 0; i < 12; ++i) {
311  checksum += val[i] * ((i % 2) ? 3 : 1);
312  }
313  checksum = (checksum % 10);
314  if (checksum) checksum = 10 - checksum;
315  val[12] = checksum;
316 
317  // if we had an old checksum value and if it doesn't match what we came
318  // up with then the string must be invalid so we will bail
319  if (old_sum != -1 && old_sum != checksum)
320  return;
321 
322  // lets determine some core attributes about this barcode
323  qreal bar_width = 1; // the width of the base unit bar
324 
325  // this is are mandatory minimum quiet zone
326  qreal quiet_zone = bar_width * 10;
327  //if (quiet_zone < 10) quiet_zone = 10;
328 
329  // what kind of area do we have to work with
330  qreal draw_width = r.width();
331  qreal draw_height = r.height() - 2;
332 
333  // L = 95X
334  // L length of barcode (excluding quite zone) in units same as X and I
335  // X the width of a bar (pixels in our case)
336  qreal L;
337 
338  qreal X = bar_width;
339 
340  L = (95.0 * X);
341 
342  // now we have the actual width the barcode will be so can determine the actual
343  // size of the quiet zone (we assume we center the barcode in the given area
344  // what should we do if the area is too small????
345  // At the moment the way the code is written is we will always start at the minimum
346  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
347  // to the right
348  //
349  // calculate the starting position based on the alignment option
350  // for left align we don't need to do anything as the values are already setup for it
351  if (align == Qt::AlignHCenter) {
352  qreal nqz = (draw_width - L) / 2;
353  if (nqz > quiet_zone)
354  quiet_zone = nqz;
355  } else if (align == Qt::AlignRight) {
356  quiet_zone = draw_width - (L + quiet_zone);
357  }
358  // left : do nothing
359 
360  qreal pos = r.left() + quiet_zone;
361  qreal top = r.top();
362 
363  QPen pen(Qt::NoPen);
364  QBrush brush(QColor("black"));
365 
366  // render open guard
367  ORORect * rect = new ORORect();
368  rect->setPen(pen);
369  rect->setBrush(brush);
370  rect->setRect(QRectF(pos, top, bar_width, draw_height));
371  page->insertPrimitive(rect);
372 
373  pos += (bar_width * 2.0);
374 
375  rect = new ORORect();
376  rect->setPen(pen);
377  rect->setBrush(brush);
378  rect->setRect(QRectF(pos, top, bar_width, draw_height));
379  page->insertPrimitive(rect);
380 
381  pos += bar_width;
382 
383  // render first set
384  for (int i = 0; i < 6; ++i) {
385  int b = val[i+1];
386  for (int w = 0; w < 7; ++w) {
387  if (_encodings[b][_parity[val[0]][i]][w]) {
388  rect = new ORORect();
389  rect->setPen(pen);
390  rect->setBrush(brush);
391  rect->setRect(QRectF(pos, top, bar_width, draw_height - (i == 0 ? 0 : 0.07)));
392  page->insertPrimitive(rect);
393  }
394  pos += bar_width;
395  }
396  }
397 
398  // render center guard
399  pos += bar_width;
400  rect = new ORORect();
401  rect->setPen(pen);
402  rect->setBrush(brush);
403  rect->setRect(QRectF(pos, top, bar_width, draw_height));
404  page->insertPrimitive(rect);
405 
406  pos += (bar_width * 2.0);
407 
408  rect = new ORORect();
409  rect->setPen(pen);
410  rect->setBrush(brush);
411  rect->setRect(QRectF(pos, top, bar_width, draw_height));
412  page->insertPrimitive(rect);
413 
414  pos += (bar_width * 2.0);
415 
416  // render last set
417  for (int i = 0; i < 6; ++i) {
418  int b = val[i+7];
419  for (int w = 0; w < 7; ++w) {
420  if (_encodings[b][RIGHTHAND][w]) {
421  rect = new ORORect();
422  rect->setPen(pen);
423  rect->setBrush(brush);
424  rect->setRect(QRectF(pos, top, bar_width, draw_height - (i == 5 ? 0 : 0.07)));
425  page->insertPrimitive(rect);
426  }
427  pos += bar_width;
428  }
429  }
430 
431  // render close guard
432  rect = new ORORect();
433  rect->setPen(pen);
434  rect->setBrush(brush);
435  rect->setRect(QRectF(pos, top, bar_width, draw_height));
436  page->insertPrimitive(rect);
437 
438  pos += (bar_width * 2.0);
439 
440  rect = new ORORect();
441  rect->setPen(pen);
442  rect->setBrush(brush);
443  rect->setRect(QRectF(pos, top, bar_width, draw_height));
444  page->insertPrimitive(rect);
445 
446  QString parstr = QString::number(val[1]);
447  QString chkstr = QString::number(val[12]);
448  QString leftstr = QString().sprintf("%d%d%d%d%d",
449  val[2], val[3], val[4], val[5], val[6]);
450  QString rightstr = QString().sprintf("%d%d%d%d%d",
451  val[7], val[8], val[9], val[10], val[11]);
452 
453  QFont font(QLatin1String("Arial"), 6);
454  KReportTextStyleData ts;
455  ts.backgroundColor = Qt::white;
456  ts.font = font;
457  ts.foregroundColor = Qt::black;
458  ts.backgroundOpacity = 100;
459  ts.alignment = Qt::AlignRight | Qt::AlignTop;
460 
461  OROTextBox * tb = new OROTextBox();
462  tb->setPosition(QPointF(r.left(), r.top() + draw_height - 12));
463  tb->setSize(QSizeF(quiet_zone - 2, 12));
464  tb->setTextStyle(ts);
465  tb->setText(parstr);
466 
467  page->insertPrimitive(tb);
468 
469  tb = new OROTextBox();
470  tb->setPosition(QPointF(r.left() + quiet_zone + 10, (r.top() + draw_height) - 7));
471  tb->setSize(QSizeF(35, 10));
472  tb->setTextStyle(ts);
473  tb->setText(leftstr);
474  page->insertPrimitive(tb);
475 
476  tb = new OROTextBox();
477  tb->setPosition(QPointF(r.left() + quiet_zone + 50, (r.top() + draw_height) - 7));
478  tb->setSize(QSizeF(35, 10));
479  tb->setTextStyle(ts);
480  tb->setText(rightstr);
481  page->insertPrimitive(tb);
482 
483  tb = new OROTextBox();
484  tb->setPosition(QPointF(r.left() + quiet_zone + L + 2, (r.top() + draw_height) - 12));
485  tb->setSize(QSizeF(8, 12));
486  tb->setTextStyle(ts);
487  tb->setText(chkstr);
488  page->insertPrimitive(tb);
489 }
490 
491 void renderCodeEAN8(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
492 {
493  int val[8];
494 
495  // initialize all the values just so we can be predictable
496  for (int i = 0; i < 8; ++i) {
497  val[i] = -1;
498  }
499 
500  // verify that the passed in string is valid
501  // if it's not either twelve or thirteen characters
502  // then it must be invalid to begin with
503  if (_str.length() != 7 && _str.length() != 8)
504  return;
505  // loop through and convert each char to a digit.
506  // if we can't convert all characters then this is
507  // an invalid number
508  for (int i = 0; i < _str.length(); ++i) {
509  val[i] = ((QChar)_str.at(i)).digitValue();
510  if (val[i] == -1)
511  return;
512  }
513 
514  // calculate and append the checksum value
515  int old_sum = val[7]; // get the old check sum value (-1 if none was set)
516  int checksum = 0;
517  for (int i = 0; i < 7; ++i) {
518  checksum += val[i] * ((i % 2) ? 1 : 3);
519  }
520  checksum = (checksum % 10);
521  if (checksum) checksum = 10 - checksum;
522  val[7] = checksum;
523 
524  // if we had an old checksum value and if it doesn't match what we came
525  // up with then the string must be invalid so we will bail
526  if (old_sum != -1 && old_sum != checksum)
527  return;
528 
529 
530  // lets determine some core attributes about this barcode
531  qreal bar_width = 1; // the width of the base unit bar
532 
533  // this is are mandatory minimum quiet zone
534  qreal quiet_zone = bar_width * 10;
535  if (quiet_zone < 10)
536  quiet_zone = 10;
537 
538  // what kind of area do we have to work with
539  qreal draw_width = r.width();
540  qreal draw_height = r.height() - 0.02;
541 
542  // L = 60X
543  // L length of barcode (excluding quite zone) in units same as X and I
544  // X the width of a bar (pixels in our case)
545  qreal L;
546 
547  qreal X = bar_width;
548 
549  L = (67.0 * X);
550 
551  // now we have the actual width the barcode will be so can determine the actual
552  // size of the quiet zone (we assume we center the barcode in the given area
553  // what should we do if the area is too small????
554  // At the moment the way the code is written is we will always start at the minimum
555  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
556  // to the right
557  //
558  // calculate the starting position based on the alignment option
559  // for left align we don't need to do anything as the values are already setup for it
560  if (align == Qt::AlignHCenter) {
561  qreal nqz = (draw_width - L) / 2;
562  if (nqz > quiet_zone)
563  quiet_zone = nqz;
564  } else if (align == Qt::AlignRight) {
565  quiet_zone = draw_width - (L + quiet_zone);
566  }
567  // left : do nothing
568 
569  qreal pos = r.left() + quiet_zone;
570  qreal top = r.top();
571 
572  QPen pen(Qt::NoPen);
573  QBrush brush(QColor("black"));
574 
575  // render open guard
576  ORORect * rect = new ORORect();
577  rect->setPen(pen);
578  rect->setBrush(brush);
579  rect->setRect(QRectF(pos, top, bar_width, draw_height));
580  page->insertPrimitive(rect);
581 
582  pos += (bar_width * 2.0);
583 
584  rect = new ORORect();
585  rect->setPen(pen);
586  rect->setBrush(brush);
587  rect->setRect(QRectF(pos, top, bar_width, draw_height));
588  page->insertPrimitive(rect);
589 
590  pos += bar_width;
591 
592  // render first set
593  for (int i = 0; i < 4; ++i) {
594  int b = val[i];
595  for (int w = 0; w < 7; ++w) {
596  if (_encodings[b][LEFTHAND_ODD][w]) {
597  ORORect * rect = new ORORect();
598  rect->setPen(pen);
599  rect->setBrush(brush);
600  rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.06));
601  page->insertPrimitive(rect);
602  }
603  pos += bar_width;
604  }
605  }
606 
607  // render center guard
608  pos += bar_width;
609 
610  rect = new ORORect();
611  rect->setPen(pen);
612  rect->setBrush(brush);
613  rect->setRect(QRectF(pos, top, bar_width, draw_height));
614  page->insertPrimitive(rect);
615 
616  pos += (bar_width * 2.0);
617 
618  rect = new ORORect();
619  rect->setPen(pen);
620  rect->setBrush(brush);
621  rect->setRect(QRectF(pos, top, bar_width, draw_height));
622  page->insertPrimitive(rect);
623 
624  pos += (bar_width * 2.0);
625 
626  // render last set
627  for (int i = 0; i < 4; ++i) {
628  int b = val[i+4];
629  for (int w = 0; w < 7; ++w) {
630  if (_encodings[b][RIGHTHAND][w]) {
631  ORORect * rect = new ORORect();
632  rect->setPen(pen);
633  rect->setBrush(brush);
634  rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.06));
635  page->insertPrimitive(rect);
636  }
637  pos += bar_width;
638  }
639  }
640 
641  // render close guard
642  rect = new ORORect();
643  rect->setPen(pen);
644  rect->setBrush(brush);
645  rect->setRect(QRectF(pos, top, bar_width, draw_height));
646  page->insertPrimitive(rect);
647 
648  pos += (bar_width * 2.0);
649 
650  rect = new ORORect();
651  rect->setPen(pen);
652  rect->setBrush(brush);
653  rect->setRect(QRectF(pos, top, bar_width, draw_height));
654  page->insertPrimitive(rect);
655 
656  QString leftstr = QString().sprintf("%d%d%d%d",
657  val[0], val[1], val[2], val[3]);
658  QString rightstr = QString().sprintf("%d%d%d%d",
659  val[4], val[5], val[6], val[7]);
660  QFont font(QLatin1String("Arial"), 6);
661  OROTextBox * tb = new OROTextBox();
662 
663  tb->setPosition(QPointF(r.left() + quiet_zone + 0.03, (r.top() + draw_height) - 0.06));
664  tb->setSize(QSizeF(0.28, 0.10));
665  tb->setFont(font);
666  tb->setText(leftstr);
667  tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
668  page->insertPrimitive(tb);
669 
670  tb = new OROTextBox();
671  tb->setPosition(QPointF(r.left() + quiet_zone + 0.36, (r.top() + draw_height) - 0.06));
672  tb->setSize(QSizeF(0.28, 0.10));
673  tb->setFont(font);
674  tb->setText(rightstr);
675  tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
676  page->insertPrimitive(tb);
677 }
678 
679 void renderCodeUPCE(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
680 {
681  int val[8];
682 
683  // initialize all the values just so we can be predictable
684  for (int i = 0; i < 8; ++i) {
685  val[i] = -1;
686  }
687 
688  // verify that the passed in string is valid
689  // if it's not either twelve or thirteen characters
690  // then it must be invalid to begin with
691  if (_str.length() != 8)
692  return;
693  // loop through and convert each char to a digit.
694  // if we can't convert all characters then this is
695  // an invalid number
696  for (int i = 0; i < _str.length(); ++i) {
697  val[i] = ((QChar)_str.at(i)).digitValue();
698  if (val[i] == -1)
699  return;
700  }
701 
702  // calculate and append the checksum value
703  // because everything is so messed up we don't calculate
704  // the checksum and require that it be passed in already
705  // however we do have to verify that the first digit is
706  // either 0 or 1 as that is our parity
707  if (val[0] != 0 && val[0] != 1)
708  return;
709 
710  // lets determine some core attributes about this barcode
711  qreal bar_width = 1; // the width of the base unit bar
712 
713  // this is are mandatory minimum quiet zone
714  qreal quiet_zone = bar_width * 0.10;
715  if (quiet_zone < 0.10)
716  quiet_zone = 0.10;
717 
718  // what kind of area do we have to work with
719  qreal draw_width = r.width();
720  qreal draw_height = r.height() - 2;
721 
722  // L = 51X
723  // L length of barcode (excluding quite zone) in units same as X and I
724  // X the width of a bar (pixels in our case)
725  qreal L;
726 
727  qreal X = bar_width;
728 
729  L = (51.0 * X);
730 
731  // now we have the actual width the barcode will be so can determine the actual
732  // size of the quiet zone (we assume we center the barcode in the given area
733  // what should we do if the area is too small????
734  // At the moment the way the code is written is we will always start at the minimum
735  // required quiet zone if we don't have enough space.... I guess we'll just have over-run
736  // to the right
737  //
738  // calculate the starting position based on the alignment option
739  // for left align we don't need to do anything as the values are already setup for it
740  if (align == Qt::AlignHCenter) {
741  qreal nqz = (draw_width - L) / 2;
742  if (nqz > quiet_zone)
743  quiet_zone = nqz;
744  } else if (align == Qt::AlignRight) {
745  quiet_zone = draw_width - (L + quiet_zone);
746  }
747  // left : do nothing
748 
749  qreal pos = r.left() + quiet_zone;
750  qreal top = r.top();
751 
752  QPen pen(Qt::NoPen);
753  QBrush brush(QColor("black"));
754 
755  // render open guard
756  ORORect * rect = new ORORect();
757  rect->setPen(pen);
758  rect->setBrush(brush);
759  rect->setRect(QRectF(pos, top, bar_width, draw_height));
760  page->insertPrimitive(rect);
761 
762  pos += (bar_width * 2.0);
763 
764  rect = new ORORect();
765  rect->setPen(pen);
766  rect->setBrush(brush);
767  rect->setRect(QRectF(pos, top, bar_width, draw_height));
768  page->insertPrimitive(rect);
769 
770  pos += bar_width;
771 
772  // render first set
773  for (int i = 0; i < 6; ++i) {
774  int b = val[i+1];
775  for (int w = 0; w < 7; ++w) {
776  if (_encodings[b][_upcparenc[val[7]][val[0]][i]][w]) {
777  rect = new ORORect();
778  rect->setPen(pen);
779  rect->setBrush(brush);
780  rect->setRect(QRectF(pos, top, bar_width, draw_height - 7));
781  page->insertPrimitive(rect);
782  }
783  pos += bar_width;
784  }
785  }
786 
787  // render center guard
788  pos += bar_width;
789 
790  rect = new ORORect();
791  rect->setPen(pen);
792  rect->setBrush(brush);
793  rect->setRect(QRectF(pos, top, bar_width, draw_height));
794  page->insertPrimitive(rect);
795 
796  pos += (bar_width * 2.0);
797 
798  rect = new ORORect();
799  rect->setPen(pen);
800  rect->setBrush(brush);
801  rect->setRect(QRectF(pos, top, bar_width, draw_height));
802  page->insertPrimitive(rect);
803 
804  pos += (bar_width * 2.0);
805 
806  // render close guard
807 
808  rect = new ORORect();
809  rect->setPen(pen);
810  rect->setBrush(brush);
811  rect->setRect(QRectF(pos, top, bar_width, draw_height));
812  page->insertPrimitive(rect);
813 
814  QString parstr = QString::number(val[0]);
815  QString chkstr = QString::number(val[7]);
816  QString leftstr = QString().sprintf("%d%d%d%d%d%d",
817  val[1], val[2], val[3], val[4], val[5], val[6]);
818  QFont font(QLatin1String("Arial"), 6);
819  KReportTextStyleData ts;
820  ts.backgroundColor = Qt::white;
821  ts.font = font;
822  ts.foregroundColor = Qt::black;
823  ts.backgroundOpacity = 100;
824  ts.alignment = Qt::AlignRight | Qt::AlignTop;
825 
826  OROTextBox * tb = new OROTextBox();
827  tb->setPosition(QPointF(r.left(), r.top() + draw_height - 12));
828  tb->setSize(QSizeF(quiet_zone - 2, 12));
829  tb->setTextStyle(ts);
830  tb->setText(parstr);
831  page->insertPrimitive(tb);
832 
833  tb = new OROTextBox();
834  tb->setPosition(QPointF(r.left() + quiet_zone + 3, (r.top() + draw_height) - 7));
835  tb->setSize(QSizeF(42, 10));
836  tb->setTextStyle(ts);
837  tb->setText(leftstr);
838  page->insertPrimitive(tb);
839 
840  tb = new OROTextBox();
841  tb->setPosition(QPointF(r.left() + quiet_zone + L + 2, r.top() + draw_height - 12));
842  tb->setSize(QSizeF(8, 12));
843  tb->setTextStyle(ts);
844  tb->setText(chkstr);
845  page->insertPrimitive(tb);
846 }
qreal left() const const
typedef Alignment
A text box primitive it defines a box region and text that will be rendered inside that region,...
QString number(int n, int base)
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
Defines a rectangle.
QString & sprintf(const char *cformat,...)
int length() const const
qreal top() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLatin1(const char *str, int size)
qreal width() const const
const QChar at(int position) const const
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.