diff options
| author | pinky <> | 2007-01-07 21:41:39 +0000 |
|---|---|---|
| committer | pinky <> | 2007-01-07 21:41:39 +0000 |
| commit | 05bb5d58295cd959c34f1fbcd5b605cd6dafaacc (patch) | |
| tree | 3b3651037037c1617a54ef3d216e8c11ea8cdddf /bin/reportlab/graphics/barcode/code128.py | |
| parent | 62524af2f41454a2302efb21f15a95318d257a76 (diff) | |
Repotrlab 2.0
bzr revid: pinky-b8333ccaab5dad8ff965b6c380fadadf30d5212a
Diffstat (limited to 'bin/reportlab/graphics/barcode/code128.py')
| -rw-r--r-- | bin/reportlab/graphics/barcode/code128.py | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/bin/reportlab/graphics/barcode/code128.py b/bin/reportlab/graphics/barcode/code128.py new file mode 100644 index 00000000000..443edb06c84 --- /dev/null +++ b/bin/reportlab/graphics/barcode/code128.py @@ -0,0 +1,322 @@ +# +# Copyright (c) 2000 Tyler C. Sarna <tsarna@sarna.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Tyler C. Sarna. +# 4. Neither the name of the author nor the names of contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +from reportlab.lib.units import inch +from common import MultiWidthBarcode +from string import digits + +_patterns = { + 0 : 'BaBbBb', 1 : 'BbBaBb', 2 : 'BbBbBa', + 3 : 'AbAbBc', 4 : 'AbAcBb', 5 : 'AcAbBb', + 6 : 'AbBbAc', 7 : 'AbBcAb', 8 : 'AcBbAb', + 9 : 'BbAbAc', 10 : 'BbAcAb', 11 : 'BcAbAb', + 12 : 'AaBbCb', 13 : 'AbBaCb', 14 : 'AbBbCa', + 15 : 'AaCbBb', 16 : 'AbCaBb', 17 : 'AbCbBa', + 18 : 'BbCbAa', 19 : 'BbAaCb', 20 : 'BbAbCa', + 21 : 'BaCbAb', 22 : 'BbCaAb', 23 : 'CaBaCa', + 24 : 'CaAbBb', 25 : 'CbAaBb', 26 : 'CbAbBa', + 27 : 'CaBbAb', 28 : 'CbBaAb', 29 : 'CbBbAa', + 30 : 'BaBaBc', 31 : 'BaBcBa', 32 : 'BcBaBa', + 33 : 'AaAcBc', 34 : 'AcAaBc', 35 : 'AcAcBa', + 36 : 'AaBcAc', 37 : 'AcBaAc', 38 : 'AcBcAa', + 39 : 'BaAcAc', 40 : 'BcAaAc', 41 : 'BcAcAa', + 42 : 'AaBaCc', 43 : 'AaBcCa', 44 : 'AcBaCa', + 45 : 'AaCaBc', 46 : 'AaCcBa', 47 : 'AcCaBa', + 48 : 'CaCaBa', 49 : 'BaAcCa', 50 : 'BcAaCa', + 51 : 'BaCaAc', 52 : 'BaCcAa', 53 : 'BaCaCa', + 54 : 'CaAaBc', 55 : 'CaAcBa', 56 : 'CcAaBa', + 57 : 'CaBaAc', 58 : 'CaBcAa', 59 : 'CcBaAa', + 60 : 'CaDaAa', 61 : 'BbAdAa', 62 : 'DcAaAa', + 63 : 'AaAbBd', 64 : 'AaAdBb', 65 : 'AbAaBd', + 66 : 'AbAdBa', 67 : 'AdAaBb', 68 : 'AdAbBa', + 69 : 'AaBbAd', 70 : 'AaBdAb', 71 : 'AbBaAd', + 72 : 'AbBdAa', 73 : 'AdBaAb', 74 : 'AdBbAa', + 75 : 'BdAbAa', 76 : 'BbAaAd', 77 : 'DaCaAa', + 78 : 'BdAaAb', 79 : 'AcDaAa', 80 : 'AaAbDb', + 81 : 'AbAaDb', 82 : 'AbAbDa', 83 : 'AaDbAb', + 84 : 'AbDaAb', 85 : 'AbDbAa', 86 : 'DaAbAb', + 87 : 'DbAaAb', 88 : 'DbAbAa', 89 : 'BaBaDa', + 90 : 'BaDaBa', 91 : 'DaBaBa', 92 : 'AaAaDc', + 93 : 'AaAcDa', 94 : 'AcAaDa', 95 : 'AaDaAc', + 96 : 'AaDcAa', 97 : 'DaAaAc', 98 : 'DaAcAa', + 99 : 'AaCaDa', 100 : 'AaDaCa', 101 : 'CaAaDa', + 102 : 'DaAaCa', 103 : 'BaAdAb', 104 : 'BaAbAd', + 105 : 'BaAbCb', 106 : 'BcCaAaB' +} + +starta, startb, startc, stop = 103, 104, 105, 106 + +seta = { + ' ' : 0, '!' : 1, '"' : 2, '#' : 3, + '$' : 4, '%' : 5, '&' : 6, '\'' : 7, + '(' : 8, ')' : 9, '*' : 10, '+' : 11, + ',' : 12, '-' : 13, '.' : 14, '/' : 15, + '0' : 16, '1' : 17, '2' : 18, '3' : 19, + '4' : 20, '5' : 21, '6' : 22, '7' : 23, + '8' : 24, '9' : 25, ':' : 26, ';' : 27, + '<' : 28, '=' : 29, '>' : 30, '?' : 31, + '@' : 32, 'A' : 33, 'B' : 34, 'C' : 35, + 'D' : 36, 'E' : 37, 'F' : 38, 'G' : 39, + 'H' : 40, 'I' : 41, 'J' : 42, 'K' : 43, + 'L' : 44, 'M' : 45, 'N' : 46, 'O' : 47, + 'P' : 48, 'Q' : 49, 'R' : 50, 'S' : 51, + 'T' : 52, 'U' : 53, 'V' : 54, 'W' : 55, + 'X' : 56, 'Y' : 57, 'Z' : 58, '[' : 59, + '\\' : 60, ']' : 61, '^' : 62, '_' : 63, + '\x00' : 64, '\x01' : 65, '\x02' : 66, '\x03' : 67, + '\x04' : 68, '\x05' : 69, '\x06' : 70, '\x07' : 71, + '\x08' : 72, '\x09' : 73, '\x0a' : 74, '\x0b' : 75, + '\x0c' : 76, '\x0d' : 77, '\x0e' : 78, '\x0f' : 79, + '\x10' : 80, '\x11' : 81, '\x12' : 82, '\x13' : 83, + '\x14' : 84, '\x15' : 85, '\x16' : 86, '\x17' : 87, + '\x18' : 88, '\x19' : 89, '\x1a' : 90, '\x1b' : 91, + '\x1c' : 92, '\x1d' : 93, '\x1e' : 94, '\x1f' : 95, + '\xf3' : 96, '\xf2' : 97, 'SHIFT' : 98, 'TO_C' : 99, + 'TO_B' : 100, '\xf4' : 101, '\xf1' : 102 +} + +setb = { + ' ' : 0, '!' : 1, '"' : 2, '#' : 3, + '$' : 4, '%' : 5, '&' : 6, '\'' : 7, + '(' : 8, ')' : 9, '*' : 10, '+' : 11, + ',' : 12, '-' : 13, '.' : 14, '/' : 15, + '0' : 16, '1' : 17, '2' : 18, '3' : 19, + '4' : 20, '5' : 21, '6' : 22, '7' : 23, + '8' : 24, '9' : 25, ':' : 26, ';' : 27, + '<' : 28, '=' : 29, '>' : 30, '?' : 31, + '@' : 32, 'A' : 33, 'B' : 34, 'C' : 35, + 'D' : 36, 'E' : 37, 'F' : 38, 'G' : 39, + 'H' : 40, 'I' : 41, 'J' : 42, 'K' : 43, + 'L' : 44, 'M' : 45, 'N' : 46, 'O' : 47, + 'P' : 48, 'Q' : 49, 'R' : 50, 'S' : 51, + 'T' : 52, 'U' : 53, 'V' : 54, 'W' : 55, + 'X' : 56, 'Y' : 57, 'Z' : 58, '[' : 59, + '\\' : 60, ']' : 61, '^' : 62, '_' : 63, + '`' : 64, 'a' : 65, 'b' : 66, 'c' : 67, + 'd' : 68, 'e' : 69, 'f' : 70, 'g' : 71, + 'h' : 72, 'i' : 73, 'j' : 74, 'k' : 75, + 'l' : 76, 'm' : 77, 'n' : 78, 'o' : 79, + 'p' : 80, 'q' : 81, 'r' : 82, 's' : 83, + 't' : 84, 'u' : 85, 'v' : 86, 'w' : 87, + 'x' : 88, 'y' : 89, 'z' : 90, '{' : 91, + '|' : 92, '}' : 93, '~' : 94, '\x7f' : 95, + '\xf3' : 96, '\xf2' : 97, 'SHIFT' : 98, 'TO_C' : 99, + '\xf4' : 100, 'TO_A' : 101, '\xf1' : 102 +} + +setc = { + '00': 0, '01': 1, '02': 2, '03': 3, '04': 4, + '05': 5, '06': 6, '07': 7, '08': 8, '09': 9, + '10':10, '11':11, '12':12, '13':13, '14':14, + '15':15, '16':16, '17':17, '18':18, '19':19, + '20':20, '21':21, '22':22, '23':23, '24':24, + '25':25, '26':26, '27':27, '28':28, '29':29, + '30':30, '31':31, '32':32, '33':33, '34':34, + '35':35, '36':36, '37':37, '38':38, '39':39, + '40':40, '41':41, '42':42, '43':43, '44':44, + '45':45, '46':46, '47':47, '48':48, '49':49, + '50':50, '51':51, '52':52, '53':53, '54':54, + '55':55, '56':56, '57':57, '58':58, '59':59, + '60':60, '61':61, '62':62, '63':63, '64':64, + '65':65, '66':66, '67':67, '68':68, '69':69, + '70':70, '71':71, '72':72, '73':73, '74':74, + '75':75, '76':76, '77':77, '78':78, '79':79, + '80':80, '81':81, '82':82, '83':83, '84':84, + '85':85, '86':86, '87':87, '88':88, '89':89, + '90':90, '91':91, '92':92, '93':93, '94':94, + '95':95, '96':96, '97':97, '98':98, '99':99, + + 'TO_B' : 100, 'TO_A' : 101, '\xf1' : 102 +} + +setmap = { + 'TO_A' : (seta, setb), + 'TO_B' : (setb, seta), + 'TO_C' : (setc, None), + 'START_A' : (starta, seta, setb), + 'START_B' : (startb, setb, seta), + 'START_C' : (startc, setc, None), +} +tos = setmap.keys() + +class Code128(MultiWidthBarcode): + """ + Code 128 is a very compact symbology that can encode the entire + 128 character ASCII set, plus 4 special control codes, + (FNC1-FNC4, expressed in the input string as \xf1 to \xf4). + Code 128 can also encode digits at double density (2 per byte) + and has a mandatory checksum. Code 128 is well supported and + commonly used -- for example, by UPS for tracking labels. + + Because of these qualities, Code 128 is probably the best choice + for a linear symbology today (assuming you have a choice). + + Options that may be passed to constructor: + + value (int, or numeric string. required.): + The value to encode. + + barWidth (float, default .0075): + X-Dimension, or width of the smallest element + Minumum is .0075 inch (7.5 mils). + + barHeight (float, see default below): + Height of the symbol. Default is the height of the two + bearer bars (if they exist) plus the greater of .25 inch + or .15 times the symbol's length. + + quiet (bool, default 1): + Wether to include quiet zones in the symbol. + + lquiet (float, see default below): + Quiet zone size to left of code, if quiet is true. + Default is the greater of .25 inch, or 10 barWidth + + rquiet (float, defaults as above): + Quiet zone size to right left of code, if quiet is true. + + Sources of Information on Code 128: + + http://www.semiconductor.agilent.com/barcode/sg/Misc/code_128.html + http://www.adams1.com/pub/russadam/128code.html + http://www.barcodeman.com/c128.html + + Official Spec, "ANSI/AIM BC4-1999, ISS" is available for US$45 from + http://www.aimglobal.org/aimstore/ + """ + barWidth = inch * 0.0075 + lquiet = None + rquiet = None + quiet = 1 + barHeight = None + def __init__(self, value='', **args): + + if type(value) is type(1): + value = str(value) + + for (k, v) in args.items(): + setattr(self, k, v) + + if self.quiet: + if self.lquiet is None: + self.lquiet = max(inch * 0.25, self.barWidth * 10.0) + if self.rquiet is None: + self.rquiet = max(inch * 0.25, self.barWidth * 10.0) + else: + self.lquiet = self.rquiet = 0.0 + + MultiWidthBarcode.__init__(self, value) + + def validate(self): + vval = "" + self.valid = 1 + for c in self.value: + if ord(c) > 127 and c not in '\xf1\xf2\xf3\xf4': + self.valid = 0 + continue + vval = vval + c + self.validated = vval + return vval + + def _trailingDigitsToC(self, l): + # Optimization: trailing digits -> set C double-digits + c = 1 + savings = -1 # the TO_C costs one character + rl = ['STOP'] + while c < len(l): + i = (-c - 1) + if l[i] == '\xf1': + c = c + 1 + rl.insert(0, '\xf1') + continue + elif len(l[i]) == 1 and l[i] in digits \ + and len(l[i-1]) == 1 and l[i-1] in digits: + c += 2 + savings += 1 + rl.insert(0, l[i-1] + l[i]) + continue + else: + break + if savings > 0: + return l[:-c] + ['TO_C'] + rl + else: + return l + + def encode(self): + # First, encode using only B + s = self.validated + l = ['START_B'] + for c in s: + if not setb.has_key(c): + l = l + ['TO_A', c, 'TO_B'] + else: + l.append(c) + l.append('STOP') + + l = self._trailingDigitsToC(l) + + # Finally, replace START_X,TO_Y with START_Y + if l[1] in tos: + l[:2] = ['START_' + l[1][-1]] + +# print `l` + + # encode into numbers + start, set, shset = setmap[l[0]] + e = [start] + + l = l[1:-1] + while l: + c = l[0] + if c == 'SHIFT': + e = e + [set[c], shset[l[1]]] + l = l[2:] + elif c in tos: + e.append(set[c]) + set, shset = setmap[c] + l = l[1:] + else: + e.append(set[c]) + l = l[1:] + + c = e[0] + for i in range(1, len(e)): + c = c + i * e[i] + self.encoded = e + [c % 103, stop] + return self.encoded + + def decompose(self): + self.decomposed = ''.join([_patterns[c] for c in self.encoded]) + return self.decomposed + + def _humanText(self): + return self.value |
