Barcode extension of reportlab
bzr revid: fp@tinyerp.com-b01bb6f0fe82521d3492a38e8215bdc3285d4442
This commit is contained in:
parent
5805984b73
commit
d60676539b
|
@ -0,0 +1,33 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 1996-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.
|
||||||
|
#
|
||||||
|
|
||||||
|
__version__ = '0.9'
|
|
@ -0,0 +1,321 @@
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
Minumum is .0075 inch (7.5 mils).
|
||||||
|
|
||||||
|
height (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 xdim
|
||||||
|
|
||||||
|
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/
|
||||||
|
"""
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.xdim = inch * 0.0275
|
||||||
|
self.lquiet = None
|
||||||
|
self.rquiet = None
|
||||||
|
self.quiet = 1
|
||||||
|
self.height = None
|
||||||
|
|
||||||
|
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.xdim * 10.0)
|
||||||
|
self.rquiet = max(inch * 0.25, self.xdim * 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 = c + 2
|
||||||
|
savings = 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):
|
||||||
|
dval = ''
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + _patterns[c]
|
||||||
|
self.decomposed = dval
|
||||||
|
return self.decomposed
|
|
@ -0,0 +1,255 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 1996-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 Barcode
|
||||||
|
import string
|
||||||
|
|
||||||
|
_patterns = {
|
||||||
|
'0': ("bsbSBsBsb", 0), '1': ("BsbSbsbsB", 1),
|
||||||
|
'2': ("bsBSbsbsB", 2), '3': ("BsBSbsbsb", 3),
|
||||||
|
'4': ("bsbSBsbsB", 4), '5': ("BsbSBsbsb", 5),
|
||||||
|
'6': ("bsBSBsbsb", 6), '7': ("bsbSbsBsB", 7),
|
||||||
|
'8': ("BsbSbsBsb", 8), '9': ("bsBSbsBsb", 9),
|
||||||
|
'A': ("BsbsbSbsB", 10), 'B': ("bsBsbSbsB", 11),
|
||||||
|
'C': ("BsBsbSbsb", 12), 'D': ("bsbsBSbsB", 13),
|
||||||
|
'E': ("BsbsBSbsb", 14), 'F': ("bsBsBSbsb", 15),
|
||||||
|
'G': ("bsbsbSBsB", 16), 'H': ("BsbsbSBsb", 17),
|
||||||
|
'I': ("bsBsbSBsb", 18), 'J': ("bsbsBSBsb", 19),
|
||||||
|
'K': ("BsbsbsbSB", 20), 'L': ("bsBsbsbSB", 21),
|
||||||
|
'M': ("BsBsbsbSb", 22), 'N': ("bsbsBsbSB", 23),
|
||||||
|
'O': ("BsbsBsbSb", 24), 'P': ("bsBsBsbSb", 25),
|
||||||
|
'Q': ("bsbsbsBSB", 26), 'R': ("BsbsbsBSb", 27),
|
||||||
|
'S': ("bsBsbsBSb", 28), 'T': ("bsbsBsBSb", 29),
|
||||||
|
'U': ("BSbsbsbsB", 30), 'V': ("bSBsbsbsB", 31),
|
||||||
|
'W': ("BSBsbsbsb", 32), 'X': ("bSbsBsbsB", 33),
|
||||||
|
'Y': ("BSbsBsbsb", 34), 'Z': ("bSBsBsbsb", 35),
|
||||||
|
'-': ("bSbsbsBsB", 36), '.': ("BSbsbsBsb", 37),
|
||||||
|
' ': ("bSBsbsBsb", 38), '*': ("bSbsBsBsb", 39),
|
||||||
|
'$': ("bSbSbSbsb", 40), '/': ("bSbSbsbSb", 41),
|
||||||
|
'+': ("bSbsbSbSb", 42), '%': ("bsbSbSbSb", 43)
|
||||||
|
}
|
||||||
|
|
||||||
|
_valchars = [
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
|
||||||
|
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||||
|
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||||
|
'X', 'Y', 'Z', '-', '.', ' ', '*', '$', '/', '+', '%'
|
||||||
|
]
|
||||||
|
|
||||||
|
_extended = {
|
||||||
|
'\0': "%U", '\01': "$A", '\02': "$B", '\03': "$C",
|
||||||
|
'\04': "$D", '\05': "$E", '\06': "$F", '\07': "$G",
|
||||||
|
'\010': "$H", '\011': "$I", '\012': "$J", '\013': "$K",
|
||||||
|
'\014': "$L", '\015': "$M", '\016': "$N", '\017': "$O",
|
||||||
|
'\020': "$P", '\021': "$Q", '\022': "$R", '\023': "$S",
|
||||||
|
'\024': "$T", '\025': "$U", '\026': "$V", '\027': "$W",
|
||||||
|
'\030': "$X", '\031': "$Y", '\032': "$Z", '\033': "%A",
|
||||||
|
'\034': "%B", '\035': "%C", '\036': "%D", '\037': "%E",
|
||||||
|
'!': "/A", '"': "/B", '#': "/C", '$': "/D",
|
||||||
|
'%': "/E", '&': "/F", '\'': "/G", '(': "/H",
|
||||||
|
')': "/I", '*': "/J", '+': "/K", ',': "/L",
|
||||||
|
'/': "/O", ':': "/Z", ';': "%F", '<': "%G",
|
||||||
|
'=': "%H", '>': "%I", '?': "%J", '@': "%V",
|
||||||
|
'[': "%K", '\\': "%L", ']': "%M", '^': "%N",
|
||||||
|
'_': "%O", '`': "%W", 'a': "+A", 'b': "+B",
|
||||||
|
'c': "+C", 'd': "+D", 'e': "+E", 'f': "+F",
|
||||||
|
'g': "+G", 'h': "+H", 'i': "+I", 'j': "+J",
|
||||||
|
'k': "+K", 'l': "+L", 'm': "+M", 'n': "+N",
|
||||||
|
'o': "+O", 'p': "+P", 'q': "+Q", 'r': "+R",
|
||||||
|
's': "+S", 't': "+T", 'u': "+U", 'v': "+V",
|
||||||
|
'w': "+W", 'x': "+X", 'y': "+Y", 'z': "+Z",
|
||||||
|
'{': "%P", '|': "%Q", '}': "%R", '~': "%S",
|
||||||
|
'\177': "%T"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_stdchrs = string.digits + string.uppercase + "-. *$/+%"
|
||||||
|
_extchrs = _stdchrs + string.lowercase + \
|
||||||
|
"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" + \
|
||||||
|
"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" + \
|
||||||
|
"!'#&\"(),:;<=>?@[\\]^_`{|}~\177"
|
||||||
|
|
||||||
|
|
||||||
|
def _encode39(str, cksum):
|
||||||
|
newval = "*"
|
||||||
|
v = 0
|
||||||
|
for c in str:
|
||||||
|
v = v + _patterns[c][1]
|
||||||
|
newval = newval + c
|
||||||
|
v = v % 43
|
||||||
|
if cksum:
|
||||||
|
newval = newval + _valchars[v]
|
||||||
|
return newval + '*'
|
||||||
|
|
||||||
|
|
||||||
|
class _Code39Base(Barcode):
|
||||||
|
def __init__(self, value = "", **args):
|
||||||
|
self.xdim = inch * 0.0075
|
||||||
|
self.lquiet = None
|
||||||
|
self.rquiet = None
|
||||||
|
self.quiet = 1
|
||||||
|
self.gap = None
|
||||||
|
self.height = None
|
||||||
|
self.ratio = 2.2
|
||||||
|
self.checksum = 0
|
||||||
|
self.bearers = 0.0
|
||||||
|
|
||||||
|
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.xdim * 10.0)
|
||||||
|
self.rquiet = max(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = ""
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + _patterns[c][0] + 'i'
|
||||||
|
self.decomposed = dval[:-1]
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
|
||||||
|
class Standard39(_Code39Base):
|
||||||
|
"""
|
||||||
|
Interleaved 2 of 5 is a numeric-only barcode. It encodes an even
|
||||||
|
number of digits; if an odd number is given, a 0 is prepended.
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (int, or numeric string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
Minumum is .0075 inch (7.5 mils).
|
||||||
|
|
||||||
|
ratio (float, default 2.2):
|
||||||
|
The ratio of wide elements to narrow elements.
|
||||||
|
Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
|
||||||
|
xdim is greater than 20 mils (.02 inch))
|
||||||
|
|
||||||
|
gap (float or None, default None):
|
||||||
|
width of intercharacter gap. None means "use xdim".
|
||||||
|
|
||||||
|
height (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.
|
||||||
|
|
||||||
|
checksum (bool, default 0):
|
||||||
|
Wether to compute and include the check digit
|
||||||
|
|
||||||
|
bearers (float, in units of xdim. default 0):
|
||||||
|
Height of bearer bars (horizontal bars along the top and
|
||||||
|
bottom of the barcode). Default is 0 (no bearers).
|
||||||
|
|
||||||
|
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 .15 times the symbol's
|
||||||
|
length.
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on Code 39:
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/code_39.html
|
||||||
|
http://www.adams1.com/pub/russadam/39code.html
|
||||||
|
http://www.barcodeman.com/c39_1.html
|
||||||
|
|
||||||
|
Official Spec, "ANSI/AIM BC1-1995, USS" is available for US$45 from
|
||||||
|
http://www.aimglobal.org/aimstore/
|
||||||
|
"""
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in self.value:
|
||||||
|
if c in string.lowercase:
|
||||||
|
c = string.upper(c)
|
||||||
|
if c not in _stdchrs:
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = _encode39(self.validated, self.checksum)
|
||||||
|
return self.encoded
|
||||||
|
|
||||||
|
|
||||||
|
class Extended39(_Code39Base):
|
||||||
|
"""
|
||||||
|
Extended Code 39 is a convention for encoding additional characters
|
||||||
|
not present in stanmdard Code 39 by using pairs of characters to
|
||||||
|
represent the characters missing in Standard Code 39.
|
||||||
|
|
||||||
|
See Standard39 for arguments.
|
||||||
|
|
||||||
|
Sources of Information on Extended Code 39:
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/xcode_39.html
|
||||||
|
http://www.barcodeman.com/c39_ext.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in self.value:
|
||||||
|
if c not in _extchrs:
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = ""
|
||||||
|
for c in self.validated:
|
||||||
|
if _extended.has_key(c):
|
||||||
|
self.encoded = self.encoded + _extended[c]
|
||||||
|
elif c in _stdchrs:
|
||||||
|
self.encoded = self.encoded + c
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
self.encoded = _encode39(self.encoded, self.checksum)
|
||||||
|
return self.encoded
|
|
@ -0,0 +1,232 @@
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
import string
|
||||||
|
|
||||||
|
_patterns = {
|
||||||
|
'0' : ('AcAaAb', 0), '1' : ('AaAbAc', 1), '2' : ('AaAcAb', 2),
|
||||||
|
'3' : ('AaAdAa', 3), '4' : ('AbAaAc', 4), '5' : ('AbAbAb', 5),
|
||||||
|
'6' : ('AbAcAa', 6), '7' : ('AaAaAd', 7), '8' : ('AcAbAa', 8),
|
||||||
|
'9' : ('AdAaAa', 9), 'A' : ('BaAaAc', 10), 'B' : ('BaAbAb', 11),
|
||||||
|
'C' : ('BaAcAa', 12), 'D' : ('BbAaAb', 13), 'E' : ('BbAbAa', 14),
|
||||||
|
'F' : ('BcAaAa', 15), 'G' : ('AaBaAc', 16), 'H' : ('AaBbAb', 17),
|
||||||
|
'I' : ('AaBcAa', 18), 'J' : ('AbBaAb', 19), 'K' : ('AcBaAa', 20),
|
||||||
|
'L' : ('AaAaBc', 21), 'M' : ('AaAbBb', 22), 'N' : ('AaAcBa', 23),
|
||||||
|
'O' : ('AbAaBb', 24), 'P' : ('AcAaBa', 25), 'Q' : ('BaBaAb', 26),
|
||||||
|
'R' : ('BaBbAa', 27), 'S' : ('BaAaBb', 28), 'T' : ('BaAbBa', 29),
|
||||||
|
'U' : ('BbAaBa', 30), 'V' : ('BbBaAa', 31), 'W' : ('AaBaBb', 32),
|
||||||
|
'X' : ('AaBbBa', 33), 'Y' : ('AbBaBa', 34), 'Z' : ('AbCaAa', 35),
|
||||||
|
'-' : ('AbAaCa', 36), '.' : ('CaAaAb', 37), ' ' : ('CaAbAa', 38),
|
||||||
|
'$' : ('CbAaAa', 39), '/' : ('AaBaCa', 40), '+' : ('AaCaBa', 41),
|
||||||
|
'%' : ('BaAaCa', 42), '#' : ('AbAbBa', 43), '!' : ('CaBaAa', 44),
|
||||||
|
'=' : ('CaAaBa', 45), '&' : ('AbBbAa', 46),
|
||||||
|
'start' : ('AaAaDa', -1), 'stop' : ('AaAaDaA', -2)
|
||||||
|
}
|
||||||
|
|
||||||
|
_charsbyval = {}
|
||||||
|
for k, v in _patterns.items():
|
||||||
|
_charsbyval[v[1]] = k
|
||||||
|
|
||||||
|
_extended = {
|
||||||
|
'\x00' : '!U', '\x01' : '#A', '\x02' : '#B', '\x03' : '#C',
|
||||||
|
'\x04' : '#D', '\x05' : '#E', '\x06' : '#F', '\x07' : '#G',
|
||||||
|
'\x08' : '#H', '\x09' : '#I', '\x0a' : '#J', '\x0b' : '#K',
|
||||||
|
'\x0c' : '#L', '\x0d' : '#M', '\x0e' : '#N', '\x0f' : '#O',
|
||||||
|
'\x10' : '#P', '\x11' : '#Q', '\x12' : '#R', '\x13' : '#S',
|
||||||
|
'\x14' : '#T', '\x15' : '#U', '\x16' : '#V', '\x17' : '#W',
|
||||||
|
'\x18' : '#X', '\x19' : '#Y', '\x1a' : '#Z', '\x1b' : '!A',
|
||||||
|
'\x1c' : '!B', '\x1d' : '!C', '\x1e' : '!D', '\x1f' : '!E',
|
||||||
|
'!' : '=A', '"' : '=B', '#' : '=C', '$' : '=D',
|
||||||
|
'%' : '=E', '&' : '=F', '\'' : '=G', '(' : '=H',
|
||||||
|
')' : '=I', '*' : '=J', '+' : '=K', ',' : '=L',
|
||||||
|
'/' : '=O', ':' : '=Z', ';' : '!F', '<' : '!G',
|
||||||
|
'=' : '!H', '>' : '!I', '?' : '!J', '@' : '!V',
|
||||||
|
'[' : '!K', '\\' : '!L', ']' : '!M', '^' : '!N',
|
||||||
|
'_' : '!O', '`' : '!W', 'a' : '&A', 'b' : '&B',
|
||||||
|
'c' : '&C', 'd' : '&D', 'e' : '&E', 'f' : '&F',
|
||||||
|
'g' : '&G', 'h' : '&H', 'i' : '&I', 'j' : '&J',
|
||||||
|
'k' : '&K', 'l' : '&L', 'm' : '&M', 'n' : '&N',
|
||||||
|
'o' : '&O', 'p' : '&P', 'q' : '&Q', 'r' : '&R',
|
||||||
|
's' : '&S', 't' : '&T', 'u' : '&U', 'v' : '&V',
|
||||||
|
'w' : '&W', 'x' : '&X', 'y' : '&Y', 'z' : '&Z',
|
||||||
|
'{' : '!P', '|' : '!Q', '}' : '!R', '~' : '!S',
|
||||||
|
'\x7f' : '!T'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _encode93(str):
|
||||||
|
s = map(None, str)
|
||||||
|
s.reverse()
|
||||||
|
|
||||||
|
# compute 'C' checksum
|
||||||
|
i = 0; v = 1; c = 0
|
||||||
|
while i < len(s):
|
||||||
|
c = c + v * _patterns[s[i]][1]
|
||||||
|
i = i + 1; v = v + 1
|
||||||
|
if v > 20:
|
||||||
|
v = 1
|
||||||
|
s.insert(0, _charsbyval[c % 47])
|
||||||
|
|
||||||
|
# compute 'K' checksum
|
||||||
|
i = 0; v = 1; c = 0
|
||||||
|
while i < len(s):
|
||||||
|
c = c + v * _patterns[s[i]][1]
|
||||||
|
i = i + 1; v = v + 1
|
||||||
|
if v > 15:
|
||||||
|
v = 1
|
||||||
|
s.insert(0, _charsbyval[c % 47])
|
||||||
|
|
||||||
|
s.reverse()
|
||||||
|
|
||||||
|
return string.join(s, '')
|
||||||
|
|
||||||
|
|
||||||
|
class _Code93Base(MultiWidthBarcode):
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.xdim = inch * 0.0075
|
||||||
|
self.lquiet = None
|
||||||
|
self.rquiet = None
|
||||||
|
self.quiet = 1
|
||||||
|
self.height = None
|
||||||
|
|
||||||
|
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.xdim * 10.0)
|
||||||
|
self.rquiet = max(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
MultiWidthBarcode.__init__(self, value)
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = _patterns['start'][0]
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + _patterns[c][0]
|
||||||
|
self.decomposed = dval + _patterns['stop'][0]
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
|
||||||
|
class Standard93(_Code93Base):
|
||||||
|
"""
|
||||||
|
Code 93 is a Uppercase alphanumeric symbology with some punctuation.
|
||||||
|
See Extended Code 93 for a variant that can represent the entire
|
||||||
|
128 characrter ASCII set.
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (int, or numeric string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
Minumum is .0075 inch (7.5 mils).
|
||||||
|
|
||||||
|
height (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 xdim
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on Code 93:
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/code_93.html
|
||||||
|
|
||||||
|
Official Spec, "NSI/AIM BC5-1995, USS" is available for US$45 from
|
||||||
|
http://www.aimglobal.org/aimstore/
|
||||||
|
"""
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in self.value:
|
||||||
|
if c in string.lowercase:
|
||||||
|
c = string.upper(c)
|
||||||
|
if not _patterns.has_key(c):
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = _encode93(self.validated)
|
||||||
|
return self.encoded
|
||||||
|
|
||||||
|
|
||||||
|
class Extended93(_Code93Base):
|
||||||
|
"""
|
||||||
|
Extended Code 93 is a convention for encoding the entire 128 character
|
||||||
|
set using pairs of characters to represent the characters missing in
|
||||||
|
Standard Code 93. It is very much like Extended Code 39 in that way.
|
||||||
|
|
||||||
|
See Standard93 for arguments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in self.value:
|
||||||
|
if not _patterns.has_key(c) and not _extended.has_key(c):
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = ""
|
||||||
|
for c in self.validated:
|
||||||
|
if _patterns.has_key(c):
|
||||||
|
self.encoded = self.encoded + c
|
||||||
|
elif _extended.has_key(c):
|
||||||
|
self.encoded = self.encoded + _extended[c]
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
self.encoded = _encode93(self.encoded)
|
||||||
|
return self.encoded
|
|
@ -0,0 +1,705 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 1996-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.platypus.flowables import Flowable
|
||||||
|
from reportlab.lib.units import inch
|
||||||
|
import string
|
||||||
|
|
||||||
|
class Barcode(Flowable):
|
||||||
|
"""Abstract Base for barcodes. Includes implementations of
|
||||||
|
some methods suitable for the more primitive barcode types"""
|
||||||
|
|
||||||
|
def __init__(self, value = ''):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
if not hasattr(self, 'gap'):
|
||||||
|
self.gap = None
|
||||||
|
|
||||||
|
self.validate()
|
||||||
|
self.encode()
|
||||||
|
#print self.encoded
|
||||||
|
self.decompose()
|
||||||
|
#print self.decomposed
|
||||||
|
self.computeSize()
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.valid = 1
|
||||||
|
self.validated = self.value
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = self.validated
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
self.decomposed = self.encoded
|
||||||
|
|
||||||
|
def computeSize(self, *args):
|
||||||
|
xdim = self.xdim
|
||||||
|
wx = xdim * self.ratio
|
||||||
|
|
||||||
|
if self.gap == None:
|
||||||
|
self.gap = xdim
|
||||||
|
|
||||||
|
w = 0.0
|
||||||
|
|
||||||
|
for c in self.decomposed:
|
||||||
|
if c in 'sb':
|
||||||
|
w = w + xdim
|
||||||
|
elif c in 'SB':
|
||||||
|
w = w + wx
|
||||||
|
else: # 'i'
|
||||||
|
w = w + self.gap
|
||||||
|
|
||||||
|
if self.height is None:
|
||||||
|
self.height = w * 0.15
|
||||||
|
self.height = max(0.25 * inch, self.height)
|
||||||
|
if self.bearers:
|
||||||
|
self.height = self.height + self.bearers * 2.0 * xdim
|
||||||
|
|
||||||
|
if self.quiet:
|
||||||
|
w = w + self.lquiet + self.rquiet
|
||||||
|
self.xo = self.lquiet
|
||||||
|
else:
|
||||||
|
self.xo = 0.0
|
||||||
|
|
||||||
|
self.width = w
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
xdim = self.xdim
|
||||||
|
wx = xdim * self.ratio
|
||||||
|
|
||||||
|
left = self.xo
|
||||||
|
b = self.bearers * xdim
|
||||||
|
bb = b * 0.5
|
||||||
|
tb = self.height - (b * 1.5)
|
||||||
|
|
||||||
|
for c in self.decomposed:
|
||||||
|
if c == 'i':
|
||||||
|
left = left + self.gap
|
||||||
|
elif c == 's':
|
||||||
|
left = left + xdim
|
||||||
|
elif c == 'S':
|
||||||
|
left = left + wx
|
||||||
|
elif c == 'b':
|
||||||
|
self.rect(left, bb, xdim, tb)
|
||||||
|
left = left + xdim
|
||||||
|
elif c == 'B':
|
||||||
|
self.rect(left, bb, wx, tb)
|
||||||
|
left = left + wx
|
||||||
|
|
||||||
|
if self.bearers:
|
||||||
|
self.rect(self.lquiet, 0.0, \
|
||||||
|
self.width - (self.lquiet + self.rquiet), b)
|
||||||
|
self.rect(self.lquiet, self.height - b, \
|
||||||
|
self.width - (self.lquiet + self.rquiet), b)
|
||||||
|
|
||||||
|
def rect(self, x, y, w, h):
|
||||||
|
self.canv.rect(x, y, w, h, stroke=0, fill=1)
|
||||||
|
|
||||||
|
|
||||||
|
class MultiWidthBarcode(Barcode):
|
||||||
|
"""Base for variable-bar-width codes like Code93 and Code128"""
|
||||||
|
|
||||||
|
def computeSize(self, *args):
|
||||||
|
xdim = self.xdim
|
||||||
|
oa, oA = ord('a') - 1, ord('A') - 1
|
||||||
|
|
||||||
|
w = 0.0
|
||||||
|
|
||||||
|
for c in self.decomposed:
|
||||||
|
oc = ord(c)
|
||||||
|
if c in string.lowercase:
|
||||||
|
w = w + xdim * (oc - oa)
|
||||||
|
elif c in string.uppercase:
|
||||||
|
w = w + xdim * (oc - oA)
|
||||||
|
|
||||||
|
if self.height is None:
|
||||||
|
self.height = w * 0.15
|
||||||
|
self.height = max(0.25 * inch, self.height)
|
||||||
|
|
||||||
|
if self.quiet:
|
||||||
|
w = w + self.lquiet + self.rquiet
|
||||||
|
self.xo = self.lquiet
|
||||||
|
else:
|
||||||
|
self.xo = 0.0
|
||||||
|
|
||||||
|
self.width = w
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
oa, oA = ord('a') - 1, ord('A') - 1
|
||||||
|
xdim = self.xdim
|
||||||
|
left = self.xo
|
||||||
|
|
||||||
|
for c in self.decomposed:
|
||||||
|
oc = ord(c)
|
||||||
|
if c in string.lowercase:
|
||||||
|
left = left + (oc - oa) * xdim
|
||||||
|
elif c in string.uppercase:
|
||||||
|
w = (oc - oA) * xdim
|
||||||
|
self.rect(left, 0.0, w, self.height)
|
||||||
|
left = left + w
|
||||||
|
|
||||||
|
|
||||||
|
class I2of5(Barcode):
|
||||||
|
"""
|
||||||
|
Interleaved 2 of 5 is a numeric-only barcode. It encodes an even
|
||||||
|
number of digits; if an odd number is given, a 0 is prepended.
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (int, or numeric string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
Minumum is .0075 inch (7.5 mils).
|
||||||
|
|
||||||
|
ratio (float, default 2.2):
|
||||||
|
The ratio of wide elements to narrow elements.
|
||||||
|
Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
|
||||||
|
xdim is greater than 20 mils (.02 inch))
|
||||||
|
|
||||||
|
gap (float or None, default None):
|
||||||
|
width of intercharacter gap. None means "use xdim".
|
||||||
|
|
||||||
|
height (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.
|
||||||
|
|
||||||
|
checksum (bool, default 1):
|
||||||
|
Wether to compute and include the check digit
|
||||||
|
|
||||||
|
bearers (float, in units of xdim. default 3.0):
|
||||||
|
Height of bearer bars (horizontal bars along the top and
|
||||||
|
bottom of the barcode). Default is 3 x-dimensions.
|
||||||
|
Set to zero for no bearer bars. (Bearer bars help detect
|
||||||
|
misscans, so it is suggested to leave them on).
|
||||||
|
|
||||||
|
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 .15 times the symbol's
|
||||||
|
length.
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on Interleaved 2 of 5:
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/i_25.html
|
||||||
|
http://www.adams1.com/pub/russadam/i25code.html
|
||||||
|
|
||||||
|
Official Spec, "ANSI/AIM BC2-1995, USS" is available for US$45 from
|
||||||
|
http://www.aimglobal.org/aimstore/
|
||||||
|
"""
|
||||||
|
|
||||||
|
patterns = {
|
||||||
|
'start' : 'bsbs',
|
||||||
|
'stop' : 'Bsb',
|
||||||
|
|
||||||
|
'B0' : 'bbBBb', 'S0' : 'ssSSs',
|
||||||
|
'B1' : 'BbbbB', 'S1' : 'SsssS',
|
||||||
|
'B2' : 'bBbbB', 'S2' : 'sSssS',
|
||||||
|
'B3' : 'BBbbb', 'S3' : 'SSsss',
|
||||||
|
'B4' : 'bbBbB', 'S4' : 'ssSsS',
|
||||||
|
'B5' : 'BbBbb', 'S5' : 'SsSss',
|
||||||
|
'B6' : 'bBBbb', 'S6' : 'sSSss',
|
||||||
|
'B7' : 'bbbBB', 'S7' : 'sssSS',
|
||||||
|
'B8' : 'BbbBb', 'S8' : 'SssSs',
|
||||||
|
'B9' : 'bBbBb', 'S9' : 'sSsSs'
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.height = None
|
||||||
|
self.xdim = inch * 0.0075
|
||||||
|
self.ratio = 2.2
|
||||||
|
self.checksum = 1
|
||||||
|
self.bearers = 3.0
|
||||||
|
self.quiet = 1
|
||||||
|
self.lquiet = self.rquiet = None
|
||||||
|
|
||||||
|
if type(value) == 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 = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
self.rquiet = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in string.strip(self.value):
|
||||||
|
if c not in string.digits:
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
s = self.validated
|
||||||
|
|
||||||
|
# make sure result will be a multiple of 2 digits long,
|
||||||
|
# checksum included
|
||||||
|
if ((len(self.validated) % 2 == 0) and self.checksum) \
|
||||||
|
or ((len(self.validated) % 2 == 1) and not self.checksum):
|
||||||
|
s = '0' + s
|
||||||
|
|
||||||
|
if self.checksum:
|
||||||
|
c = 0
|
||||||
|
cm = 3
|
||||||
|
|
||||||
|
for d in s:
|
||||||
|
c = c + cm * int(d)
|
||||||
|
if cm == 3:
|
||||||
|
cm = 1
|
||||||
|
else:
|
||||||
|
cm = 3
|
||||||
|
|
||||||
|
d = 10 - (int(d) % 10)
|
||||||
|
s = s + `d`
|
||||||
|
|
||||||
|
self.encoded = s
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = self.patterns['start']
|
||||||
|
|
||||||
|
for i in range(0, len(self.encoded), 2):
|
||||||
|
b = self.patterns['B' + self.encoded[i]]
|
||||||
|
s = self.patterns['S' + self.encoded[i+1]]
|
||||||
|
|
||||||
|
for i in range(0, len(b)):
|
||||||
|
dval = dval + b[i] + s[i]
|
||||||
|
|
||||||
|
self.decomposed = dval + self.patterns['stop']
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MSI(Barcode):
|
||||||
|
"""
|
||||||
|
MSI is a numeric-only barcode.
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (int, or numeric string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
|
||||||
|
ratio (float, default 2.2):
|
||||||
|
The ratio of wide elements to narrow elements.
|
||||||
|
|
||||||
|
gap (float or None, default None):
|
||||||
|
width of intercharacter gap. None means "use xdim".
|
||||||
|
|
||||||
|
height (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.
|
||||||
|
|
||||||
|
checksum (bool, default 1):
|
||||||
|
Wether to compute and include the check digit
|
||||||
|
|
||||||
|
bearers (float, in units of xdim. default 0):
|
||||||
|
Height of bearer bars (horizontal bars along the top and
|
||||||
|
bottom of the barcode). Default is 0 (no bearers).
|
||||||
|
|
||||||
|
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 xdims.
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on MSI Bar Code:
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/msi_code.html
|
||||||
|
http://www.adams1.com/pub/russadam/plessy.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
patterns = {
|
||||||
|
'start' : 'Bs', 'stop' : 'bSb',
|
||||||
|
|
||||||
|
'0' : 'bSbSbSbS', '1' : 'bSbSbSBs',
|
||||||
|
'2' : 'bSbSBsbS', '3' : 'bSbSBsBs',
|
||||||
|
'4' : 'bSBsbSbS', '5' : 'bSBsbSBs',
|
||||||
|
'6' : 'bSBsBsbS', '7' : 'bSBsBsBs',
|
||||||
|
'8' : 'BsbSbSbS', '9' : 'BsbSbSBs'
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, value="", **args):
|
||||||
|
self.height = None
|
||||||
|
self.xdim = inch * 0.0075
|
||||||
|
self.ratio = 2.2
|
||||||
|
self.checksum = 1
|
||||||
|
self.bearers = 0.0
|
||||||
|
self.quiet = 1
|
||||||
|
self.lquiet = self.rquiet = None
|
||||||
|
|
||||||
|
if type(value) == 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.xdim * 10.0)
|
||||||
|
self.rquiet = max(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
for c in string.strip(self.value):
|
||||||
|
if c not in string.digits:
|
||||||
|
self.valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
s = self.validated
|
||||||
|
|
||||||
|
if self.checksum:
|
||||||
|
c = ''
|
||||||
|
for i in range(1, len(s), 2):
|
||||||
|
c = c + s[i]
|
||||||
|
d = str(int(c) * 2)
|
||||||
|
t = 0
|
||||||
|
for c in d:
|
||||||
|
t = t + int(c)
|
||||||
|
for i in range(0, len(s), 2):
|
||||||
|
t = t + int(s[i])
|
||||||
|
c = 10 - (t % 10)
|
||||||
|
|
||||||
|
s = s + str(c)
|
||||||
|
|
||||||
|
self.encoded = s
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = self.patterns['start']
|
||||||
|
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + self.patterns[c]
|
||||||
|
|
||||||
|
self.decomposed = dval + self.patterns['stop']
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Codabar(Barcode):
|
||||||
|
"""
|
||||||
|
Codabar is a numeric plus some puntuation ("-$:/.+") barcode
|
||||||
|
with four start/stop characters (A, B, C, and D).
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0065):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
minimum is 6.5 mils (.0065 inch)
|
||||||
|
|
||||||
|
ratio (float, default 2.0):
|
||||||
|
The ratio of wide elements to narrow elements.
|
||||||
|
|
||||||
|
gap (float or None, default None):
|
||||||
|
width of intercharacter gap. None means "use xdim".
|
||||||
|
|
||||||
|
height (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.
|
||||||
|
|
||||||
|
checksum (bool, default 0):
|
||||||
|
Wether to compute and include the check digit
|
||||||
|
|
||||||
|
bearers (float, in units of xdim. default 0):
|
||||||
|
Height of bearer bars (horizontal bars along the top and
|
||||||
|
bottom of the barcode). Default is 0 (no bearers).
|
||||||
|
|
||||||
|
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 xdim
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on Codabar
|
||||||
|
|
||||||
|
http://www.semiconductor.agilent.com/barcode/sg/Misc/codabar.html
|
||||||
|
http://www.barcodeman.com/codabar.html
|
||||||
|
|
||||||
|
Official Spec, "ANSI/AIM BC3-1995, USS" is available for US$45 from
|
||||||
|
http://www.aimglobal.org/aimstore/
|
||||||
|
"""
|
||||||
|
|
||||||
|
patterns = {
|
||||||
|
'0': 'bsbsbSB', '1': 'bsbsBSb', '2': 'bsbSbsB',
|
||||||
|
'3': 'BSbsbsb', '4': 'bsBsbSb', '5': 'BsbsbSb',
|
||||||
|
'6': 'bSbsbsB', '7': 'bSbsBsb', '8': 'bSBsbsb',
|
||||||
|
'9': 'BsbSbsb', '-': 'bsbSBsb', '$': 'bsBSbsb',
|
||||||
|
':': 'BsbsBsB', '/': 'BsBsbsB', '.': 'BsBsBsb',
|
||||||
|
'+': 'bsBsBsB', 'A': 'bsBSbSb', 'B': 'bSbSbsB',
|
||||||
|
'C': 'bsbSbSB', 'D': 'bsbSBSb'
|
||||||
|
}
|
||||||
|
|
||||||
|
values = {
|
||||||
|
'0' : 0, '1' : 1, '2' : 2, '3' : 3, '4' : 4,
|
||||||
|
'5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9,
|
||||||
|
'-' : 10, '$' : 11, ':' : 12, '/' : 13, '.' : 14,
|
||||||
|
'+' : 15, 'A' : 16, 'B' : 17, 'C' : 18, 'D' : 19
|
||||||
|
}
|
||||||
|
|
||||||
|
chars = string.digits + "-$:/.+"
|
||||||
|
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.height = None
|
||||||
|
self.xdim = inch * 0.0065
|
||||||
|
self.ratio = 2.0 # XXX ?
|
||||||
|
self.checksum = 0
|
||||||
|
self.bearers = 0.0
|
||||||
|
self.quiet = 1
|
||||||
|
self.lquiet = self.rquiet = None
|
||||||
|
|
||||||
|
if type(value) == 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 = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
self.rquiet = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
s = string.strip(self.value)
|
||||||
|
for i in range(0, len(s)):
|
||||||
|
c = s[i]
|
||||||
|
if c not in self.chars:
|
||||||
|
if ((i != 0) and (i != len(s) - 1)) or (c not in 'ABCD'):
|
||||||
|
self.Valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
|
||||||
|
if vval[0] not in 'ABCD':
|
||||||
|
vval = 'A' + vval
|
||||||
|
if vval[-1] not in 'ABCD':
|
||||||
|
vval = vval + vval[0]
|
||||||
|
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
s = self.validated
|
||||||
|
|
||||||
|
if self.checksum:
|
||||||
|
v = 0
|
||||||
|
for c in s:
|
||||||
|
v = v + self.values[v]
|
||||||
|
v = 16 - (v % 16)
|
||||||
|
s = s + self.chars[v]
|
||||||
|
|
||||||
|
self.encoded = s
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = ""
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + self.patterns[c] + 'i'
|
||||||
|
self.decomposed = dval[:-1]
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Code11(Barcode):
|
||||||
|
"""
|
||||||
|
Code 11 is an almost-numeric barcode. It encodes the digits 0-9 plus
|
||||||
|
dash ("-"). 11 characters total, hence the name.
|
||||||
|
|
||||||
|
value (int or string. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
xdim (float, default .0075):
|
||||||
|
X-Dimension, or width of the smallest element
|
||||||
|
|
||||||
|
ratio (float, default 2.2):
|
||||||
|
The ratio of wide elements to narrow elements.
|
||||||
|
|
||||||
|
gap (float or None, default None):
|
||||||
|
width of intercharacter gap. None means "use xdim".
|
||||||
|
|
||||||
|
height (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.
|
||||||
|
|
||||||
|
checksum (0 none, 1 1-digit, 2 2-digit, -1 auto, default -1):
|
||||||
|
How many checksum digits to include. -1 ("auto") means
|
||||||
|
1 if the number of digits is 10 or less, else 2.
|
||||||
|
|
||||||
|
bearers (float, in units of xdim. default 0):
|
||||||
|
Height of bearer bars (horizontal bars along the top and
|
||||||
|
bottom of the barcode). Default is 0 (no bearers).
|
||||||
|
|
||||||
|
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 xdim
|
||||||
|
|
||||||
|
rquiet (float, defaults as above):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of Information on Code 11:
|
||||||
|
|
||||||
|
http://www.cwi.nl/people/dik/english/codes/barcodes.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
chars = string.digits + '-'
|
||||||
|
|
||||||
|
patterns = {
|
||||||
|
'0' : 'bsbsB', '1' : 'BsbsB', '2' : 'bSbsB',
|
||||||
|
'3' : 'BSbsb', '4' : 'bsBsB', '5' : 'BsBsb',
|
||||||
|
'6' : 'bSBsb', '7' : 'bsbSB', '8' : 'BsbSb',
|
||||||
|
'9' : 'Bsbsb', '-' : 'bsBsb', 'S' : 'bsBSb' # Start/Stop
|
||||||
|
}
|
||||||
|
|
||||||
|
values = {
|
||||||
|
'0' : 0, '1' : 1, '2' : 2, '3' : 3, '4' : 4,
|
||||||
|
'5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9,
|
||||||
|
'-' : 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.height = None
|
||||||
|
self.xdim = inch * 0.0075
|
||||||
|
self.ratio = 2.2 # XXX ?
|
||||||
|
self.checksum = -1 # Auto
|
||||||
|
self.bearers = 0.0
|
||||||
|
self.quiet = 1
|
||||||
|
self.lquiet = self.rquiet = None
|
||||||
|
|
||||||
|
if type(value) == 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 = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
self.rquiet = min(inch * 0.25, self.xdim * 10.0)
|
||||||
|
else:
|
||||||
|
self.lquiet = self.rquiet = 0.0
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
vval = ""
|
||||||
|
self.valid = 1
|
||||||
|
s = string.strip(self.value)
|
||||||
|
for i in range(0, len(s)):
|
||||||
|
c = s[i]
|
||||||
|
if c not in self.chars:
|
||||||
|
self.Valid = 0
|
||||||
|
continue
|
||||||
|
vval = vval + c
|
||||||
|
|
||||||
|
self.validated = vval
|
||||||
|
return vval
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
s = self.validated
|
||||||
|
|
||||||
|
if self.checksum == -1:
|
||||||
|
if len(s) <= 10:
|
||||||
|
self.checksum = 1
|
||||||
|
else:
|
||||||
|
self.checksum = 2
|
||||||
|
|
||||||
|
if self.checksum > 0:
|
||||||
|
# compute first checksum
|
||||||
|
i = 0; v = 1; c = 0
|
||||||
|
while i < len(s):
|
||||||
|
c = c + v * string.index(self.chars, s[-(i+1)])
|
||||||
|
i = i + 1; v = v + 1
|
||||||
|
if v > 10:
|
||||||
|
v = 1
|
||||||
|
s = s + self.chars[c % 11]
|
||||||
|
|
||||||
|
if self.checksum > 1:
|
||||||
|
# compute second checksum
|
||||||
|
i = 0; v = 1; c = 0
|
||||||
|
while i < len(s):
|
||||||
|
c = c + v * string.index(self.chars, s[-(i+1)])
|
||||||
|
i = i + 1; v = v + 1
|
||||||
|
if v > 9:
|
||||||
|
v = 1
|
||||||
|
s = s + self.chars[c % 10]
|
||||||
|
|
||||||
|
self.encoded = 'S' + s + 'S'
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
dval = ""
|
||||||
|
for c in self.encoded:
|
||||||
|
dval = dval + self.patterns[c] + 'i'
|
||||||
|
self.decomposed = dval[:-1]
|
||||||
|
return self.decomposed
|
|
@ -0,0 +1,81 @@
|
||||||
|
#
|
||||||
|
# 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 Barcode
|
||||||
|
import string
|
||||||
|
|
||||||
|
# . 3 T Tracker
|
||||||
|
# , 2 D Descender
|
||||||
|
# ' 1 A Ascender
|
||||||
|
# | 0 H Ascender/Descender
|
||||||
|
|
||||||
|
_rm_patterns = {
|
||||||
|
"0" : "--||", "1" : "-',|", "2" : "-'|,", "3" : "'-,|",
|
||||||
|
"4" : "'-|,", "5" : "'',,", "6" : "-,'|", "7" : "-|-|",
|
||||||
|
"8" : "-|',", "9" : "',-|", "A" : "',',", "B" : "'|-,",
|
||||||
|
"C" : "-,|'", "D" : "-|,'", "E" : "-||-", "F" : "',,'",
|
||||||
|
"G" : "',|-", "H" : "'|,-", "I" : ",-'|", "J" : ",'-|",
|
||||||
|
"K" : ",'',", "L" : "|--|", "M" : "|-',", "N" : "|'-,",
|
||||||
|
"O" : ",-|'", "P" : ",','", "Q" : ",'|-", "R" : "|-,'",
|
||||||
|
"S" : "|-|-", "T" : "|',-", "U" : ",,''", "V" : ",|-'",
|
||||||
|
"W" : ",|'-", "X" : "|,-'", "Y" : "|,'-", "Z" : "||--",
|
||||||
|
|
||||||
|
# start, stop
|
||||||
|
"(" : "'-,'", ")" : "'|,|"
|
||||||
|
}
|
||||||
|
|
||||||
|
_ozN_patterns = {
|
||||||
|
"0" : "||", "1" : "|'", "2" : "|,", "3" : "'|", "4" : "''",
|
||||||
|
"5" : "',", "6" : ",|", "7" : ",'", "8" : ",,", "9" : ".|"
|
||||||
|
}
|
||||||
|
|
||||||
|
_ozC_patterns = {
|
||||||
|
"A" : "|||", "B" : "||'", "C" : "||,", "D" : "|'|",
|
||||||
|
"E" : "|''", "F" : "|',", "G" : "|,|", "H" : "|,'",
|
||||||
|
"I" : "|,,", "J" : "'||", "K" : "'|'", "L" : "'|,",
|
||||||
|
"M" : "''|", "N" : "'''", "O" : "'',", "P" : "',|",
|
||||||
|
"Q" : "','", "R" : "',,", "S" : ",||", "T" : ",|'",
|
||||||
|
"U" : ",|,", "V" : ",'|", "W" : ",''", "X" : ",',",
|
||||||
|
"Y" : ",,|", "Z" : ",,'", "a" : "|,.", "b" : "|.|",
|
||||||
|
"c" : "|.'", "d" : "|.,", "e" : "|..", "f" : "'|.",
|
||||||
|
"g" : "''.", "h" : "',.", "i" : "'.|", "j" : "'.'",
|
||||||
|
"k" : "'.,", "l" : "'..", "m" : ",|.", "n" : ",'.",
|
||||||
|
"o" : ",,.", "p" : ",.|", "q" : ",.'", "r" : ",.,",
|
||||||
|
"s" : ",..", "t" : ".|.", "u" : ".'.", "v" : ".,.",
|
||||||
|
"w" : "..|", "x" : "..'", "y" : "..,", "z" : "...",
|
||||||
|
"0" : ",,,", "1" : ".||", "2" : ".|'", "3" : ".|,",
|
||||||
|
"4" : ".'|", "5" : ".''", "6" : ".',", "7" : ".,|",
|
||||||
|
"8" : ".,'", "9" : ".,,", " " : "||.", "#" : "|'.",
|
||||||
|
}
|
||||||
|
|
||||||
|
#http://www.auspost.com.au/futurepost/
|
Binary file not shown.
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/pkg/bin/python
|
||||||
|
from common import *
|
||||||
|
from code39 import *
|
||||||
|
from code93 import *
|
||||||
|
from code128 import *
|
||||||
|
from usps import *
|
||||||
|
|
||||||
|
from reportlab.pdfgen.canvas import Canvas
|
||||||
|
from reportlab.lib.styles import getSampleStyleSheet
|
||||||
|
from reportlab.platypus import Paragraph, Frame
|
||||||
|
from reportlab.platypus.flowables import XBox
|
||||||
|
def run():
|
||||||
|
styles = getSampleStyleSheet()
|
||||||
|
styleN = styles['Normal']
|
||||||
|
styleH = styles['Heading1']
|
||||||
|
story = []
|
||||||
|
|
||||||
|
story.append(Paragraph('I2of5', styleN))
|
||||||
|
story.append(I2of5(1234, xdim = inch*0.02, checksum=0))
|
||||||
|
story.append(Paragraph('MSI', styleN))
|
||||||
|
story.append(MSI(1234, xdim = inch*0.02))
|
||||||
|
story.append(Paragraph('Codabar', styleN))
|
||||||
|
story.append(Codabar("A012345B", xdim = inch*0.02))
|
||||||
|
story.append(Paragraph('Code 11', styleN))
|
||||||
|
story.append(Code11("01234545634563"))
|
||||||
|
story.append(Paragraph('Code 39', styleN))
|
||||||
|
story.append(Standard39("A012345B%R"))
|
||||||
|
story.append(Paragraph('Extended Code 39', styleN))
|
||||||
|
story.append(Extended39("A012345B}"))
|
||||||
|
story.append(Paragraph('Code93', styleN))
|
||||||
|
story.append(Standard93("CODE 93"))
|
||||||
|
story.append(Paragraph('Extended Code93', styleN))
|
||||||
|
story.append(Extended93("L@@K! Code 93 :-)")) #, xdim=0.005 * inch))
|
||||||
|
story.append(Paragraph('Code 128', styleN))
|
||||||
|
c=Code128("AB-12345678") #, xdim=0.005 * inch)
|
||||||
|
#print 'WIDTH =', (c.width / inch), 'XDIM =', (c.xdim / inch)
|
||||||
|
#print 'LQ =', (c.lquiet / inch), 'RQ =', (c.rquiet / inch)
|
||||||
|
story.append(c)
|
||||||
|
story.append(Paragraph('USPS FIM', styleN))
|
||||||
|
story.append(FIM("A"))
|
||||||
|
story.append(Paragraph('USPS POSTNET', styleN))
|
||||||
|
story.append(POSTNET('78247-1043'))
|
||||||
|
story.append(Paragraph('Label Size', styleN))
|
||||||
|
story.append(XBox((2.0 + 5.0/8.0)*inch, 1 * inch, '1x2-5/8"'))
|
||||||
|
story.append(Paragraph('Label Size', styleN))
|
||||||
|
story.append(XBox((1.75)*inch, .5 * inch, '1/2x1-3/4"'))
|
||||||
|
c = Canvas('out.pdf')
|
||||||
|
f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1)
|
||||||
|
f.addFromList(story, c)
|
||||||
|
c.save()
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
run()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 1996-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 Barcode
|
||||||
|
import string
|
||||||
|
|
||||||
|
_fim_patterns = {
|
||||||
|
'A' : "|| | ||",
|
||||||
|
'B' : "| || || |",
|
||||||
|
'C' : "|| | | ||",
|
||||||
|
'D' : "||| | |||",
|
||||||
|
# XXX There is an E.
|
||||||
|
# The below has been seen, but dunno if it is E or not:
|
||||||
|
# 'E' : '|||| ||||'
|
||||||
|
}
|
||||||
|
|
||||||
|
_postnet_patterns = {
|
||||||
|
'1' : "...||", '2' : "..|.|", '3' : "..||.", '4' : ".|..|",
|
||||||
|
'5' : ".|.|.", '6' : ".||..", '7' : "|...|", '8' : "|..|.",
|
||||||
|
'9' : "|.|..", '0' : "||...", 'S' : "|",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FIM(Barcode):
|
||||||
|
""""
|
||||||
|
FIM (Facing ID Marks) encode only one letter.
|
||||||
|
There are currently four defined:
|
||||||
|
|
||||||
|
A Courtesy reply mail with pre-printed POSTNET
|
||||||
|
B Business reply mail without pre-printed POSTNET
|
||||||
|
C Business reply mail with pre-printed POSTNET
|
||||||
|
D OCR Readable mail without pre-printed POSTNET
|
||||||
|
|
||||||
|
Interleaved 2 of 5 is a numeric-only barcode. It encodes an even
|
||||||
|
number of digits; if an odd number is given, a 0 is prepended.
|
||||||
|
|
||||||
|
Options that may be passed to constructor:
|
||||||
|
|
||||||
|
value (single character string from the set A - D. required.):
|
||||||
|
The value to encode.
|
||||||
|
|
||||||
|
quiet (bool, default 1):
|
||||||
|
Wether to include quiet zones in the symbol.
|
||||||
|
|
||||||
|
The following may also be passed, but doing so will generate nonstandard
|
||||||
|
symbols which should not be used. This is mainly documented here to
|
||||||
|
show the defaults:
|
||||||
|
|
||||||
|
height (float, default 5/8 inch):
|
||||||
|
Height of the code. This might legitimately be overriden to make
|
||||||
|
a taller symbol that will 'bleed' off the edge of the paper,
|
||||||
|
leaving 5/8 inch remaining.
|
||||||
|
|
||||||
|
lquiet (float, default 1/4 inch):
|
||||||
|
Quiet zone size to left of code, if quiet is true.
|
||||||
|
Default is the greater of .25 inch, or .15 times the symbol's
|
||||||
|
length.
|
||||||
|
|
||||||
|
rquiet (float, default 15/32 inch):
|
||||||
|
Quiet zone size to right left of code, if quiet is true.
|
||||||
|
|
||||||
|
Sources of information on FIM:
|
||||||
|
|
||||||
|
USPS Publication 25, A Guide to Business Mail Preparation
|
||||||
|
http://new.usps.com/cpim/ftp/pubs/pub25.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.barwidth = inch * (1.0/32.0)
|
||||||
|
self.barspace = inch * (1.0/16.0)
|
||||||
|
self.height = inch * (5.0/8.0)
|
||||||
|
self.rquiet = inch * (0.25)
|
||||||
|
self.lquiet = inch * (15.0/32.0)
|
||||||
|
self.quiet = 0
|
||||||
|
|
||||||
|
for (k, v) in args.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.valid = 1
|
||||||
|
self.validated = ''
|
||||||
|
for c in self.value:
|
||||||
|
if c in string.whitespace:
|
||||||
|
continue
|
||||||
|
elif c in "abcdABCD":
|
||||||
|
self.validated = self.validated + string.upper(c)
|
||||||
|
else:
|
||||||
|
self.valid = 0
|
||||||
|
|
||||||
|
if len(self.validated) != 1:
|
||||||
|
raise ValueError, "Input must be exactly one character"
|
||||||
|
|
||||||
|
return self.validated
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
self.decomposed = ''
|
||||||
|
for c in self.encoded:
|
||||||
|
self.decomposed = self.decomposed + _fim_patterns[c]
|
||||||
|
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
def computeSize(self):
|
||||||
|
self.width = (len(self.decomposed) - 1) * self.barspace + self.barwidth
|
||||||
|
if self.quiet:
|
||||||
|
self.xo = self.lquiet
|
||||||
|
self.width = self.lquiet + self.width + self.rquiet
|
||||||
|
else:
|
||||||
|
self.xo = 0.0
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
left = self.xo
|
||||||
|
for c in self.decomposed:
|
||||||
|
if c == '|':
|
||||||
|
self.rect(left, 0.0, self.barwidth, self.height)
|
||||||
|
left = left + self.barspace
|
||||||
|
|
||||||
|
|
||||||
|
class POSTNET(Barcode):
|
||||||
|
""""
|
||||||
|
POSTNET is used in the US to encode "zip codes" (postal codes) on
|
||||||
|
mail. It can encode 5, 9, or 11 digit codes. I've read that it's
|
||||||
|
pointless to do 5 digits, since USPS will just have to re-print
|
||||||
|
them with 9 or 11 digits.
|
||||||
|
|
||||||
|
Sources of information on POSTNET:
|
||||||
|
|
||||||
|
USPS Publication 25, A Guide to Business Mail Preparation
|
||||||
|
http://new.usps.com/cpim/ftp/pubs/pub25.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, value='', **args):
|
||||||
|
self.sbarheight = inch * 0.050
|
||||||
|
self.fbarheight = inch * 0.125
|
||||||
|
self.barwide = inch * 0.018
|
||||||
|
self.spacewide = inch * 0.0275
|
||||||
|
|
||||||
|
for (k, v) in args.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
Barcode.__init__(self, value)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.validated = ''
|
||||||
|
self.valid = 1
|
||||||
|
count = 0
|
||||||
|
for c in self.value:
|
||||||
|
if c in (string.whitespace + '-'):
|
||||||
|
pass
|
||||||
|
elif c in string.digits:
|
||||||
|
count = count + 1
|
||||||
|
if count == 6:
|
||||||
|
self.validated = self.validated + '-'
|
||||||
|
self.validated = self.validated + c
|
||||||
|
else:
|
||||||
|
self.valid = 0
|
||||||
|
|
||||||
|
if len(self.validated) not in [5, 10, 12]:
|
||||||
|
self.valid = 0
|
||||||
|
|
||||||
|
return self.validated
|
||||||
|
|
||||||
|
def encode(self):
|
||||||
|
self.encoded = "S"
|
||||||
|
check = 0
|
||||||
|
for c in self.validated:
|
||||||
|
if c in string.digits:
|
||||||
|
self.encoded = self.encoded + c
|
||||||
|
check = check + string.atoi(c)
|
||||||
|
elif c == '-':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError, "Invalid character in input"
|
||||||
|
check = (10 - (check % 10)) % 10
|
||||||
|
self.encoded = self.encoded + `check` + 'S'
|
||||||
|
return self.encoded
|
||||||
|
|
||||||
|
def decompose(self):
|
||||||
|
self.decomposed = ''
|
||||||
|
for c in self.encoded:
|
||||||
|
self.decomposed = self.decomposed + _postnet_patterns[c]
|
||||||
|
return self.decomposed
|
||||||
|
|
||||||
|
def computeSize(self):
|
||||||
|
self.width = len(self.decomposed) * self.barwide
|
||||||
|
self.width = self.width + (len(self.decomposed) - 1) * self.spacewide
|
||||||
|
self.height = self.fbarheight
|
||||||
|
self.xo = 0.0
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
sdown = self.fbarheight - self.sbarheight
|
||||||
|
left = self.xo
|
||||||
|
|
||||||
|
for c in self.decomposed:
|
||||||
|
if c == '.':
|
||||||
|
h = self.sbarheight
|
||||||
|
else:
|
||||||
|
h = self.fbarheight
|
||||||
|
self.rect(left, 0.0, self.barwide, h)
|
||||||
|
left = left + self.barwide + self.spacewide
|
|
@ -40,14 +40,14 @@ import base64
|
||||||
url = 'http://localhost:8069/xmlrpc'
|
url = 'http://localhost:8069/xmlrpc'
|
||||||
profiles = [
|
profiles = [
|
||||||
'profile_accounting',
|
'profile_accounting',
|
||||||
'profile_manufacturing',
|
'profile_service',
|
||||||
'profile_service'
|
'profile_manufacturing'
|
||||||
]
|
]
|
||||||
l10n_charts = [
|
l10n_charts = [
|
||||||
'l10n_be',
|
|
||||||
'l10n_fr',
|
|
||||||
'l10n_chart_uk_minimal',
|
'l10n_chart_uk_minimal',
|
||||||
False
|
False,
|
||||||
|
'l10n_be',
|
||||||
|
'l10n_fr'
|
||||||
]
|
]
|
||||||
dbname = 'test'
|
dbname = 'test'
|
||||||
admin_passwd = 'admin'
|
admin_passwd = 'admin'
|
||||||
|
|
Loading…
Reference in New Issue