[MERGE] Merged with lp:addons
[odoo/odoo.git] / addons / auction / barcode / code93.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (c) 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 MultiWidthBarcode
36 import string
37
38 _patterns = {
39   '0' : ('AcAaAb', 0),  '1' : ('AaAbAc', 1),  '2' : ('AaAcAb', 2),
40   '3' : ('AaAdAa', 3),  '4' : ('AbAaAc', 4),  '5' : ('AbAbAb', 5),
41   '6' : ('AbAcAa', 6),  '7' : ('AaAaAd', 7),  '8' : ('AcAbAa', 8),
42   '9' : ('AdAaAa', 9),  'A' : ('BaAaAc', 10), 'B' : ('BaAbAb', 11),
43   'C' : ('BaAcAa', 12), 'D' : ('BbAaAb', 13), 'E' : ('BbAbAa', 14),
44   'F' : ('BcAaAa', 15), 'G' : ('AaBaAc', 16), 'H' : ('AaBbAb', 17),
45   'I' : ('AaBcAa', 18), 'J' : ('AbBaAb', 19), 'K' : ('AcBaAa', 20),
46   'L' : ('AaAaBc', 21), 'M' : ('AaAbBb', 22), 'N' : ('AaAcBa', 23),
47   'O' : ('AbAaBb', 24), 'P' : ('AcAaBa', 25), 'Q' : ('BaBaAb', 26),
48   'R' : ('BaBbAa', 27), 'S' : ('BaAaBb', 28), 'T' : ('BaAbBa', 29),
49   'U' : ('BbAaBa', 30), 'V' : ('BbBaAa', 31), 'W' : ('AaBaBb', 32),
50   'X' : ('AaBbBa', 33), 'Y' : ('AbBaBa', 34), 'Z' : ('AbCaAa', 35),
51   '-' : ('AbAaCa', 36), '.' : ('CaAaAb', 37), ' ' : ('CaAbAa', 38),
52   '$' : ('CbAaAa', 39), '/' : ('AaBaCa', 40), '+' : ('AaCaBa', 41),
53   '%' : ('BaAaCa', 42), '#' : ('AbAbBa', 43), '!' : ('CaBaAa', 44),
54   '=' : ('CaAaBa', 45), '&' : ('AbBbAa', 46),
55   'start' : ('AaAaDa', -1),  'stop' : ('AaAaDaA', -2)
56 }
57
58 _charsbyval = {}
59 for k, v in _patterns.items():
60     _charsbyval[v[1]] = k
61
62 _extended = {
63     '\x00' : '!U',    '\x01' : '#A',    '\x02' : '#B',    '\x03' : '#C',
64     '\x04' : '#D',    '\x05' : '#E',    '\x06' : '#F',    '\x07' : '#G',
65     '\x08' : '#H',    '\x09' : '#I',    '\x0a' : '#J',    '\x0b' : '#K',
66     '\x0c' : '#L',    '\x0d' : '#M',    '\x0e' : '#N',    '\x0f' : '#O',
67     '\x10' : '#P',    '\x11' : '#Q',    '\x12' : '#R',    '\x13' : '#S',
68     '\x14' : '#T',    '\x15' : '#U',    '\x16' : '#V',    '\x17' : '#W',
69     '\x18' : '#X',    '\x19' : '#Y',    '\x1a' : '#Z',    '\x1b' : '!A',
70     '\x1c' : '!B',    '\x1d' : '!C',    '\x1e' : '!D',    '\x1f' : '!E',
71     '!'    : '=A',    '"'    : '=B',    '#'    : '=C',    '$'    : '=D',
72     '%'    : '=E',    '&'    : '=F',    '\''   : '=G',    '('    : '=H',
73     ')'    : '=I',    '*'    : '=J',    '+'    : '=K',    ','    : '=L',
74     '/'    : '=O',    ':'    : '=Z',    ';'    : '!F',    '<'    : '!G',
75     '='    : '!H',    '>'    : '!I',    '?'    : '!J',    '@'    : '!V',
76     '['    : '!K',    '\\'   : '!L',    ']'    : '!M',    '^'    : '!N',
77     '_'    : '!O',    '`'    : '!W',    'a'    : '&A',    'b'    : '&B',
78     'c'    : '&C',    'd'    : '&D',    'e'    : '&E',    'f'    : '&F',
79     'g'    : '&G',    'h'    : '&H',    'i'    : '&I',    'j'    : '&J',
80     'k'    : '&K',    'l'    : '&L',    'm'    : '&M',    'n'    : '&N',
81     'o'    : '&O',    'p'    : '&P',    'q'    : '&Q',    'r'    : '&R',
82     's'    : '&S',    't'    : '&T',    'u'    : '&U',    'v'    : '&V',
83     'w'    : '&W',    'x'    : '&X',    'y'    : '&Y',    'z'    : '&Z',
84     '{'    : '!P',    '|'    : '!Q',    '}'    : '!R',    '~'    : '!S',
85     '\x7f' : '!T'
86 }
87
88
89 def _encode93(str):
90     s = map(None, str)
91     s.reverse()
92
93     # compute 'C' checksum
94     i = 0; v = 1; c = 0
95     while i < len(s):
96         c = c + v * _patterns[s[i]][1]
97         i = i + 1; v = v + 1
98         if v > 20:
99             v = 1
100     s.insert(0, _charsbyval[c % 47])
101
102     # compute 'K' checksum
103     i = 0; v = 1; c = 0
104     while i < len(s):
105         c = c + v * _patterns[s[i]][1]
106         i = i + 1; v = v + 1
107         if v > 15:
108             v = 1
109     s.insert(0, _charsbyval[c % 47])
110
111     s.reverse()
112
113     return string.join(s, '')
114
115
116 class _Code93Base(MultiWidthBarcode):
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.height = None
123
124         if type(value) is type(1):
125             value = str(value)
126             
127         for (k, v) in args.items():
128             setattr(self, k, v)
129
130         if self.quiet:
131             if self.lquiet is None:
132                 self.lquiet = max(inch * 0.25, self.xdim * 10.0)
133                 self.rquiet = max(inch * 0.25, self.xdim * 10.0)
134         else:
135             self.lquiet = self.rquiet = 0.0
136
137         MultiWidthBarcode.__init__(self, value)
138
139     def decompose(self):
140         dval = _patterns['start'][0]
141         for c in self.encoded:
142             dval = dval + _patterns[c][0]
143         self.decomposed = dval + _patterns['stop'][0]
144         return self.decomposed
145
146
147 class Standard93(_Code93Base):
148     """
149     Code 93 is a Uppercase alphanumeric symbology with some punctuation.
150     See Extended Code 93 for a variant that can represent the entire
151     128 characrter ASCII set.
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         height (float, see default below):
163             Height of the symbol.  Default is the height of the two
164             bearer bars (if they exist) plus the greater of .25 inch
165             or .15 times the symbol's length.
166
167         quiet (bool, default 1):
168             Wether to include quiet zones in the symbol.
169             
170         lquiet (float, see default below):
171             Quiet zone size to left of code, if quiet is true.
172             Default is the greater of .25 inch, or 10 xdim
173             
174         rquiet (float, defaults as above):
175             Quiet zone size to right left of code, if quiet is true.
176
177     Sources of Information on Code 93:
178
179     http://www.semiconductor.agilent.com/barcode/sg/Misc/code_93.html
180
181     Official Spec, "NSI/AIM BC5-1995, USS" is available for US$45 from
182     http://www.aimglobal.org/aimstore/
183     """
184
185     def validate(self):
186         vval = ""
187         self.valid = 1
188         for c in self.value:
189             if c in string.lowercase:
190                 c = string.upper(c)
191             if not _patterns.has_key(c):
192                 self.valid = 0
193                 continue
194             vval = vval + c
195         self.validated = vval
196         return vval
197
198     def encode(self):
199         self.encoded = _encode93(self.validated)
200         return self.encoded
201
202
203 class Extended93(_Code93Base):
204     """
205     Extended Code 93 is a convention for encoding the entire 128 character
206     set using pairs of characters to represent the characters missing in
207     Standard Code 93. It is very much like Extended Code 39 in that way.
208     
209     See Standard93 for arguments.
210     """    
211
212     def validate(self):
213         vval = ""
214         self.valid = 1
215         for c in self.value:
216             if not _patterns.has_key(c) and not _extended.has_key(c):
217                 self.valid = 0
218                 continue
219             vval = vval + c
220         self.validated = vval
221         return vval
222
223     def encode(self):
224         self.encoded = ""
225         for c in self.validated:
226             if _patterns.has_key(c):
227                 self.encoded = self.encoded + c
228             elif _extended.has_key(c):
229                 self.encoded = self.encoded + _extended[c]
230             else:
231                 raise ValueError
232         self.encoded = _encode93(self.encoded)
233         return self.encoded
234 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: