File indexing completed on 2024-05-12 04:43:19
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2001-2012 by OpenMFG, LLC 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public 0015 * License along with this library; if not, write to the Free Software 0016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 0017 * Please contact info@openmfg.com with any questions on this license. 0018 */ 0019 0020 /* 0021 * This file contains the implementation of the interleaved 2 of 5 barcode renderer. 0022 * All this code assumes a 100dpi rendering surface for it's calculations. 0023 */ 0024 0025 #include <QString> 0026 #include <QRectF> 0027 #include <QPainter> 0028 #include <QPen> 0029 #include <QBrush> 0030 0031 const char* __i2of5charmap[] = { 0032 "NNWWN", 0033 "WNNNW", 0034 "NWNNW", 0035 "WWNNN", 0036 "NNWNW", 0037 "WNWNN", 0038 "NWWNN", 0039 "NNNWW", 0040 "WNNWN", 0041 "NWNWN" 0042 }; 0043 0044 0045 static QPointF addElement(const QRectF &r, QPointF startPos, qreal width, bool isSpace, QPainter * pPainter) 0046 { 0047 if (!isSpace && pPainter) { 0048 pPainter->fillRect(startPos.x(),startPos.y(), width, r.height(), pPainter->pen().color()); 0049 } 0050 0051 return QPointF(startPos.x() + width, startPos.y()); 0052 } 0053 0054 static QPointF addBar(const QRectF &r, QPointF startPos, qreal width, QPainter * pPainter) 0055 { 0056 return addElement(r, startPos, width, false, pPainter); 0057 } 0058 static QPointF addSpace(const QRectF &r, QPointF startPos, qreal width, QPainter * pPainter) 0059 { 0060 return addElement(r, startPos, width, true, pPainter); 0061 } 0062 0063 0064 void renderI2of5(const QRectF &r, const QString & _str, Qt::Alignment align, QPainter * pPainter) 0065 { 0066 QString str = _str; 0067 qreal narrow_bar = 1; // a narrow bar is 1/100th inch wide 0068 qreal bar_width_mult = 2.5; // the wide bar width multiple of the narrow bar 0069 qreal wide_bar = narrow_bar * bar_width_mult; 0070 0071 if (str.length() % 2) { 0072 str = QLatin1Char('0')+ str; // padding zero if number of characters is not even 0073 } 0074 0075 // this is our mandatory minimum quiet zone 0076 qreal quiet_zone = narrow_bar * 10; 0077 if(quiet_zone < 0.1) { 0078 quiet_zone = 0.1; 0079 } 0080 0081 // what kind of area do we have to work with 0082 int draw_width = r.width(); 0083 0084 // how long is the value we need to encode? 0085 int val_length = str.length(); 0086 0087 // L = (C(2N+3)+6+N)X 0088 // L length of barcode (excluding quite zone 0089 // C the number of characters in the value excluding the start/stop 0090 // N the bar width multiple for wide bars 0091 // X the width of a bar (pixels in our case) 0092 int L; 0093 int C = val_length; 0094 qreal N = bar_width_mult; 0095 qreal X = narrow_bar; 0096 0097 L = (C * (2.0*N + 3.0) + 6.0 + N) * X; 0098 0099 // now we have the actual width the barcode will be so can determine the actual 0100 // size of the quiet zone (we assume we center the barcode in the given area) 0101 // At the moment the way the code is written is we will always start at the minimum 0102 // required quiet zone if we don't have enough space.... I guess we'll just have over-run 0103 // to the right 0104 // 0105 // calculate the starting position based on the alignment option 0106 if (align == Qt::AlignHCenter) { 0107 int nqz = (draw_width - L) / 2.0; 0108 if (nqz > quiet_zone) { 0109 quiet_zone = nqz; 0110 } 0111 } 0112 else if (align == Qt::AlignRight) { 0113 quiet_zone = draw_width - (L + quiet_zone); 0114 } 0115 // left : do nothing 0116 0117 if (pPainter) { 0118 pPainter->save(); 0119 0120 QPen oneWide(pPainter->pen()); 0121 oneWide.setWidth(1); 0122 #ifndef Q_OS_WIN32 0123 oneWide.setJoinStyle(Qt::MiterJoin); 0124 #endif 0125 pPainter->setPen(oneWide); 0126 pPainter->setBrush(pPainter->pen().color()); 0127 } 0128 0129 QPointF pos(r.left() + quiet_zone, r.top()); 0130 0131 // start character 0132 pos = addBar(r, pos, narrow_bar,pPainter); 0133 pos = addSpace(r, pos, narrow_bar, pPainter); 0134 pos = addBar(r, pos, narrow_bar, pPainter); 0135 pos = addSpace(r, pos, narrow_bar, pPainter); 0136 0137 for (int i = 0; i < str.length()-1; i+=2) { 0138 for (int iElt = 0; __i2of5charmap [0][iElt] != '\0'; iElt++) { 0139 for (int offset=0; offset<=1; offset++) { 0140 QChar c = str.at(i+offset); 0141 if (!c.isDigit()) { 0142 break; // invalid character 0143 } 0144 0145 int iChar = c.digitValue(); 0146 int width = __i2of5charmap[iChar][iElt] == 'W' ? wide_bar : narrow_bar; 0147 pos = addElement(r, pos, width, offset==1, pPainter); 0148 } 0149 } 0150 } 0151 0152 // stop character 0153 pos = addBar(r, pos, wide_bar, pPainter); 0154 pos = addSpace(r, pos, narrow_bar, pPainter); 0155 pos = addBar(r, pos, narrow_bar, pPainter); 0156 }