KReport

codeean.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 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
32static const int LEFTHAND_ODD = 0;
33static const int LEFTHAND_EVEN = 1;
34static const int RIGHTHAND = 2;
35
36static 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
50static const int odd = LEFTHAND_ODD;
51static const int even = LEFTHAND_EVEN;
52
53static 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
66static 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
86void 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
283void 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
491void 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
679void 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}
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
Defines a rectangle.
A text box primitive it defines a box region and text that will be rendered inside that region,...
qreal height() const const
qreal left() const const
qreal top() const const
qreal width() const const
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
QString fromLatin1(QByteArrayView str)
qsizetype length() const const
QString number(double n, char format, int precision)
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.