[IMP] Changed all module categories, limited number of categories
[odoo/odoo.git] / addons / auction / barcode / code128.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 from string import digits
37
38 _patterns = {
39     0   :   'BaBbBb',    1   :   'BbBaBb',    2   :   'BbBbBa',
40     3   :   'AbAbBc',    4   :   'AbAcBb',    5   :   'AcAbBb',
41     6   :   'AbBbAc',    7   :   'AbBcAb',    8   :   'AcBbAb',
42     9   :   'BbAbAc',    10  :   'BbAcAb',    11  :   'BcAbAb',
43     12  :   'AaBbCb',    13  :   'AbBaCb',    14  :   'AbBbCa',
44     15  :   'AaCbBb',    16  :   'AbCaBb',    17  :   'AbCbBa',
45     18  :   'BbCbAa',    19  :   'BbAaCb',    20  :   'BbAbCa',
46     21  :   'BaCbAb',    22  :   'BbCaAb',    23  :   'CaBaCa',
47     24  :   'CaAbBb',    25  :   'CbAaBb',    26  :   'CbAbBa',
48     27  :   'CaBbAb',    28  :   'CbBaAb',    29  :   'CbBbAa',
49     30  :   'BaBaBc',    31  :   'BaBcBa',    32  :   'BcBaBa',
50     33  :   'AaAcBc',    34  :   'AcAaBc',    35  :   'AcAcBa',
51     36  :   'AaBcAc',    37  :   'AcBaAc',    38  :   'AcBcAa',
52     39  :   'BaAcAc',    40  :   'BcAaAc',    41  :   'BcAcAa',
53     42  :   'AaBaCc',    43  :   'AaBcCa',    44  :   'AcBaCa',
54     45  :   'AaCaBc',    46  :   'AaCcBa',    47  :   'AcCaBa',
55     48  :   'CaCaBa',    49  :   'BaAcCa',    50  :   'BcAaCa',
56     51  :   'BaCaAc',    52  :   'BaCcAa',    53  :   'BaCaCa',
57     54  :   'CaAaBc',    55  :   'CaAcBa',    56  :   'CcAaBa',
58     57  :   'CaBaAc',    58  :   'CaBcAa',    59  :   'CcBaAa',
59     60  :   'CaDaAa',    61  :   'BbAdAa',    62  :   'DcAaAa',
60     63  :   'AaAbBd',    64  :   'AaAdBb',    65  :   'AbAaBd',
61     66  :   'AbAdBa',    67  :   'AdAaBb',    68  :   'AdAbBa',
62     69  :   'AaBbAd',    70  :   'AaBdAb',    71  :   'AbBaAd',
63     72  :   'AbBdAa',    73  :   'AdBaAb',    74  :   'AdBbAa',
64     75  :   'BdAbAa',    76  :   'BbAaAd',    77  :   'DaCaAa',
65     78  :   'BdAaAb',    79  :   'AcDaAa',    80  :   'AaAbDb',
66     81  :   'AbAaDb',    82  :   'AbAbDa',    83  :   'AaDbAb',
67     84  :   'AbDaAb',    85  :   'AbDbAa',    86  :   'DaAbAb',
68     87  :   'DbAaAb',    88  :   'DbAbAa',    89  :   'BaBaDa',
69     90  :   'BaDaBa',    91  :   'DaBaBa',    92  :   'AaAaDc',
70     93  :   'AaAcDa',    94  :   'AcAaDa',    95  :   'AaDaAc',
71     96  :   'AaDcAa',    97  :   'DaAaAc',    98  :   'DaAcAa',
72     99  :   'AaCaDa',    100 :   'AaDaCa',    101 :   'CaAaDa',
73     102 :   'DaAaCa',    103 :   'BaAdAb',    104 :   'BaAbAd',
74     105 :   'BaAbCb',    106 :   'BcCaAaB'
75 }
76
77 starta, startb, startc, stop = 103, 104, 105, 106
78
79 seta = {
80         ' ' :   0,        '!' :   1,        '"' :   2,        '#' :   3,
81         '$' :   4,        '%' :   5,        '&' :   6,       '\'' :   7,
82         '(' :   8,        ')' :   9,        '*' :  10,        '+' :  11,
83         ',' :  12,        '-' :  13,        '.' :  14,        '/' :  15,
84         '0' :  16,        '1' :  17,        '2' :  18,        '3' :  19,
85         '4' :  20,        '5' :  21,        '6' :  22,        '7' :  23,
86         '8' :  24,        '9' :  25,        ':' :  26,        ';' :  27,
87         '<' :  28,        '=' :  29,        '>' :  30,        '?' :  31,
88         '@' :  32,        'A' :  33,        'B' :  34,        'C' :  35,
89         'D' :  36,        'E' :  37,        'F' :  38,        'G' :  39,
90         'H' :  40,        'I' :  41,        'J' :  42,        'K' :  43,
91         'L' :  44,        'M' :  45,        'N' :  46,        'O' :  47,
92         'P' :  48,        'Q' :  49,        'R' :  50,        'S' :  51,
93         'T' :  52,        'U' :  53,        'V' :  54,        'W' :  55,
94         'X' :  56,        'Y' :  57,        'Z' :  58,        '[' :  59,
95        '\\' :  60,        ']' :  61,        '^' :  62,        '_' :  63,
96      '\x00' :  64,     '\x01' :  65,     '\x02' :  66,     '\x03' :  67,
97      '\x04' :  68,     '\x05' :  69,     '\x06' :  70,     '\x07' :  71,
98      '\x08' :  72,     '\x09' :  73,     '\x0a' :  74,     '\x0b' :  75,
99      '\x0c' :  76,     '\x0d' :  77,     '\x0e' :  78,     '\x0f' :  79,
100      '\x10' :  80,     '\x11' :  81,     '\x12' :  82,     '\x13' :  83,
101      '\x14' :  84,     '\x15' :  85,     '\x16' :  86,     '\x17' :  87,
102      '\x18' :  88,     '\x19' :  89,     '\x1a' :  90,     '\x1b' :  91,
103      '\x1c' :  92,     '\x1d' :  93,     '\x1e' :  94,     '\x1f' :  95,
104      '\xf3' :  96,     '\xf2' :  97,    'SHIFT' :  98,     'TO_C' :  99,
105      'TO_B' : 100,     '\xf4' : 101,     '\xf1' : 102
106 }
107
108 setb = {
109         ' ' :   0,        '!' :   1,        '"' :   2,        '#' :   3,
110         '$' :   4,        '%' :   5,        '&' :   6,       '\'' :   7,
111         '(' :   8,        ')' :   9,        '*' :  10,        '+' :  11,
112         ',' :  12,        '-' :  13,        '.' :  14,        '/' :  15,
113         '0' :  16,        '1' :  17,        '2' :  18,        '3' :  19,
114         '4' :  20,        '5' :  21,        '6' :  22,        '7' :  23,
115         '8' :  24,        '9' :  25,        ':' :  26,        ';' :  27,
116         '<' :  28,        '=' :  29,        '>' :  30,        '?' :  31,
117         '@' :  32,        'A' :  33,        'B' :  34,        'C' :  35,
118         'D' :  36,        'E' :  37,        'F' :  38,        'G' :  39,
119         'H' :  40,        'I' :  41,        'J' :  42,        'K' :  43,
120         'L' :  44,        'M' :  45,        'N' :  46,        'O' :  47,
121         'P' :  48,        'Q' :  49,        'R' :  50,        'S' :  51,
122         'T' :  52,        'U' :  53,        'V' :  54,        'W' :  55,
123         'X' :  56,        'Y' :  57,        'Z' :  58,        '[' :  59,
124        '\\' :  60,        ']' :  61,        '^' :  62,        '_' :  63,
125         '`' :  64,        'a' :  65,        'b' :  66,        'c' :  67,
126         'd' :  68,        'e' :  69,        'f' :  70,        'g' :  71,
127         'h' :  72,        'i' :  73,        'j' :  74,        'k' :  75,
128         'l' :  76,        'm' :  77,        'n' :  78,        'o' :  79,
129         'p' :  80,        'q' :  81,        'r' :  82,        's' :  83,
130         't' :  84,        'u' :  85,        'v' :  86,        'w' :  87,
131         'x' :  88,        'y' :  89,        'z' :  90,        '{' :  91,
132         '|' :  92,        '}' :  93,        '~' :  94,     '\x7f' :  95,
133      '\xf3' :  96,     '\xf2' :  97,    'SHIFT' :  98,     'TO_C' :  99,
134      '\xf4' : 100,     'TO_A' : 101,     '\xf1' : 102
135 }
136
137 setc = {
138     '00': 0, '01': 1, '02': 2, '03': 3, '04': 4,
139     '05': 5, '06': 6, '07': 7, '08': 8, '09': 9,
140     '10':10, '11':11, '12':12, '13':13, '14':14,
141     '15':15, '16':16, '17':17, '18':18, '19':19,
142     '20':20, '21':21, '22':22, '23':23, '24':24,
143     '25':25, '26':26, '27':27, '28':28, '29':29,
144     '30':30, '31':31, '32':32, '33':33, '34':34,
145     '35':35, '36':36, '37':37, '38':38, '39':39,
146     '40':40, '41':41, '42':42, '43':43, '44':44,
147     '45':45, '46':46, '47':47, '48':48, '49':49,
148     '50':50, '51':51, '52':52, '53':53, '54':54,
149     '55':55, '56':56, '57':57, '58':58, '59':59,
150     '60':60, '61':61, '62':62, '63':63, '64':64,
151     '65':65, '66':66, '67':67, '68':68, '69':69,
152     '70':70, '71':71, '72':72, '73':73, '74':74,
153     '75':75, '76':76, '77':77, '78':78, '79':79,
154     '80':80, '81':81, '82':82, '83':83, '84':84,
155     '85':85, '86':86, '87':87, '88':88, '89':89,
156     '90':90, '91':91, '92':92, '93':93, '94':94,
157     '95':95, '96':96, '97':97, '98':98, '99':99,
158
159     'TO_B' : 100,    'TO_A' : 101,    '\xf1' : 102
160 }
161
162 setmap = {
163     'TO_A' : (seta, setb),
164     'TO_B' : (setb, seta),
165     'TO_C' : (setc, None),
166     'START_A' : (starta, seta, setb),
167     'START_B' : (startb, setb, seta),
168     'START_C' : (startc, setc, None),
169 }
170 tos = setmap.keys()
171
172 class Code128(MultiWidthBarcode):
173     """
174     Code 128 is a very compact symbology that can encode the entire
175     128 character ASCII set, plus 4 special control codes,
176     (FNC1-FNC4, expressed in the input string as \xf1 to \xf4).
177     Code 128 can also encode digits at double density (2 per byte)
178     and has a mandatory checksum.  Code 128 is well supported and
179     commonly used -- for example, by UPS for tracking labels.
180
181     Because of these qualities, Code 128 is probably the best choice
182     for a linear symbology today (assuming you have a choice).
183
184     Options that may be passed to constructor:
185
186         value (int, or numeric string. required.):
187             The value to encode.
188
189         xdim (float, default .0075):
190             X-Dimension, or width of the smallest element
191             Minumum is .0075 inch (7.5 mils).
192
193         height (float, see default below):
194             Height of the symbol.  Default is the height of the two
195             bearer bars (if they exist) plus the greater of .25 inch
196             or .15 times the symbol's length.
197
198         quiet (bool, default 1):
199             Wether to include quiet zones in the symbol.
200
201         lquiet (float, see default below):
202             Quiet zone size to left of code, if quiet is true.
203             Default is the greater of .25 inch, or 10 xdim
204
205         rquiet (float, defaults as above):
206             Quiet zone size to right left of code, if quiet is true.
207
208     Sources of Information on Code 128:
209
210     http://www.semiconductor.agilent.com/barcode/sg/Misc/code_128.html
211     http://www.adams1.com/pub/russadam/128code.html
212     http://www.barcodeman.com/c128.html
213
214     Official Spec, "ANSI/AIM BC4-1999, ISS" is available for US$45 from
215     http://www.aimglobal.org/aimstore/
216     """
217     def __init__(self, value='', **args):
218         self.xdim = inch * 0.0075
219         self.lquiet = None
220         self.rquiet = None
221         self.quiet = 1
222         self.height = None
223
224         if type(value) is type(1):
225             value = str(value)
226
227         for (k, v) in args.items():
228             setattr(self, k, v)
229
230         if self.quiet:
231             if self.lquiet is None:
232                 self.lquiet = max(inch * 0.25, self.xdim * 10.0)
233                 self.rquiet = max(inch * 0.25, self.xdim * 10.0)
234         else:
235             self.lquiet = self.rquiet = 0.0
236
237         MultiWidthBarcode.__init__(self, value)
238
239     def validate(self):
240         vval = ""
241         self.valid = 1
242         for c in self.value:
243             if ord(c) > 127 and c not in '\xf1\xf2\xf3\xf4':
244                 self.valid = 0
245                 continue
246             vval = vval + c
247         self.validated = vval
248         return vval
249
250     def _trailingDigitsToC(self, l):
251         # Optimization: trailing digits -> set C double-digits
252         c = 1
253         savings = -1 # the TO_C costs one character
254         rl = ['STOP']
255         while c < len(l):
256             i = (-c - 1)
257             if l[i] == '\xf1':
258                 c = c + 1
259                 rl.insert(0, '\xf1')
260                 continue
261             elif len(l[i]) == 1 and l[i] in digits \
262              and len(l[i-1]) == 1 and l[i-1] in digits:
263                 c = c + 2
264                 savings = savings + 1
265                 rl.insert(0, l[i-1] + l[i])
266                 continue
267             else:
268                 break
269         if savings > 0:
270             return l[:-c] + ['TO_C'] + rl
271         else:
272             return l
273
274     def encode(self):
275         # First, encode using only B
276         s = self.validated
277         l = ['START_B']
278         for c in s:
279             if not setb.has_key(c):
280                 l = l + ['TO_A', c, 'TO_B']
281             else:
282                 l.append(c)
283         l.append('STOP')
284
285         l = self._trailingDigitsToC(l)
286
287         # Finally, replace START_X,TO_Y with START_Y
288         if l[1] in tos:
289             l[:2] = ['START_' + l[1][-1]]
290
291
292         # encode into numbers
293         start, set, shset = setmap[l[0]]
294         e = [start]
295
296         l = l[1:-1]
297         while l:
298             c = l[0]
299             if c == 'SHIFT':
300                 e = e + [set[c], shset[l[1]]]
301                 l = l[2:]
302             elif c in tos:
303                 e.append(set[c])
304                 set, shset = setmap[c]
305                 l = l[1:]
306             else:
307                 e.append(set[c])
308                 l = l[1:]
309
310         c = e[0]
311         for i in range(1, len(e)):
312             c = c + i * e[i]
313         self.encoded = e + [c % 103, stop]
314         return self.encoded
315
316     def decompose(self):
317         dval = ''
318         for c in self.encoded:
319             dval = dval + _patterns[c]
320         self.decomposed = dval
321         return self.decomposed
322 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: