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

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 <QPainter>
0028 #include <QPen>
0029 #include <QBrush>
0030 
0031 #include "KReportRenderObjects.h"
0032 
0033 static const int LEFTHAND_ODD = 0;
0034 static const int LEFTHAND_EVEN = 1;
0035 static const int RIGHTHAND = 2;
0036 
0037 static int const _encodings[10][3][7] = {
0038     /*   LEFTHAND_ODD   */  /*   LEFTHAND_EVEN   */  /*     RIGHTHAND     */
0039     { { 0, 0, 0, 1, 1, 0, 1}, { 0, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0 } }, // 0
0040     { { 0, 0, 1, 1, 0, 0, 1}, { 0, 1, 1, 0, 0, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0 } }, // 1
0041     { { 0, 0, 1, 0, 0, 1, 1}, { 0, 0, 1, 1, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 0 } }, // 2
0042     { { 0, 1, 1, 1, 1, 0, 1}, { 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1, 0 } }, // 3
0043     { { 0, 1, 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1, 0, 1 }, { 1, 0, 1, 1, 1, 0, 0 } }, // 4
0044     { { 0, 1, 1, 0, 0, 0, 1}, { 0, 1, 1, 1, 0, 0, 1 }, { 1, 0, 0, 1, 1, 1, 0 } }, // 5
0045     { { 0, 1, 0, 1, 1, 1, 1}, { 0, 0, 0, 0, 1, 0, 1 }, { 1, 0, 1, 0, 0, 0, 0 } }, // 6
0046     { { 0, 1, 1, 1, 0, 1, 1}, { 0, 0, 1, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1, 0, 0 } }, // 7
0047     { { 0, 1, 1, 0, 1, 1, 1}, { 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 0, 1, 0, 0, 0 } }, // 8
0048     { { 0, 0, 0, 1, 0, 1, 1}, { 0, 0, 1, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 0, 0 } }  // 9
0049 };
0050 
0051 static const int odd = LEFTHAND_ODD;
0052 static const int even = LEFTHAND_EVEN;
0053 
0054 static const int _parity[10][6] = {
0055     { odd,  odd,  odd,  odd,  odd,  odd }, // 0
0056     { odd,  odd, even,  odd, even, even }, // 1
0057     { odd,  odd, even, even,  odd, even }, // 2
0058     { odd,  odd, even, even, even,  odd }, // 3
0059     { odd, even,  odd,  odd, even, even }, // 4
0060     { odd, even, even,  odd,  odd, even }, // 5
0061     { odd, even, even, even,  odd,  odd }, // 6
0062     { odd, even,  odd, even,  odd, even }, // 7
0063     { odd, even,  odd, even, even,  odd }, // 8
0064     { odd, even, even,  odd, even,  odd }  // 9
0065 };
0066 
0067 static const int _upcparenc[10][2][6] = {
0068     /*             PARITY 0             */  /*             PARITY 1             */
0069     { { even, even, even,  odd,  odd,  odd }, {  odd,  odd,  odd, even, even, even } }, // 0
0070     { { even, even,  odd, even,  odd,  odd }, {  odd,  odd, even,  odd, even, even } }, // 1
0071     { { even, even,  odd,  odd, even,  odd }, {  odd,  odd, even, even,  odd, even } }, // 2
0072     { { even, even,  odd,  odd,  odd, even }, {  odd,  odd, even, even, even,  odd } }, // 3
0073     { { even,  odd, even, even,  odd,  odd }, {  odd, even,  odd,  odd, even, even } }, // 4
0074     { { even,  odd,  odd, even, even,  odd }, {  odd, even, even,  odd,  odd, even } }, // 5
0075     { { even,  odd,  odd,  odd, even, even }, {  odd, even, even, even,  odd,  odd } }, // 6
0076     { { even,  odd, even,  odd, even,  odd }, {  odd, even,  odd, even,  odd, even } }, // 7
0077     { { even,  odd, even,  odd,  odd, even }, {  odd, even,  odd, even, even,  odd } }, // 8
0078     { { even,  odd,  odd, even,  odd, even }, {  odd, even, even,  odd, even,  odd } }  // 9
0079 };
0080 
0081 
0082 void renderCodeEAN13(const QRect & r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
0083 {
0084     int val[13];
0085 
0086     // initialize all the values just so we can be predictable
0087     for (int i = 0; i < 13; ++i) {
0088         val[i] = -1;
0089     }
0090 
0091     // verify that the passed in string is valid
0092     // if it's not either twelve or thirteen characters
0093     // then it must be invalid to begin with
0094     if (_str.length() != 12 && _str.length() != 13) return;
0095     // loop through and convert each char to a digit.
0096     // if we can't convert all characters then this is
0097     // an invalid number
0098     for (int i = 0; i < _str.length(); ++i) {
0099         val[i] = ((QChar) _str.at(i)).digitValue();
0100         if (val[i] == -1) return;
0101     }
0102 
0103     // calculate and append the checksum value
0104     int old_sum = val[12]; // get the old check sum value (-1 if none was set)
0105     int checksum = 0;
0106     for (int i = 0; i < 12; ++i) {
0107         checksum += val[i] * ((i % 2) ? 3 : 1);
0108     }
0109     checksum = (checksum % 10);
0110     if (checksum) checksum = 10 - checksum;
0111     val[12] = checksum;
0112 
0113     // if we had an old checksum value and if it doesn't match what we came
0114     // up with then the string must be invalid so we will bail
0115     if (old_sum != -1 && old_sum != checksum) return;
0116 
0117 
0118     // lets determine some core attributes about this barcode
0119     int bar_width = 1; // the width of the base unit bar
0120 
0121     // this is are mandatory minimum quiet zone
0122     int quiet_zone = bar_width * 10;
0123     //if (quiet_zone < 10) quiet_zone = 10;
0124 
0125     // what kind of area do we have to work with
0126     int draw_width = r.width();
0127     int draw_height = r.height() - 2;
0128 
0129     // L = 95X
0130     // L length of barcode (excluding quite zone) in units same as X and I
0131     // X the width of a bar (pixels in our case)
0132     int L;
0133 
0134     int X = bar_width;
0135 
0136     L = (95 * X);
0137 
0138     // now we have the actual width the barcode will be so can determine the actual
0139     // size of the quiet zone (we assume we center the barcode in the given area
0140     // what should we do if the area is too small????
0141     // At the moment the way the code is written is we will always start at the minimum
0142     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0143     // to the right
0144     //
0145     // calculate the starting position based on the alignment option
0146     // for left align we don't need to do anything as the values are already setup for it
0147     if (align == Qt::AlignHCenter) {
0148         int nqz = (draw_width - L) / 2;
0149         if (nqz > quiet_zone) quiet_zone = nqz;
0150     } else if (align == Qt::AlignRight) {
0151         quiet_zone = draw_width - (L + quiet_zone);
0152     }
0153     // left : do nothing
0154 
0155     int pos = r.left() + quiet_zone;
0156     int top = r.top();
0157 
0158     if (pPainter) {
0159         pPainter->save();
0160 
0161         QPen oneWide(pPainter->pen());
0162         oneWide.setWidth(1);
0163 #ifndef Q_OS_WIN32
0164         oneWide.setJoinStyle(Qt::MiterJoin);
0165 #endif
0166         pPainter->setPen(oneWide);
0167         pPainter->setBrush(pPainter->pen().color());
0168 
0169         // render open guard
0170         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0171         pos += 2;
0172         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0173         pos ++;
0174 
0175         // render first set
0176         for (int i = 0; i < 6; ++i) {
0177             int b = val[i+1];
0178             for (int w = 0; w < 7; ++w) {
0179                 if (_encodings[b][_parity[val[0]][i]][w]) {
0180                     pPainter->fillRect(pos, top, 1, draw_height - 7, pPainter->pen().color());
0181                 }
0182                 pos++;
0183             }
0184         }
0185 
0186         // render center guard
0187         pos++;
0188         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0189         pos += 2;
0190         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0191         pos += 2;
0192 
0193         // render last set
0194         for (int i = 0; i < 6; ++i) {
0195             int b = val[i+7];
0196             for (int w = 0; w < 7; ++w) {
0197                 if (_encodings[b][RIGHTHAND][w]) {
0198                     pPainter->fillRect(pos, top, 1, draw_height - 7, pPainter->pen().color());
0199                 }
0200                 pos++;
0201             }
0202         }
0203 
0204         // render close guard
0205         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0206         pos += 2;
0207         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0208 
0209         QString parstr = QString::number(val[0]);
0210         QString leftstr = QString::asprintf("%d%d%d%d%d%d",
0211                                             val[1], val[2], val[3], val[4], val[5], val[6]);
0212         QString rightstr = QString::asprintf("%d%d%d%d%d%d",
0213                                              val[7], val[8], val[9], val[10], val[11], val[12]);
0214         pPainter->setFont(QFont(QLatin1String("Arial"), 6));
0215         pPainter->drawText(r.left(), r.top() + draw_height - 12,
0216                            quiet_zone - 2, 12, Qt::AlignRight | Qt::AlignTop,
0217                            parstr);
0218         pPainter->drawText(r.left() + quiet_zone + 3,
0219                            (r.top() + draw_height) - 7,
0220                            42, 10, Qt::AlignHCenter | Qt::AlignTop,
0221                            leftstr);
0222         pPainter->drawText(r.left() + quiet_zone + 50,
0223                            (r.top() + draw_height) - 7,
0224                            42, 10, Qt::AlignHCenter | Qt::AlignTop,
0225                            rightstr);
0226 
0227         pPainter->restore();
0228     }
0229 }
0230 
0231 void renderCodeUPCA(const QRect & r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
0232 {
0233     int val[13];
0234 
0235     // initialize all the values just so we can be predictable
0236     for (int i = 0; i < 13; ++i) {
0237         val[i] = -1;
0238     }
0239 
0240     // verify that the passed in string is valid
0241     // if it's not either twelve or thirteen characters
0242     // then it must be invalid to begin with
0243     if (_str.length() != 11 && _str.length() != 12) return;
0244     // loop through and convert each char to a digit.
0245     // if we can't convert all characters then this is
0246     // an invalid number
0247     val[0] = 0;
0248     for (int i = 0; i < _str.length(); ++i) {
0249         val[i+1] = ((QChar) _str.at(i)).digitValue();
0250         if (val[i+1] == -1) return;
0251     }
0252 
0253     // calculate and append the checksum value
0254     int old_sum = val[12]; // get the old check sum value (-1 if none was set)
0255     int checksum = 0;
0256     for (int i = 0; i < 12; ++i) {
0257         checksum += val[i] * ((i % 2) ? 3 : 1);
0258     }
0259     checksum = (checksum % 10);
0260     if (checksum) checksum = 10 - checksum;
0261     val[12] = checksum;
0262 
0263     // if we had an old checksum value and if it doesn't match what we came
0264     // up with then the string must be invalid so we will bail
0265     if (old_sum != -1 && old_sum != checksum) return;
0266 
0267 
0268     // lets determine some core attributes about this barcode
0269     int bar_width = 1; // the width of the base unit bar
0270 
0271     // this is are mandatory minimum quiet zone
0272     int quiet_zone = bar_width * 10;
0273     //if (quiet_zone < 10) quiet_zone = 10;
0274 
0275     // what kind of area do we have to work with
0276     int draw_width = r.width();
0277     int draw_height = r.height() - 2;
0278 
0279     // L = 95X
0280     // L length of barcode (excluding quite zone) in units same as X and I
0281     // X the width of a bar (pixels in our case)
0282     int L;
0283 
0284     int X = bar_width;
0285 
0286     L = (95 * X);
0287 
0288     // now we have the actual width the barcode will be so can determine the actual
0289     // size of the quiet zone (we assume we center the barcode in the given area
0290     // what should we do if the area is too small????
0291     // At the moment the way the code is written is we will always start at the minimum
0292     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0293     // to the right
0294     //
0295     // calculate the starting position based on the alignment option
0296     // for left align we don't need to do anything as the values are already setup for it
0297     if (align == Qt::AlignHCenter) {
0298         int nqz = (draw_width - L) / 2;
0299         if (nqz > quiet_zone) quiet_zone = nqz;
0300     } else if (align == Qt::AlignRight) {
0301         quiet_zone = draw_width - (L + quiet_zone);
0302     }
0303     // left : do nothing
0304 
0305     int pos = r.left() + quiet_zone;
0306     int top = r.top();
0307 
0308     if (pPainter) {
0309         pPainter->save();
0310 
0311         QPen oneWide(pPainter->pen());
0312         oneWide.setWidth(1);
0313 #ifndef Q_OS_WIN32
0314         oneWide.setJoinStyle(Qt::MiterJoin);
0315 #endif
0316         pPainter->setPen(oneWide);
0317         pPainter->setBrush(pPainter->pen().color());
0318 
0319         // render open guard
0320         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0321         pos += 2;
0322         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0323         pos ++;
0324 
0325         // render first set
0326         for (int i = 0; i < 6; ++i) {
0327             int b = val[i+1];
0328             for (int w = 0; w < 7; ++w) {
0329                 if (_encodings[b][_parity[val[0]][i]][w]) {
0330                     pPainter->fillRect(pos, top, 1, draw_height - (i == 0 ? 0 : 7), pPainter->pen().color());
0331                 }
0332                 pos++;
0333             }
0334         }
0335 
0336         // render center guard
0337         pos++;
0338         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0339         pos += 2;
0340         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0341         pos += 2;
0342 
0343         // render last set
0344         for (int i = 0; i < 6; ++i) {
0345             int b = val[i+7];
0346             for (int w = 0; w < 7; ++w) {
0347                 if (_encodings[b][RIGHTHAND][w]) {
0348                     pPainter->fillRect(pos, top, 1, draw_height - (i == 5 ? 0 : 7), pPainter->pen().color());
0349                 }
0350                 pos++;
0351             }
0352         }
0353 
0354         // render close guard
0355         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0356         pos += 2;
0357         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0358 
0359         QString parstr = QString::number(val[1]);
0360         QString chkstr = QString::number(val[12]);
0361         QString leftstr = QString().sprintf("%d%d%d%d%d",
0362                                             val[2], val[3], val[4], val[5], val[6]);
0363         QString rightstr = QString().sprintf("%d%d%d%d%d",
0364                                              val[7], val[8], val[9], val[10], val[11]);
0365         pPainter->setFont(QFont(QLatin1String("Arial"), 6));
0366         pPainter->drawText(r.left(), r.top() + draw_height - 12,
0367                            quiet_zone - 2, 12, Qt::AlignRight | Qt::AlignTop,
0368                            parstr);
0369         pPainter->drawText(r.left() + quiet_zone + 10,
0370                            (r.top() + draw_height) - 7,
0371                            35, 10, Qt::AlignHCenter | Qt::AlignTop,
0372                            leftstr);
0373         pPainter->drawText(r.left() + quiet_zone + 50,
0374                            (r.top() + draw_height) - 7,
0375                            35, 10, Qt::AlignHCenter | Qt::AlignTop,
0376                            rightstr);
0377         pPainter->drawText(r.left() + quiet_zone + L + 2, r.top() + draw_height - 12,
0378                            8, 12, Qt::AlignLeft | Qt::AlignTop,
0379                            chkstr);
0380 
0381         pPainter->restore();
0382     }
0383 }
0384 
0385 void renderCodeEAN8(const QRect & r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
0386 {
0387     int val[8];
0388 
0389     // initialize all the values just so we can be predictable
0390     for (int i = 0; i < 8; ++i) {
0391         val[i] = -1;
0392     }
0393 
0394     // verify that the passed in string is valid
0395     // if it's not either twelve or thirteen characters
0396     // then it must be invalid to begin with
0397     if (_str.length() != 7 && _str.length() != 8) return;
0398     // loop through and convert each char to a digit.
0399     // if we can't convert all characters then this is
0400     // an invalid number
0401     for (int i = 0; i < _str.length(); ++i) {
0402         val[i] = ((QChar) _str.at(i)).digitValue();
0403         if (val[i] == -1) return;
0404     }
0405 
0406     // calculate and append the checksum value
0407     int old_sum = val[7]; // get the old check sum value (-1 if none was set)
0408     int checksum = 0;
0409     for (int i = 0; i < 7; ++i) {
0410         checksum += val[i] * ((i % 2) ? 1 : 3);
0411     }
0412     checksum = (checksum % 10);
0413     if (checksum) checksum = 10 - checksum;
0414     val[7] = checksum;
0415 
0416     // if we had an old checksum value and if it doesn't match what we came
0417     // up with then the string must be invalid so we will bail
0418     if (old_sum != -1 && old_sum != checksum) return;
0419 
0420 
0421     // lets determine some core attributes about this barcode
0422     int bar_width = 1; // the width of the base unit bar
0423 
0424     // this is are mandatory minimum quiet zone
0425     int quiet_zone = bar_width * 10;
0426     //if (quiet_zone < 10) quiet_zone = 10;
0427 
0428     // what kind of area do we have to work with
0429     int draw_width = r.width();
0430     int draw_height = r.height() - 2;
0431 
0432     // L = 60X
0433     // L length of barcode (excluding quite zone) in units same as X and I
0434     // X the width of a bar (pixels in our case)
0435     int L;
0436 
0437     int X = bar_width;
0438 
0439     L = (67 * X);
0440 
0441     // now we have the actual width the barcode will be so can determine the actual
0442     // size of the quiet zone (we assume we center the barcode in the given area
0443     // what should we do if the area is too small????
0444     // At the moment the way the code is written is we will always start at the minimum
0445     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0446     // to the right
0447     //
0448     // calculate the starting position based on the alignment option
0449     // for left align we don't need to do anything as the values are already setup for it
0450     if (align == Qt::AlignHCenter) {
0451         int nqz = (draw_width - L) / 2;
0452         if (nqz > quiet_zone) quiet_zone = nqz;
0453     } else if (align == Qt::AlignRight) {
0454         quiet_zone = draw_width - (L + quiet_zone);
0455     }
0456     // left : do nothing
0457 
0458     int pos = r.left() + quiet_zone;
0459     int top = r.top();
0460 
0461     if (pPainter) {
0462         pPainter->save();
0463 
0464         QPen oneWide(pPainter->pen());
0465         oneWide.setWidth(1);
0466 #ifndef Q_OS_WIN32
0467         oneWide.setJoinStyle(Qt::MiterJoin);
0468 #endif
0469         pPainter->setPen(oneWide);
0470         pPainter->setBrush(pPainter->pen().color());
0471 
0472         // render open guard
0473         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0474         pos += 2;
0475         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0476         pos ++;
0477 
0478         // render first set
0479         for (int i = 0; i < 4; ++i) {
0480             int b = val[i];
0481             for (int w = 0; w < 7; ++w) {
0482                 if (_encodings[b][LEFTHAND_ODD][w]) {
0483                     pPainter->fillRect(pos, top, 1, draw_height - 6, pPainter->pen().color());
0484                 }
0485                 pos++;
0486             }
0487         }
0488 
0489         // render center guard
0490         pos++;
0491         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0492         pos += 2;
0493         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0494         pos += 2;
0495 
0496         // render last set
0497         for (int i = 0; i < 4; ++i) {
0498             int b = val[i+4];
0499             for (int w = 0; w < 7; ++w) {
0500                 if (_encodings[b][RIGHTHAND][w]) {
0501                     pPainter->fillRect(pos, top, 1, draw_height - 6, pPainter->pen().color());
0502                 }
0503                 pos++;
0504             }
0505         }
0506 
0507         // render close guard
0508         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0509         pos += 2;
0510         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0511 
0512         QString leftstr = QString().sprintf("%d%d%d%d",
0513                                             val[0], val[1], val[2], val[3]);
0514         QString rightstr = QString().sprintf("%d%d%d%d",
0515                                              val[4], val[5], val[6], val[7]);
0516         pPainter->setFont(QFont(QLatin1String("Arial"), 6));
0517         pPainter->drawText(r.left() + quiet_zone + 3,
0518                            (r.top() + draw_height) - 6,
0519                            28, 10, Qt::AlignHCenter | Qt::AlignTop,
0520                            leftstr);
0521         pPainter->drawText(r.left() + quiet_zone + 36,
0522                            (r.top() + draw_height) - 6,
0523                            28, 10, Qt::AlignHCenter | Qt::AlignTop,
0524                            rightstr);
0525 
0526         pPainter->restore();
0527     }
0528 }
0529 
0530 void renderCodeUPCE(const QRect & r, const QString & _str, Qt::Alignment align, QPainter * pPainter)
0531 {
0532     int val[8];
0533 
0534     // initialize all the values just so we can be predictable
0535     for (int i = 0; i < 8; ++i) {
0536         val[i] = -1;
0537     }
0538 
0539     // verify that the passed in string is valid
0540     // if it's not either twelve or thirteen characters
0541     // then it must be invalid to begin with
0542     if (_str.length() != 8) return;
0543     // loop through and convert each char to a digit.
0544     // if we can't convert all characters then this is
0545     // an invalid number
0546     for (int i = 0; i < _str.length(); ++i) {
0547         val[i] = ((QChar) _str.at(i)).digitValue();
0548         if (val[i] == -1) return;
0549     }
0550 
0551     // calculate and append the checksum value
0552     // because everything is so messed up we don't calculate
0553     // the checksum and require that it be passed in already
0554     // however we do have to verify that the first digit is
0555     // either 0 or 1 as that is our parity
0556     if (val[0] != 0 && val[0] != 1) return;
0557 
0558     // lets determine some core attributes about this barcode
0559     int bar_width = 1; // the width of the base unit bar
0560 
0561     // this is are mandatory minimum quiet zone
0562     int quiet_zone = bar_width * 10;
0563     //if (quiet_zone < 10) quiet_zone = 10;
0564 
0565     // what kind of area do we have to work with
0566     int draw_width = r.width();
0567     int draw_height = r.height() - 2;
0568 
0569     // L = 51X
0570     // L length of barcode (excluding quite zone) in units same as X and I
0571     // X the width of a bar (pixels in our case)
0572     int L;
0573 
0574     int X = bar_width;
0575 
0576     L = (51 * X);
0577 
0578     // now we have the actual width the barcode will be so can determine the actual
0579     // size of the quiet zone (we assume we center the barcode in the given area
0580     // what should we do if the area is too small????
0581     // At the moment the way the code is written is we will always start at the minimum
0582     // required quiet zone if we don't have enough space.... I guess we'll just have over-run
0583     // to the right
0584     //
0585     // calculate the starting position based on the alignment option
0586     // for left align we don't need to do anything as the values are already setup for it
0587     if (align == Qt::AlignHCenter) {
0588         int nqz = (draw_width - L) / 2;
0589         if (nqz > quiet_zone) quiet_zone = nqz;
0590     } else if (align == Qt::AlignRight) {
0591         quiet_zone = draw_width - (L + quiet_zone);
0592     }
0593     // left : do nothing
0594 
0595     int pos = r.left() + quiet_zone;
0596     int top = r.top();
0597 
0598     if (pPainter) {
0599         pPainter->save();
0600 
0601         QPen oneWide(pPainter->pen());
0602         oneWide.setWidth(1);
0603 #ifndef Q_OS_WIN32
0604         oneWide.setJoinStyle(Qt::MiterJoin);
0605 #endif
0606         pPainter->setPen(oneWide);
0607         pPainter->setBrush(pPainter->pen().color());
0608 
0609         // render open guard
0610         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0611         pos += 2;
0612         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0613         pos ++;
0614 
0615         // render first set
0616         for (int i = 0; i < 6; ++i) {
0617             int b = val[i+1];
0618             for (int w = 0; w < 7; ++w) {
0619                 if (_encodings[b][_upcparenc[val[7]][val[0]][i]][w]) {
0620                     pPainter->fillRect(pos, top, 1, draw_height - 7, pPainter->pen().color());
0621                 }
0622                 pos++;
0623             }
0624         }
0625 
0626         // render center guard
0627         pos++;
0628         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0629         pos += 2;
0630         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0631         pos += 2;
0632 
0633         // render close guard
0634         pPainter->fillRect(pos, top, 1, draw_height, pPainter->pen().color());
0635 
0636         QString parstr = QString::number(val[0]);
0637         QString chkstr = QString::number(val[7]);
0638         QString leftstr = QString().sprintf("%d%d%d%d%d%d",
0639                                             val[1], val[2], val[3], val[4], val[5], val[6]);
0640         pPainter->setFont(QFont(QLatin1String("Arial"), 6));
0641         pPainter->drawText(r.left(), r.top() + draw_height - 12,
0642                            quiet_zone - 2, 12, Qt::AlignRight | Qt::AlignTop,
0643                            parstr);
0644         pPainter->drawText(r.left() + quiet_zone + 3,
0645                            (r.top() + draw_height) - 7,
0646                            42, 10, Qt::AlignHCenter | Qt::AlignTop,
0647                            leftstr);
0648         pPainter->drawText(r.left() + quiet_zone + L + 2, r.top() + draw_height - 12,
0649                            8, 12, Qt::AlignLeft | Qt::AlignTop,
0650                            chkstr);
0651 
0652         pPainter->restore();
0653     }
0654 }
0655