[MERGE] Merged with lp:addons
[odoo/odoo.git] / addons / auction / barcode / code39.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (c) 1996-2000 Tyler C. Sarna <tsarna@sarna.org>
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 # 3. All advertising materials mentioning features or use of this software
15 #    must display the following acknowledgement:
16 #      This product includes software developed by Tyler C. Sarna.
17 # 4. Neither the name of the author nor the names of contributors
18 #    may be used to endorse or promote products derived from this software
19 #    without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 #
33
34 from reportlab.lib.units import inch
35 from common import Barcode
36 import string
37
38 _patterns = {
39     '0':    ("bsbSBsBsb", 0),       '1': ("BsbSbsbsB", 1),
40     '2':    ("bsBSbsbsB", 2),       '3': ("BsBSbsbsb", 3),
41     '4':    ("bsbSBsbsB", 4),       '5': ("BsbSBsbsb", 5),
42     '6':    ("bsBSBsbsb", 6),       '7': ("bsbSbsBsB", 7),
43     '8':    ("BsbSbsBsb", 8),       '9': ("bsBSbsBsb", 9),
44     'A':    ("BsbsbSbsB", 10),      'B': ("bsBsbSbsB", 11),
45     'C':    ("BsBsbSbsb", 12),      'D': ("bsbsBSbsB", 13),
46     'E':    ("BsbsBSbsb", 14),      'F': ("bsBsBSbsb", 15),
47     'G':    ("bsbsbSBsB", 16),      'H': ("BsbsbSBsb", 17),
48     'I':    ("bsBsbSBsb", 18),      'J': ("bsbsBSBsb", 19),
49     'K':    ("BsbsbsbSB", 20),      'L': ("bsBsbsbSB", 21),
50     'M':    ("BsBsbsbSb", 22),      'N': ("bsbsBsbSB", 23),
51     'O':    ("BsbsBsbSb", 24),      'P': ("bsBsBsbSb", 25),
52     'Q':    ("bsbsbsBSB", 26),      'R': ("BsbsbsBSb", 27),
53     'S':    ("bsBsbsBSb", 28),      'T': ("bsbsBsBSb", 29),
54     'U':    ("BSbsbsbsB", 30),      'V': ("bSBsbsbsB", 31),
55     'W':    ("BSBsbsbsb", 32),      'X': ("bSbsBsbsB", 33),
56     'Y':    ("BSbsBsbsb", 34),      'Z': ("bSBsBsbsb", 35),
57     '-':    ("bSbsbsBsB", 36),      '.': ("BSbsbsBsb", 37),
58     ' ':    ("bSBsbsBsb", 38),      '*': ("bSbsBsBsb", 39),
59     '$':    ("bSbSbSbsb", 40),      '/': ("bSbSbsbSb", 41),
60     '+':    ("bSbsbSbSb", 42),      '%': ("bsbSbSbSb", 43)
61 }
62
63 _valchars = [
64     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
65     'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
66     'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
67     'X', 'Y', 'Z', '-', '.', ' ', '*', '$', '/', '+', '%'
68 ]
69
70 _extended = {
71     '\0':   "%U",    '\01':  "$A",    '\02':  "$B",    '\03':  "$C",
72     '\04':  "$D",    '\05':  "$E",    '\06':  "$F",    '\07':  "$G",
73     '\010': "$H",    '\011': "$I",    '\012': "$J",    '\013': "$K",
74     '\014': "$L",    '\015': "$M",    '\016': "$N",    '\017': "$O",
75     '\020': "$P",    '\021': "$Q",    '\022': "$R",    '\023': "$S",
76     '\024': "$T",    '\025': "$U",    '\026': "$V",    '\027': "$W",
77     '\030': "$X",    '\031': "$Y",    '\032': "$Z",    '\033': "%A",
78     '\034': "%B",    '\035': "%C",    '\036': "%D",    '\037': "%E",
79     '!':    "/A",    '"':    "/B",    '#':    "/C",    '$':    "/D",
80     '%':    "/E",    '&':    "/F",    '\'':   "/G",    '(':    "/H",
81     ')':    "/I",    '*':    "/J",    '+':    "/K",    ',':    "/L",
82     '/':    "/O",    ':':    "/Z",    ';':    "%F",    '<':    "%G",
83     '=':    "%H",    '>':    "%I",    '?':    "%J",    '@':    "%V",
84     '[':    "%K",    '\\':   "%L",    ']':    "%M",    '^':    "%N",
85     '_':    "%O",    '`':    "%W",    'a':    "+A",    'b':    "+B",
86     'c':    "+C",    'd':    "+D",    'e':    "+E",    'f':    "+F",
87     'g':    "+G",    'h':    "+H",    'i':    "+I",    'j':    "+J",
88     'k':    "+K",    'l':    "+L",    'm':    "+M",    'n':    "+N",
89     'o':    "+O",    'p':    "+P",    'q':    "+Q",    'r':    "+R",
90     's':    "+S",    't':    "+T",    'u':    "+U",    'v':    "+V",
91     'w':    "+W",    'x':    "+X",    'y':    "+Y",    'z':    "+Z",
92     '{':    "%P",    '|':    "%Q",    '}':    "%R",    '~':    "%S",
93     '\177': "%T"
94 }
95
96
97 _stdchrs = string.digits + string.uppercase + "-. *$/+%"
98 _extchrs = _stdchrs + string.lowercase + \
99     "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" + \
100     "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" + \
101     "!'#&\"(),:;<=>?@[\\]^_`{|}~\177"
102
103
104 def _encode39(str, cksum):
105     newval = "*"
106     v = 0
107     for c in str:
108         v = v + _patterns[c][1]
109         newval = newval + c
110     v = v % 43
111     if cksum:
112         newval = newval + _valchars[v]
113     return newval + '*'
114
115         
116 class _Code39Base(Barcode):
117     def __init__(self, value = "", **args):
118         self.xdim = inch * 0.0075
119         self.lquiet = None
120         self.rquiet = None
121         self.quiet = 1
122         self.gap = None
123         self.height = None
124         self.ratio = 2.2
125         self.checksum = 0
126         self.bearers = 0.0
127
128         for (k, v) in args.items():
129             setattr(self, k, v)
130             
131         if self.quiet:
132             if self.lquiet is None:
133                 self.lquiet = max(inch * 0.25, self.xdim * 10.0)
134                 self.rquiet = max(inch * 0.25, self.xdim * 10.0)
135         else:
136             self.lquiet = self.rquiet = 0.0
137                                                          
138         Barcode.__init__(self, value)
139
140     def decompose(self):
141         dval = ""
142         for c in self.encoded:
143             dval = dval + _patterns[c][0] + 'i'
144         self.decomposed = dval[:-1]
145         return self.decomposed
146
147
148 class Standard39(_Code39Base):
149     """
150     Interleaved 2 of 5 is a numeric-only barcode.  It encodes an even
151     number of digits; if an odd number is given, a 0 is prepended.
152
153     Options that may be passed to constructor:
154
155         value (int, or numeric string. required.):
156             The value to encode.
157    
158         xdim (float, default .0075):
159             X-Dimension, or width of the smallest element
160             Minumum is .0075 inch (7.5 mils).
161             
162         ratio (float, default 2.2):
163             The ratio of wide elements to narrow elements.
164             Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
165             xdim is greater than 20 mils (.02 inch))
166             
167         gap (float or None, default None):
168             width of intercharacter gap. None means "use xdim".
169         
170         height (float, see default below):
171             Height of the symbol.  Default is the height of the two
172             bearer bars (if they exist) plus the greater of .25 inch
173             or .15 times the symbol's length.
174
175         checksum (bool, default 0):
176             Wether to compute and include the check digit
177             
178         bearers (float, in units of xdim. default 0):
179             Height of bearer bars (horizontal bars along the top and
180             bottom of the barcode). Default is 0 (no bearers).
181             
182         quiet (bool, default 1):
183             Wether to include quiet zones in the symbol.
184             
185         lquiet (float, see default below):
186             Quiet zone size to left of code, if quiet is true.
187             Default is the greater of .25 inch, or .15 times the symbol's
188             length.
189             
190         rquiet (float, defaults as above):
191             Quiet zone size to right left of code, if quiet is true.
192
193     Sources of Information on Code 39:
194     
195     http://www.semiconductor.agilent.com/barcode/sg/Misc/code_39.html
196     http://www.adams1.com/pub/russadam/39code.html
197     http://www.barcodeman.com/c39_1.html
198
199     Official Spec, "ANSI/AIM BC1-1995, USS" is available for US$45 from
200     http://www.aimglobal.org/aimstore/
201     """
202
203     def validate(self):
204         vval = ""
205         self.valid = 1
206         for c in self.value:
207             if c in string.lowercase:
208                 c = string.upper(c)
209             if c not in _stdchrs:
210                 self.valid = 0
211                 continue
212             vval = vval + c
213         self.validated = vval
214         return vval
215
216     def encode(self):
217         self.encoded = _encode39(self.validated, self.checksum)
218         return self.encoded
219
220
221 class Extended39(_Code39Base):
222     """
223     Extended Code 39 is a convention for encoding additional characters
224     not present in stanmdard Code 39 by using pairs of characters to
225     represent the characters missing in Standard Code 39.
226     
227     See Standard39 for arguments.
228
229     Sources of Information on Extended Code 39:
230     
231     http://www.semiconductor.agilent.com/barcode/sg/Misc/xcode_39.html
232     http://www.barcodeman.com/c39_ext.html
233     """
234
235     def validate(self):
236         vval = ""
237         self.valid = 1
238         for c in self.value:
239             if c not in _extchrs:
240                 self.valid = 0
241                 continue
242             vval = vval + c
243         self.validated = vval
244         return vval
245
246     def encode(self):
247         self.encoded = ""
248         for c in self.validated:
249             if _extended.has_key(c):
250                 self.encoded = self.encoded + _extended[c]
251             elif c in _stdchrs:
252                 self.encoded = self.encoded + c
253             else:
254                 raise ValueError
255         self.encoded = _encode39(self.encoded, self.checksum)
256         return self.encoded
257 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: