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 3of9 barcode renderer. 0021 * All this code assumes a 100dpi rendering surface for it's calculations. 0022 */ 0023 0024 #include "KReportRenderObjects.h" 0025 0026 #include <QString> 0027 #include <QRectF> 0028 #include <QPen> 0029 #include <QBrush> 0030 #include "kreportplugin_debug.h" 0031 0032 struct code3of9 { 0033 char code; 0034 int values[9]; 0035 }; 0036 0037 const struct code3of9 _3of9codes[] = { 0038 { '0', { 0, 0, 0, 1, 1, 0, 1, 0, 0 } }, 0039 { '1', { 1, 0, 0, 1, 0, 0, 0, 0, 1 } }, 0040 { '2', { 0, 0, 1, 1, 0, 0, 0, 0, 1 } }, 0041 { '3', { 1, 0, 1, 1, 0, 0, 0, 0, 0 } }, 0042 { '4', { 0, 0, 0, 1, 1, 0, 0, 0, 1 } }, 0043 { '5', { 1, 0, 0, 1, 1, 0, 0, 0, 0 } }, 0044 { '6', { 0, 0, 1, 1, 1, 0, 0, 0, 0 } }, 0045 { '7', { 0, 0, 0, 1, 0, 0, 1, 0, 1 } }, 0046 { '8', { 1, 0, 0, 1, 0, 0, 1, 0, 0 } }, 0047 { '9', { 0, 0, 1, 1, 0, 0, 1, 0, 0 } }, 0048 0049 { 'A', { 1, 0, 0, 0, 0, 1, 0, 0, 1 } }, 0050 { 'B', { 0, 0, 1, 0, 0, 1, 0, 0, 1 } }, 0051 { 'C', { 1, 0, 1, 0, 0, 1, 0, 0, 0 } }, 0052 { 'D', { 0, 0, 0, 0, 1, 1, 0, 0, 1 } }, 0053 { 'E', { 1, 0, 0, 0, 1, 1, 0, 0, 0 } }, 0054 { 'F', { 0, 0, 1, 0, 1, 1, 0, 0, 0 } }, 0055 { 'G', { 0, 0, 0, 0, 0, 1, 1, 0, 1 } }, 0056 { 'H', { 1, 0, 0, 0, 0, 1, 1, 0, 0 } }, 0057 { 'I', { 0, 0, 1, 0, 0, 1, 1, 0, 0 } }, 0058 { 'J', { 0, 0, 0, 0, 1, 1, 1, 0, 0 } }, 0059 { 'K', { 1, 0, 0, 0, 0, 0, 0, 1, 1 } }, 0060 { 'L', { 0, 0, 1, 0, 0, 0, 0, 1, 1 } }, 0061 { 'M', { 1, 0, 1, 0, 0, 0, 0, 1, 0 } }, 0062 { 'N', { 0, 0, 0, 0, 1, 0, 0, 1, 1 } }, 0063 { 'O', { 1, 0, 0, 0, 1, 0, 0, 1, 0 } }, 0064 { 'P', { 0, 0, 1, 0, 1, 0, 0, 1, 0 } }, 0065 { 'Q', { 0, 0, 0, 0, 0, 0, 1, 1, 1 } }, 0066 { 'R', { 1, 0, 0, 0, 0, 0, 1, 1, 0 } }, 0067 { 'S', { 0, 0, 1, 0, 0, 0, 1, 1, 0 } }, 0068 { 'T', { 0, 0, 0, 0, 1, 0, 1, 1, 0 } }, 0069 { 'U', { 1, 1, 0, 0, 0, 0, 0, 0, 1 } }, 0070 { 'V', { 0, 1, 1, 0, 0, 0, 0, 0, 1 } }, 0071 { 'W', { 1, 1, 1, 0, 0, 0, 0, 0, 0 } }, 0072 { 'X', { 0, 1, 0, 0, 1, 0, 0, 0, 1 } }, 0073 { 'Y', { 1, 1, 0, 0, 1, 0, 0, 0, 0 } }, 0074 { 'Z', { 0, 1, 1, 0, 1, 0, 0, 0, 0 } }, 0075 0076 { '-', { 0, 1, 0, 0, 0, 0, 1, 0, 1 } }, 0077 { '.', { 1, 1, 0, 0, 0, 0, 1, 0, 0 } }, 0078 { ' ', { 0, 1, 1, 0, 0, 0, 1, 0, 0 } }, 0079 { '$', { 0, 1, 0, 1, 0, 1, 0, 0, 0 } }, 0080 { '/', { 0, 1, 0, 1, 0, 0, 0, 1, 0 } }, 0081 { '+', { 0, 1, 0, 0, 0, 1, 0, 1, 0 } }, 0082 { '%', { 0, 0, 0, 1, 0, 1, 0, 1, 0 } }, 0083 0084 { '*', { 0, 1, 0, 0, 1, 0, 1, 0, 0 } }, // this is a special start/stop character 0085 0086 { '\0', { 0, 0, 0, 0, 0, 0, 0, 0, 0 } } // null termininator of list 0087 }; 0088 0089 int codeIndex(QChar code) 0090 { 0091 // we are a case insensitive search 0092 const char latin1Code = code.toUpper().toLatin1(); 0093 for (int idx = 0; _3of9codes[idx].code != '\0'; idx++) { 0094 if (_3of9codes[idx].code == latin1Code) return idx; 0095 } 0096 return -1; // couldn't find it 0097 } 0098 0099 0100 void render3of9(OROPage * page, const QRectF & r, const QString & _str, Qt::Alignment align) 0101 { 0102 QString str = _str; 0103 // lets determine some core attributes about this barcode 0104 qreal narrow_bar = 1; // a narrow bar is 1/100th inch wide 0105 qreal interchange_gap = narrow_bar; // the space between each 'set' of bars 0106 int bar_width_mult = 2; // the wide bar width multiple of the narrow bar 0107 0108 // this is our mandatory minimum quiet zone 0109 qreal quiet_zone = narrow_bar * 10; 0110 if (quiet_zone < 0.1) 0111 quiet_zone = 0.1; 0112 0113 // what kind of area do we have to work with 0114 qreal draw_width = r.width(); 0115 qreal draw_height = r.height(); 0116 0117 // how long is the value we need to encode? 0118 int val_length = str.length(); 0119 0120 // L = (C + 2)(3N + 6)X + (C + 1)I 0121 // L length of barcode (excluding quite zone) in units same as X and I 0122 // C the number of characters in the value excluding the start/stop 0123 // N the bar width multiple for wide bars 0124 // X the width of a bar (pixels in our case) 0125 // I the interchange gap in the same units as X (value is same as X for our case) 0126 qreal L; 0127 0128 qreal C = val_length; 0129 qreal N = bar_width_mult; 0130 qreal X = narrow_bar; 0131 qreal I = interchange_gap; 0132 0133 L = ((C + 2.0) * (3.0 * N + 6.0) * X) + ((C + 1.0) * I); 0134 0135 // now we have the actual width the barcode will be so can determine the actual 0136 // size of the quiet zone (we assume we center the barcode in the given area 0137 // what should we do if the area is too small???? 0138 // At the moment the way the code is written is we will always start at the minimum 0139 // required quiet zone if we don't have enough space.... I guess we'll just have over-run 0140 // to the right 0141 // 0142 // calculate the starting position based on the alignment option 0143 // for left align we don't need to do anything as the values are already setup for it 0144 if (align == Qt::AlignHCenter) { 0145 qreal nqz = (draw_width - L) / 2.0; 0146 if (nqz > quiet_zone) 0147 quiet_zone = nqz; 0148 } else if (align == Qt::AlignRight) { 0149 quiet_zone = draw_width - (L + quiet_zone); 0150 } 0151 //else if(align < 1) {} // left : do nothing 0152 0153 qreal pos = r.left() + quiet_zone; 0154 qreal top = r.top(); 0155 0156 // ok we need to prepend and append the str with a * 0157 //str = QString().sprintf("*%s*",(const char*)str); 0158 str = QLatin1Char('*') + str + QLatin1Char('*'); 0159 0160 QPen pen(Qt::NoPen); 0161 QBrush brush(QColor("black")); 0162 for (int i = 0; i < str.length(); i++) { 0163 // loop through each char and render the barcode 0164 QChar c = str.at(i); 0165 int idx = codeIndex(c); 0166 //kreportpluginDebug() << idx; 0167 if (idx == -1) { 0168 kreportpluginWarning() << "Encountered a non-compliant character while rendering a 3of9 barcode -- skipping"; 0169 continue; 0170 } 0171 0172 bool space = false; 0173 for (int b = 0; b < 9; b++, space = !space) { 0174 qreal w = (_3of9codes[idx].values[b] == 1 ? narrow_bar * bar_width_mult : narrow_bar); 0175 //kreportpluginDebug() << w << space; 0176 if (!space) { 0177 ORORect * rect = new ORORect(); 0178 rect->setPen(pen); 0179 rect->setBrush(brush); 0180 rect->setRect(QRectF(pos, top, w, draw_height)); 0181 page->insertPrimitive(rect); 0182 } 0183 pos += w; 0184 } 0185 pos += interchange_gap; 0186 } 0187 }