File indexing completed on 2024-05-12 04:43:18

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
0003  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 /*
0020  *     This file contains the implementation of the Code EAN and similar
0021  * formats for rendering purposes. All this code assumes a 100dpi
0022  * rendering surface for it's calculations.
0023  */
0024 
0025 #include <QString>
0026 #include <QRect>
0027 #include <QPen>
0028 #include <QBrush>
0029 
0030 #include "KReportRenderObjects.h"
0031 
0032 static const int LEFTHAND_ODD = 0;
0033 static const int LEFTHAND_EVEN = 1;
0034 static const int RIGHTHAND = 2;
0035 
0036 static const int _encodings[10][3][7] = {
0037     /*   LEFTHAND_ODD   */  /*   LEFTHAND_EVEN   */  /*     RIGHTHAND     */
0038     { { 0, 0, 0, 1, 1, 0, 1}, { 0, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0 } }, // 0
0039     { { 0, 0, 1, 1, 0, 0, 1}, { 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0 } }, // 1
0040     { { 0, 0, 1, 0, 0, 1, 1}, { 0, 0, 1, 1, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 0 } }, // 2
0041     { { 0, 1, 1, 1, 1, 0, 1}, { 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1, 0 } }, // 3
0042     { { 0, 1, 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1, 0, 1 }, { 1, 0, 1, 1, 1, 0, 0 } }, // 4
0043     { { 0, 1, 1, 0, 0, 0, 1}, { 0, 1, 1, 1, 0, 0, 1 }, { 1, 0, 0, 1, 1, 1, 0 } }, // 5
0044     { { 0, 1, 0, 1, 1, 1, 1}, { 0, 0, 0, 0, 1, 0, 1 }, { 1, 0, 1, 0, 0, 0, 0 } }, // 6
0045     { { 0, 1, 1, 1, 0, 1, 1}, { 0, 0, 1, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1, 0, 0 } }, // 7
0046     { { 0, 1, 1, 0, 1, 1, 1}, { 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 0, 1, 0, 0, 0 } }, // 8
0047     { { 0, 0, 0, 1, 0, 1, 1}, { 0, 0, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 0, 0 } }  // 9
0048 };
0049 
0050 static const int odd = LEFTHAND_ODD;
0051 static const int even = LEFTHAND_EVEN;
0052 
0053 static const int _parity[10][6] = {
0054     { odd,  odd,  odd,  odd,  odd,  odd }, // 0
0055     { odd,  odd, even,  odd, even, even }, // 1
0056     { odd,  odd, even, even,  odd, even }, // 2
0057     { odd,  odd, even, even, even,  odd }, // 3
0058     { odd, even,  odd,  odd, even, even }, // 4
0059     { odd, even, even,  odd,  odd, even }, // 5
0060     { odd, even, even, even,  odd,  odd }, // 6
0061     { odd, even,  odd, even,  odd, even }, // 7
0062     { odd, even,  odd, even, even,  odd }, // 8
0063     { odd, even, even,  odd, even,  odd }  // 9
0064 };
0065 
0066 static const int _upcparenc[10][2][6] = {
0067     /*             PARITY 0             */  /*             PARITY 1             */
0068     { { even, even, even,  odd,  odd,  odd }, {  odd,  odd,  odd, even, even, even } }, // 0
0069     { { even, even,  odd, even,  odd,  odd }, {  odd,  odd, even,  odd, even, even } }, // 1
0070     { { even, even,  odd,  odd, even,  odd }, {  odd,  odd, even, even,  odd, even } }, // 2
0071     { { even, even,  odd,  odd,  odd, even }, {  odd,  odd, even, even, even,  odd } }, // 3
0072     { { even,  odd, even, even,  odd,  odd }, {  odd, even,  odd,  odd, even, even } }, // 4
0073     { { even,  odd,  odd, even, even,  odd }, {  odd, even, even,  odd,  odd, even } }, // 5
0074     { { even,  odd,  odd,  odd, even, even }, {  odd, even, even, even,  odd,  odd } }, // 6
0075     { { even,  odd, even,  odd, even,  odd }, {  odd, even,  odd, even,  odd, even } }, // 7
0076     { { even,  odd, even,  odd,  odd, even }, {  odd, even,  odd, even, even,  odd } }, // 8
0077     { { even,  odd,  odd, even,  odd, even }, {  odd, even, even,  odd, even,  odd } }  // 9
0078 };
0079 
0080 
0081 
0082 //
0083 //! @todo New Renderer Functions
0084 ////////////////////////////////////////////////////////
0085 
0086 void renderCodeEAN13(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
0087 {
0088     int val[13];
0089 
0090     // initialize all the values just so we can be predictable
0091     for (int i = 0; i < 13; ++i)
0092         val[i] = -1;
0093 
0094     // verify that the passed in string is valid
0095     // if it's not either twelve or thirteen characters
0096     // then it must be invalid to begin with
0097     if (_str.length() != 12 && _str.length() != 13)
0098         return;
0099     // loop through and convert each char to a digit.
0100     // if we can't convert all characters then this is
0101     // an invalid number
0102     for (int i = 0; i < _str.length(); ++i) {
0103         val[i] = ((QChar)_str.at(i)).digitValue();
0104         if (val[i] == -1)
0105             return;
0106     }
0107 
0108     // calculate and append the checksum value
0109     int old_sum = val[12]; // get the old check sum value (-1 if none was set)
0110     int checksum = 0;
0111     for (int i = 0; i < 12; ++i) {
0112         checksum += val[i] * ((i % 2) ? 3 : 1);
0113     }
0114     checksum = (checksum % 10);
0115     if (checksum) checksum = 10 - checksum;
0116     val[12] = checksum;
0117 
0118     // if we had an old checksum value and if it doesn't match what we came
0119     // up with then the string must be invalid so we will bail
0120     if (old_sum != -1 && old_sum != checksum)
0121         return;
0122 
0123 
0124     // lets determine some core attributes about this barcode
0125     qreal bar_width = 1; // the width of the base unit bar 1/100 inch
0126 
0127     // this is are mandatory minimum quiet zone
0128     qreal quiet_zone = bar_width * 10;
0129     if (quiet_zone < 10)
0130         quiet_zone = 10;
0131 
0132     // what kind of area do we have to work with
0133     qreal draw_width = r.width();
0134     qreal draw_height = r.height() - 2;
0135 
0136     // L = 95X
0137     // L length of barcode (excluding quite zone) in units same as X and I
0138     // X the width of a bar (pixels in our case)
0139     qreal L;
0140 
0141     qreal X = bar_width;
0142 
0143     L = (95.0 * X);
0144 
0145     // now we have the actual width the barcode will be so can determine the actual
0146     // size of the quiet zone (we assume we center the barcode in the given area
0147     // what should we do if the area is too small????
0148     // At the moment the way the code is written is we will always start at the minimum
0149     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0150     // to the right
0151     //
0152     // calculate the starting position based on the alignment option
0153     // for left align we don't need to do anything as the values are already setup for it
0154     if (align == Qt::AlignHCenter) {
0155         qreal nqz = (draw_width - L) / 2;
0156         if (nqz > quiet_zone)
0157             quiet_zone = nqz;
0158     } else if (align == Qt::AlignRight) {
0159         quiet_zone = draw_width - (L + quiet_zone);
0160     }
0161     // left : do nothing
0162 
0163     qreal pos = r.left() + quiet_zone;
0164     qreal top = r.top();
0165 
0166 
0167     QPen pen(Qt::NoPen);
0168     QBrush brush(QColor("black"));
0169 
0170     // render open guard
0171     ORORect * rect = new ORORect();
0172     rect->setPen(pen);
0173     rect->setBrush(brush);
0174     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0175     page->insertPrimitive(rect);
0176 
0177     pos += (bar_width * 2.0);
0178 
0179     rect = new ORORect();
0180     rect->setPen(pen);
0181     rect->setBrush(brush);
0182     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0183     page->insertPrimitive(rect);
0184 
0185     pos += bar_width;
0186 
0187     // render first set
0188     for (int i = 0; i < 6; ++i) {
0189         int b = val[i+1];
0190         for (int w = 0; w < 7; ++w) {
0191             if (_encodings[b][_parity[val[0]][i]][w]) {
0192                 rect = new ORORect();
0193                 rect->setPen(pen);
0194                 rect->setBrush(brush);
0195                 rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.07));
0196                 page->insertPrimitive(rect);
0197             }
0198             pos += bar_width;
0199         }
0200     }
0201 
0202     // render center guard
0203     pos += bar_width;
0204 
0205     rect = new ORORect();
0206     rect->setPen(pen);
0207     rect->setBrush(brush);
0208     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0209     page->insertPrimitive(rect);
0210 
0211     pos += (bar_width * 2.0);
0212 
0213     rect = new ORORect();
0214     rect->setPen(pen);
0215     rect->setBrush(brush);
0216     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0217     page->insertPrimitive(rect);
0218 
0219     pos += (bar_width * 2.0);
0220 
0221     // render last set
0222     for (int i = 0; i < 6; ++i) {
0223         int b = val[i+7];
0224         for (int w = 0; w < 7; ++w) {
0225             if (_encodings[b][RIGHTHAND][w]) {
0226                 rect = new ORORect();
0227                 rect->setPen(pen);
0228                 rect->setBrush(brush);
0229                 rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.07));
0230                 page->insertPrimitive(rect);
0231             }
0232             pos += bar_width;
0233         }
0234     }
0235 
0236     // render close guard
0237     rect = new ORORect();
0238     rect->setPen(pen);
0239     rect->setBrush(brush);
0240     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0241     page->insertPrimitive(rect);
0242 
0243     pos += (bar_width * 2.0);
0244 
0245     rect = new ORORect();
0246     rect->setPen(pen);
0247     rect->setBrush(brush);
0248     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0249     page->insertPrimitive(rect);
0250 
0251     QString parstr = QString::fromLatin1("%1").arg(val[0]);
0252     QString leftstr = QString().sprintf("%d%d%d%d%d%d",
0253                                         val[1], val[2], val[3], val[4], val[5], val[6]);
0254     QString rightstr = QString().sprintf("%d%d%d%d%d%d",
0255                                          val[7], val[8], val[9], val[10], val[11], val[12]);
0256     QFont font(QLatin1String("Arial"), 6);
0257 
0258     OROTextBox * tb = new OROTextBox();
0259     tb->setPosition(QPointF(r.left(), r.top() + draw_height - 0.12));
0260     tb->setSize(QSizeF(quiet_zone - 0.02, 0.12));
0261     tb->setFont(font);
0262     tb->setText(parstr);
0263     tb->setFlags(Qt::AlignRight | Qt::AlignTop);
0264     page->insertPrimitive(tb);
0265 
0266     tb = new OROTextBox();
0267     tb->setPosition(QPointF(r.left() + quiet_zone + 0.03, (r.top() + draw_height) - 0.07));
0268     tb->setSize(QSizeF(0.42, 0.1));
0269     tb->setFont(font);
0270     tb->setText(leftstr);
0271     tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
0272     page->insertPrimitive(tb);
0273 
0274     tb = new OROTextBox();
0275     tb->setPosition(QPointF(r.left() + quiet_zone + 0.5, (r.top() + draw_height) - 0.07));
0276     tb->setSize(QSizeF(0.42, 0.1));
0277     tb->setFont(font);
0278     tb->setText(rightstr);
0279     tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
0280     page->insertPrimitive(tb);
0281 }
0282 
0283 void renderCodeUPCA(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
0284 {
0285     int val[13];
0286 
0287     // initialize all the values just so we can be predictable
0288     for (int i = 0; i < 13; ++i) {
0289         val[i] = -1;
0290     }
0291 
0292     // verify that the passed in string is valid
0293     // if it's not either twelve or thirteen characters
0294     // then it must be invalid to begin with
0295     if (_str.length() != 11 && _str.length() != 12)
0296         return;
0297     // loop through and convert each char to a digit.
0298     // if we can't convert all characters then this is
0299     // an invalid number
0300     val[0] = 0;
0301     for (int i = 0; i < _str.length(); ++i) {
0302         val[i+1] = ((QChar)_str.at(i)).digitValue();
0303         if (val[i+1] == -1)
0304             return;
0305     }
0306 
0307     // calculate and append the checksum value
0308     int old_sum = val[12]; // get the old check sum value (-1 if none was set)
0309     int checksum = 0;
0310     for (int i = 0; i < 12; ++i) {
0311         checksum += val[i] * ((i % 2) ? 3 : 1);
0312     }
0313     checksum = (checksum % 10);
0314     if (checksum) checksum = 10 - checksum;
0315     val[12] = checksum;
0316 
0317     // if we had an old checksum value and if it doesn't match what we came
0318     // up with then the string must be invalid so we will bail
0319     if (old_sum != -1 && old_sum != checksum)
0320         return;
0321 
0322     // lets determine some core attributes about this barcode
0323     qreal bar_width = 1; // the width of the base unit bar
0324 
0325     // this is are mandatory minimum quiet zone
0326     qreal quiet_zone = bar_width * 10;
0327     //if (quiet_zone < 10) quiet_zone = 10;
0328 
0329     // what kind of area do we have to work with
0330     qreal draw_width = r.width();
0331     qreal draw_height = r.height() - 2;
0332 
0333     // L = 95X
0334     // L length of barcode (excluding quite zone) in units same as X and I
0335     // X the width of a bar (pixels in our case)
0336     qreal L;
0337 
0338     qreal X = bar_width;
0339 
0340     L = (95.0 * X);
0341 
0342     // now we have the actual width the barcode will be so can determine the actual
0343     // size of the quiet zone (we assume we center the barcode in the given area
0344     // what should we do if the area is too small????
0345     // At the moment the way the code is written is we will always start at the minimum
0346     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0347     // to the right
0348     //
0349     // calculate the starting position based on the alignment option
0350     // for left align we don't need to do anything as the values are already setup for it
0351     if (align == Qt::AlignHCenter) {
0352         qreal nqz = (draw_width - L) / 2;
0353         if (nqz > quiet_zone)
0354             quiet_zone = nqz;
0355     } else if (align == Qt::AlignRight) {
0356         quiet_zone = draw_width - (L + quiet_zone);
0357     }
0358     // left : do nothing
0359 
0360     qreal pos = r.left() + quiet_zone;
0361     qreal top = r.top();
0362 
0363     QPen pen(Qt::NoPen);
0364     QBrush brush(QColor("black"));
0365 
0366     // render open guard
0367     ORORect * rect = new ORORect();
0368     rect->setPen(pen);
0369     rect->setBrush(brush);
0370     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0371     page->insertPrimitive(rect);
0372 
0373     pos += (bar_width * 2.0);
0374 
0375     rect = new ORORect();
0376     rect->setPen(pen);
0377     rect->setBrush(brush);
0378     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0379     page->insertPrimitive(rect);
0380 
0381     pos += bar_width;
0382 
0383     // render first set
0384     for (int i = 0; i < 6; ++i) {
0385         int b = val[i+1];
0386         for (int w = 0; w < 7; ++w) {
0387             if (_encodings[b][_parity[val[0]][i]][w]) {
0388                 rect = new ORORect();
0389                 rect->setPen(pen);
0390                 rect->setBrush(brush);
0391                 rect->setRect(QRectF(pos, top, bar_width, draw_height - (i == 0 ? 0 : 0.07)));
0392                 page->insertPrimitive(rect);
0393             }
0394             pos += bar_width;
0395         }
0396     }
0397 
0398     // render center guard
0399     pos += bar_width;
0400     rect = new ORORect();
0401     rect->setPen(pen);
0402     rect->setBrush(brush);
0403     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0404     page->insertPrimitive(rect);
0405 
0406     pos += (bar_width * 2.0);
0407 
0408     rect = new ORORect();
0409     rect->setPen(pen);
0410     rect->setBrush(brush);
0411     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0412     page->insertPrimitive(rect);
0413 
0414     pos += (bar_width * 2.0);
0415 
0416     // render last set
0417     for (int i = 0; i < 6; ++i) {
0418         int b = val[i+7];
0419         for (int w = 0; w < 7; ++w) {
0420             if (_encodings[b][RIGHTHAND][w]) {
0421                 rect = new ORORect();
0422                 rect->setPen(pen);
0423                 rect->setBrush(brush);
0424                 rect->setRect(QRectF(pos, top, bar_width, draw_height - (i == 5 ? 0 : 0.07)));
0425                 page->insertPrimitive(rect);
0426             }
0427             pos += bar_width;
0428         }
0429     }
0430 
0431     // render close guard
0432     rect = new ORORect();
0433     rect->setPen(pen);
0434     rect->setBrush(brush);
0435     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0436     page->insertPrimitive(rect);
0437 
0438     pos += (bar_width * 2.0);
0439 
0440     rect = new ORORect();
0441     rect->setPen(pen);
0442     rect->setBrush(brush);
0443     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0444     page->insertPrimitive(rect);
0445 
0446     QString parstr = QString::number(val[1]);
0447     QString chkstr = QString::number(val[12]);
0448     QString leftstr = QString().sprintf("%d%d%d%d%d",
0449                                         val[2], val[3], val[4], val[5], val[6]);
0450     QString rightstr = QString().sprintf("%d%d%d%d%d",
0451                                          val[7], val[8], val[9], val[10], val[11]);
0452 
0453     QFont font(QLatin1String("Arial"), 6);
0454     KReportTextStyleData ts;
0455     ts.backgroundColor = Qt::white;
0456     ts.font = font;
0457     ts.foregroundColor = Qt::black;
0458     ts.backgroundOpacity = 100;
0459     ts.alignment = Qt::AlignRight | Qt::AlignTop;
0460 
0461     OROTextBox * tb = new OROTextBox();
0462     tb->setPosition(QPointF(r.left(), r.top() + draw_height - 12));
0463     tb->setSize(QSizeF(quiet_zone - 2, 12));
0464     tb->setTextStyle(ts);
0465     tb->setText(parstr);
0466 
0467     page->insertPrimitive(tb);
0468 
0469     tb = new OROTextBox();
0470     tb->setPosition(QPointF(r.left() + quiet_zone + 10, (r.top() + draw_height) - 7));
0471     tb->setSize(QSizeF(35, 10));
0472     tb->setTextStyle(ts);
0473     tb->setText(leftstr);
0474     page->insertPrimitive(tb);
0475 
0476     tb = new OROTextBox();
0477     tb->setPosition(QPointF(r.left() + quiet_zone + 50, (r.top() + draw_height) - 7));
0478     tb->setSize(QSizeF(35, 10));
0479     tb->setTextStyle(ts);
0480     tb->setText(rightstr);
0481     page->insertPrimitive(tb);
0482 
0483     tb = new OROTextBox();
0484     tb->setPosition(QPointF(r.left() + quiet_zone + L + 2, (r.top() + draw_height) - 12));
0485     tb->setSize(QSizeF(8, 12));
0486     tb->setTextStyle(ts);
0487     tb->setText(chkstr);
0488     page->insertPrimitive(tb);
0489 }
0490 
0491 void renderCodeEAN8(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
0492 {
0493     int val[8];
0494 
0495     // initialize all the values just so we can be predictable
0496     for (int i = 0; i < 8; ++i) {
0497         val[i] = -1;
0498     }
0499 
0500     // verify that the passed in string is valid
0501     // if it's not either twelve or thirteen characters
0502     // then it must be invalid to begin with
0503     if (_str.length() != 7 && _str.length() != 8)
0504         return;
0505     // loop through and convert each char to a digit.
0506     // if we can't convert all characters then this is
0507     // an invalid number
0508     for (int i = 0; i < _str.length(); ++i) {
0509         val[i] = ((QChar)_str.at(i)).digitValue();
0510         if (val[i] == -1)
0511             return;
0512     }
0513 
0514     // calculate and append the checksum value
0515     int old_sum = val[7]; // get the old check sum value (-1 if none was set)
0516     int checksum = 0;
0517     for (int i = 0; i < 7; ++i) {
0518         checksum += val[i] * ((i % 2) ? 1 : 3);
0519     }
0520     checksum = (checksum % 10);
0521     if (checksum) checksum = 10 - checksum;
0522     val[7] = checksum;
0523 
0524     // if we had an old checksum value and if it doesn't match what we came
0525     // up with then the string must be invalid so we will bail
0526     if (old_sum != -1 && old_sum != checksum)
0527         return;
0528 
0529 
0530     // lets determine some core attributes about this barcode
0531     qreal bar_width = 1; // the width of the base unit bar
0532 
0533     // this is are mandatory minimum quiet zone
0534     qreal quiet_zone = bar_width * 10;
0535     if (quiet_zone < 10)
0536         quiet_zone = 10;
0537 
0538     // what kind of area do we have to work with
0539     qreal draw_width = r.width();
0540     qreal draw_height = r.height() - 0.02;
0541 
0542     // L = 60X
0543     // L length of barcode (excluding quite zone) in units same as X and I
0544     // X the width of a bar (pixels in our case)
0545     qreal L;
0546 
0547     qreal X = bar_width;
0548 
0549     L = (67.0 * X);
0550 
0551     // now we have the actual width the barcode will be so can determine the actual
0552     // size of the quiet zone (we assume we center the barcode in the given area
0553     // what should we do if the area is too small????
0554     // At the moment the way the code is written is we will always start at the minimum
0555     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0556     // to the right
0557     //
0558     // calculate the starting position based on the alignment option
0559     // for left align we don't need to do anything as the values are already setup for it
0560     if (align ==  Qt::AlignHCenter) {
0561         qreal nqz = (draw_width - L) / 2;
0562         if (nqz > quiet_zone)
0563             quiet_zone = nqz;
0564     } else if (align == Qt::AlignRight) {
0565         quiet_zone = draw_width - (L + quiet_zone);
0566     }
0567     // left : do nothing
0568 
0569     qreal pos = r.left() + quiet_zone;
0570     qreal top = r.top();
0571 
0572     QPen pen(Qt::NoPen);
0573     QBrush brush(QColor("black"));
0574 
0575     // render open guard
0576     ORORect * rect = new ORORect();
0577     rect->setPen(pen);
0578     rect->setBrush(brush);
0579     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0580     page->insertPrimitive(rect);
0581 
0582     pos += (bar_width * 2.0);
0583 
0584     rect = new ORORect();
0585     rect->setPen(pen);
0586     rect->setBrush(brush);
0587     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0588     page->insertPrimitive(rect);
0589 
0590     pos += bar_width;
0591 
0592     // render first set
0593     for (int i = 0; i < 4; ++i) {
0594         int b = val[i];
0595         for (int w = 0; w < 7; ++w) {
0596             if (_encodings[b][LEFTHAND_ODD][w]) {
0597                 ORORect * rect = new ORORect();
0598                 rect->setPen(pen);
0599                 rect->setBrush(brush);
0600                 rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.06));
0601                 page->insertPrimitive(rect);
0602             }
0603             pos += bar_width;
0604         }
0605     }
0606 
0607     // render center guard
0608     pos += bar_width;
0609 
0610     rect = new ORORect();
0611     rect->setPen(pen);
0612     rect->setBrush(brush);
0613     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0614     page->insertPrimitive(rect);
0615 
0616     pos += (bar_width * 2.0);
0617 
0618     rect = new ORORect();
0619     rect->setPen(pen);
0620     rect->setBrush(brush);
0621     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0622     page->insertPrimitive(rect);
0623 
0624     pos += (bar_width * 2.0);
0625 
0626     // render last set
0627     for (int i = 0; i < 4; ++i) {
0628         int b = val[i+4];
0629         for (int w = 0; w < 7; ++w) {
0630             if (_encodings[b][RIGHTHAND][w]) {
0631                 ORORect * rect = new ORORect();
0632                 rect->setPen(pen);
0633                 rect->setBrush(brush);
0634                 rect->setRect(QRectF(pos, top, bar_width, draw_height - 0.06));
0635                 page->insertPrimitive(rect);
0636             }
0637             pos += bar_width;
0638         }
0639     }
0640 
0641     // render close guard
0642     rect = new ORORect();
0643     rect->setPen(pen);
0644     rect->setBrush(brush);
0645     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0646     page->insertPrimitive(rect);
0647 
0648     pos += (bar_width * 2.0);
0649 
0650     rect = new ORORect();
0651     rect->setPen(pen);
0652     rect->setBrush(brush);
0653     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0654     page->insertPrimitive(rect);
0655 
0656     QString leftstr = QString().sprintf("%d%d%d%d",
0657                                         val[0], val[1], val[2], val[3]);
0658     QString rightstr = QString().sprintf("%d%d%d%d",
0659                                          val[4], val[5], val[6], val[7]);
0660     QFont font(QLatin1String("Arial"), 6);
0661     OROTextBox * tb = new OROTextBox();
0662 
0663     tb->setPosition(QPointF(r.left() + quiet_zone + 0.03, (r.top() + draw_height) - 0.06));
0664     tb->setSize(QSizeF(0.28, 0.10));
0665     tb->setFont(font);
0666     tb->setText(leftstr);
0667     tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
0668     page->insertPrimitive(tb);
0669 
0670     tb = new OROTextBox();
0671     tb->setPosition(QPointF(r.left() + quiet_zone + 0.36, (r.top() + draw_height) - 0.06));
0672     tb->setSize(QSizeF(0.28, 0.10));
0673     tb->setFont(font);
0674     tb->setText(rightstr);
0675     tb->setFlags(Qt::AlignHCenter | Qt::AlignTop);
0676     page->insertPrimitive(tb);
0677 }
0678 
0679 void renderCodeUPCE(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align)
0680 {
0681     int val[8];
0682 
0683     // initialize all the values just so we can be predictable
0684     for (int i = 0; i < 8; ++i) {
0685         val[i] = -1;
0686     }
0687 
0688     // verify that the passed in string is valid
0689     // if it's not either twelve or thirteen characters
0690     // then it must be invalid to begin with
0691     if (_str.length() != 8)
0692         return;
0693     // loop through and convert each char to a digit.
0694     // if we can't convert all characters then this is
0695     // an invalid number
0696     for (int i = 0; i < _str.length(); ++i) {
0697         val[i] = ((QChar)_str.at(i)).digitValue();
0698         if (val[i] == -1)
0699             return;
0700     }
0701 
0702     // calculate and append the checksum value
0703     // because everything is so messed up we don't calculate
0704     // the checksum and require that it be passed in already
0705     // however we do have to verify that the first digit is
0706     // either 0 or 1 as that is our parity
0707     if (val[0] != 0 && val[0] != 1)
0708         return;
0709 
0710     // lets determine some core attributes about this barcode
0711     qreal bar_width = 1; // the width of the base unit bar
0712 
0713     // this is are mandatory minimum quiet zone
0714     qreal quiet_zone = bar_width * 0.10;
0715     if (quiet_zone < 0.10)
0716         quiet_zone = 0.10;
0717 
0718     // what kind of area do we have to work with
0719     qreal draw_width = r.width();
0720     qreal draw_height = r.height() - 2;
0721 
0722     // L = 51X
0723     // L length of barcode (excluding quite zone) in units same as X and I
0724     // X the width of a bar (pixels in our case)
0725     qreal L;
0726 
0727     qreal X = bar_width;
0728 
0729     L = (51.0 * X);
0730 
0731     // now we have the actual width the barcode will be so can determine the actual
0732     // size of the quiet zone (we assume we center the barcode in the given area
0733     // what should we do if the area is too small????
0734     // At the moment the way the code is written is we will always start at the minimum
0735     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0736     // to the right
0737     //
0738     // calculate the starting position based on the alignment option
0739     // for left align we don't need to do anything as the values are already setup for it
0740     if (align == Qt::AlignHCenter) {
0741         qreal nqz = (draw_width - L) / 2;
0742         if (nqz > quiet_zone)
0743             quiet_zone = nqz;
0744     } else if (align == Qt::AlignRight) {
0745         quiet_zone = draw_width - (L + quiet_zone);
0746     }
0747     // left : do nothing
0748 
0749     qreal pos = r.left() + quiet_zone;
0750     qreal top = r.top();
0751 
0752     QPen pen(Qt::NoPen);
0753     QBrush brush(QColor("black"));
0754 
0755     // render open guard
0756     ORORect * rect = new ORORect();
0757     rect->setPen(pen);
0758     rect->setBrush(brush);
0759     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0760     page->insertPrimitive(rect);
0761 
0762     pos += (bar_width * 2.0);
0763 
0764     rect = new ORORect();
0765     rect->setPen(pen);
0766     rect->setBrush(brush);
0767     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0768     page->insertPrimitive(rect);
0769 
0770     pos += bar_width;
0771 
0772     // render first set
0773     for (int i = 0; i < 6; ++i) {
0774         int b = val[i+1];
0775         for (int w = 0; w < 7; ++w) {
0776             if (_encodings[b][_upcparenc[val[7]][val[0]][i]][w]) {
0777                 rect = new ORORect();
0778                 rect->setPen(pen);
0779                 rect->setBrush(brush);
0780                 rect->setRect(QRectF(pos, top, bar_width, draw_height - 7));
0781                 page->insertPrimitive(rect);
0782             }
0783             pos += bar_width;
0784         }
0785     }
0786 
0787     // render center guard
0788     pos += bar_width;
0789 
0790     rect = new ORORect();
0791     rect->setPen(pen);
0792     rect->setBrush(brush);
0793     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0794     page->insertPrimitive(rect);
0795 
0796     pos += (bar_width * 2.0);
0797 
0798     rect = new ORORect();
0799     rect->setPen(pen);
0800     rect->setBrush(brush);
0801     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0802     page->insertPrimitive(rect);
0803 
0804     pos += (bar_width * 2.0);
0805 
0806     // render close guard
0807 
0808     rect = new ORORect();
0809     rect->setPen(pen);
0810     rect->setBrush(brush);
0811     rect->setRect(QRectF(pos, top, bar_width, draw_height));
0812     page->insertPrimitive(rect);
0813 
0814     QString parstr = QString::number(val[0]);
0815     QString chkstr = QString::number(val[7]);
0816     QString leftstr = QString().sprintf("%d%d%d%d%d%d",
0817                                         val[1], val[2], val[3], val[4], val[5], val[6]);
0818     QFont font(QLatin1String("Arial"), 6);
0819     KReportTextStyleData ts;
0820     ts.backgroundColor = Qt::white;
0821     ts.font = font;
0822     ts.foregroundColor = Qt::black;
0823     ts.backgroundOpacity = 100;
0824     ts.alignment = Qt::AlignRight | Qt::AlignTop;
0825 
0826     OROTextBox * tb = new OROTextBox();
0827     tb->setPosition(QPointF(r.left(), r.top() + draw_height - 12));
0828     tb->setSize(QSizeF(quiet_zone - 2, 12));
0829     tb->setTextStyle(ts);
0830     tb->setText(parstr);
0831     page->insertPrimitive(tb);
0832 
0833     tb = new OROTextBox();
0834     tb->setPosition(QPointF(r.left() + quiet_zone + 3, (r.top() + draw_height) - 7));
0835     tb->setSize(QSizeF(42, 10));
0836     tb->setTextStyle(ts);
0837     tb->setText(leftstr);
0838     page->insertPrimitive(tb);
0839 
0840     tb = new OROTextBox();
0841     tb->setPosition(QPointF(r.left() + quiet_zone + L + 2, r.top() + draw_height - 12));
0842     tb->setSize(QSizeF(8, 12));
0843     tb->setTextStyle(ts);
0844     tb->setText(chkstr);
0845     page->insertPrimitive(tb);
0846 }