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 }