~ubuntu-branches/ubuntu/quantal/openerp6.1/quantal-proposed

« back to all changes in this revision

Viewing changes to openerp/addons/auction/barcode/common.py

  • Committer: Package Import Robot
  • Author(s): Yolanda Robla
  • Date: 2012-09-20 15:29:00 UTC
  • Revision ID: package-import@ubuntu.com-20120920152900-woyy3yww8z6acmsk
Tags: upstream-6.1-1+dfsg
ImportĀ upstreamĀ versionĀ 6.1-1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.platypus.flowables import Flowable
 
35
from reportlab.lib.units import inch
 
36
import string
 
37
 
 
38
class Barcode(Flowable):
 
39
    """Abstract Base for barcodes. Includes implementations of
 
40
    some methods suitable for the more primitive barcode types"""
 
41
    
 
42
    def __init__(self, value = ''):
 
43
        self.value = value
 
44
        
 
45
        if not hasattr(self, 'gap'):
 
46
            self.gap = None
 
47
            
 
48
        self.validate()
 
49
        self.encode()
 
50
        #print self.encoded
 
51
        self.decompose()
 
52
        #print self.decomposed
 
53
        self.computeSize()
 
54
 
 
55
    def validate(self):
 
56
        self.valid = 1
 
57
        self.validated = self.value
 
58
 
 
59
    def encode(self):
 
60
        self.encoded = self.validated
 
61
 
 
62
    def decompose(self):
 
63
        self.decomposed = self.encoded
 
64
 
 
65
    def computeSize(self, *args):
 
66
        xdim = self.xdim
 
67
        wx = xdim * self.ratio
 
68
 
 
69
        if self.gap == None:
 
70
            self.gap = xdim
 
71
            
 
72
        w = 0.0
 
73
        
 
74
        for c in self.decomposed:
 
75
            if c in 'sb':
 
76
                w = w + xdim
 
77
            elif c in 'SB':
 
78
                w = w + wx
 
79
            else: # 'i'
 
80
                w = w + self.gap
 
81
    
 
82
        if self.height is None:
 
83
            self.height = w * 0.15
 
84
            self.height = max(0.25 * inch, self.height)
 
85
            if self.bearers:
 
86
                self.height = self.height + self.bearers * 2.0 * xdim
 
87
 
 
88
        if self.quiet:
 
89
            w = w + self.lquiet + self.rquiet
 
90
            self.xo = self.lquiet
 
91
        else:
 
92
            self.xo = 0.0
 
93
            
 
94
        self.width = w
 
95
 
 
96
    def draw(self):
 
97
        xdim = self.xdim
 
98
        wx = xdim * self.ratio
 
99
    
 
100
        left = self.xo
 
101
        b = self.bearers * xdim
 
102
        bb = b * 0.5
 
103
        tb = self.height - (b * 1.5)
 
104
 
 
105
        for c in self.decomposed:
 
106
            if c == 'i':
 
107
                left = left + self.gap
 
108
            elif c == 's':
 
109
                left = left + xdim
 
110
            elif c == 'S':
 
111
                left = left + wx
 
112
            elif c == 'b':
 
113
                self.rect(left, bb, xdim, tb)
 
114
                left = left + xdim
 
115
            elif c == 'B':
 
116
                self.rect(left, bb, wx, tb)
 
117
                left = left + wx
 
118
                
 
119
        if self.bearers:
 
120
            self.rect(self.lquiet, 0.0, \
 
121
                self.width - (self.lquiet + self.rquiet), b)
 
122
            self.rect(self.lquiet, self.height - b, \
 
123
                self.width - (self.lquiet + self.rquiet), b)
 
124
 
 
125
    def rect(self, x, y, w, h):
 
126
        self.canv.rect(x, y, w, h, stroke=0, fill=1)
 
127
 
 
128
 
 
129
class MultiWidthBarcode(Barcode):
 
130
    """Base for variable-bar-width codes like Code93 and Code128"""
 
131
    
 
132
    def computeSize(self, *args):
 
133
        xdim = self.xdim
 
134
        oa, oA = ord('a') - 1, ord('A') - 1
 
135
 
 
136
        w = 0.0
 
137
        
 
138
        for c in self.decomposed:
 
139
            oc = ord(c)
 
140
            if c in string.lowercase:
 
141
                w = w + xdim * (oc - oa)
 
142
            elif c in string.uppercase:
 
143
                w = w + xdim * (oc - oA)
 
144
    
 
145
        if self.height is None:
 
146
            self.height = w * 0.15
 
147
            self.height = max(0.25 * inch, self.height)
 
148
 
 
149
        if self.quiet:
 
150
            w = w + self.lquiet + self.rquiet
 
151
            self.xo = self.lquiet
 
152
        else:
 
153
            self.xo = 0.0
 
154
            
 
155
        self.width = w
 
156
 
 
157
    def draw(self):
 
158
        oa, oA = ord('a') - 1, ord('A') - 1
 
159
        xdim = self.xdim
 
160
        left = self.xo
 
161
 
 
162
        for c in self.decomposed:
 
163
            oc = ord(c)
 
164
            if c in string.lowercase:
 
165
                left = left + (oc - oa) * xdim
 
166
            elif c in string.uppercase:
 
167
                w = (oc - oA) * xdim
 
168
                self.rect(left, 0.0, w, self.height)
 
169
                left = left + w
 
170
 
 
171
 
 
172
class I2of5(Barcode):
 
173
    """
 
174
    Interleaved 2 of 5 is a numeric-only barcode.  It encodes an even
 
175
    number of digits; if an odd number is given, a 0 is prepended.
 
176
 
 
177
    Options that may be passed to constructor:
 
178
 
 
179
        value (int, or numeric string. required.):
 
180
            The value to encode.
 
181
   
 
182
        xdim (float, default .0075):
 
183
            X-Dimension, or width of the smallest element
 
184
            Minumum is .0075 inch (7.5 mils).
 
185
            
 
186
        ratio (float, default 2.2):
 
187
            The ratio of wide elements to narrow elements.
 
188
            Must be between 2.0 and 3.0 (or 2.2 and 3.0 if the
 
189
            xdim is greater than 20 mils (.02 inch))
 
190
            
 
191
        gap (float or None, default None):
 
192
            width of intercharacter gap. None means "use xdim".
 
193
        
 
194
        height (float, see default below):
 
195
            Height of the symbol.  Default is the height of the two
 
196
            bearer bars (if they exist) plus the greater of .25 inch
 
197
            or .15 times the symbol's length.
 
198
 
 
199
        checksum (bool, default 1):
 
200
            Wether to compute and include the check digit
 
201
            
 
202
        bearers (float, in units of xdim. default 3.0):
 
203
            Height of bearer bars (horizontal bars along the top and
 
204
            bottom of the barcode). Default is 3 x-dimensions.
 
205
            Set to zero for no bearer bars. (Bearer bars help detect
 
206
            misscans, so it is suggested to leave them on).
 
207
            
 
208
        quiet (bool, default 1):
 
209
            Wether to include quiet zones in the symbol.
 
210
            
 
211
        lquiet (float, see default below):
 
212
            Quiet zone size to left of code, if quiet is true.
 
213
            Default is the greater of .25 inch, or .15 times the symbol's
 
214
            length.
 
215
            
 
216
        rquiet (float, defaults as above):
 
217
            Quiet zone size to right left of code, if quiet is true.
 
218
            
 
219
    Sources of Information on Interleaved 2 of 5:
 
220
 
 
221
    http://www.semiconductor.agilent.com/barcode/sg/Misc/i_25.html
 
222
    http://www.adams1.com/pub/russadam/i25code.html
 
223
 
 
224
    Official Spec, "ANSI/AIM BC2-1995, USS" is available for US$45 from
 
225
    http://www.aimglobal.org/aimstore/
 
226
    """
 
227
 
 
228
    patterns = {
 
229
        'start' : 'bsbs',
 
230
        'stop' : 'Bsb',
 
231
 
 
232
        'B0' : 'bbBBb',     'S0' : 'ssSSs',
 
233
        'B1' : 'BbbbB',     'S1' : 'SsssS',
 
234
        'B2' : 'bBbbB',     'S2' : 'sSssS',
 
235
        'B3' : 'BBbbb',     'S3' : 'SSsss',
 
236
        'B4' : 'bbBbB',     'S4' : 'ssSsS',
 
237
        'B5' : 'BbBbb',     'S5' : 'SsSss',
 
238
        'B6' : 'bBBbb',     'S6' : 'sSSss',
 
239
        'B7' : 'bbbBB',     'S7' : 'sssSS',
 
240
        'B8' : 'BbbBb',     'S8' : 'SssSs',
 
241
        'B9' : 'bBbBb',     'S9' : 'sSsSs'
 
242
    }
 
243
 
 
244
    def __init__(self, value='', **args):
 
245
        self.height = None
 
246
        self.xdim = inch * 0.0075
 
247
        self.ratio = 2.2
 
248
        self.checksum = 1
 
249
        self.bearers = 3.0
 
250
        self.quiet = 1
 
251
        self.lquiet = self.rquiet = None
 
252
 
 
253
        if type(value) == type(1):
 
254
            value = str(value)
 
255
 
 
256
        for (k, v) in args.items():
 
257
            setattr(self, k, v)
 
258
 
 
259
        if self.quiet:
 
260
            if self.lquiet is None:
 
261
                self.lquiet = min(inch * 0.25, self.xdim * 10.0)
 
262
                self.rquiet = min(inch * 0.25, self.xdim * 10.0)
 
263
        else:
 
264
            self.lquiet = self.rquiet = 0.0
 
265
 
 
266
        Barcode.__init__(self, value)
 
267
 
 
268
    def validate(self):
 
269
        vval = ""
 
270
        self.valid = 1
 
271
        for c in string.strip(self.value):
 
272
            if c not in string.digits:
 
273
                self.valid = 0
 
274
                continue
 
275
            vval = vval + c
 
276
        self.validated = vval
 
277
        return vval
 
278
 
 
279
    def encode(self):
 
280
        s = self.validated
 
281
 
 
282
        # make sure result will be a multiple of 2 digits long,
 
283
        # checksum included
 
284
        if ((len(self.validated) % 2 == 0) and self.checksum) \
 
285
        or ((len(self.validated) % 2 == 1) and not self.checksum):
 
286
            s = '0' + s
 
287
 
 
288
        if self.checksum:
 
289
            c = 0
 
290
            cm = 3
 
291
 
 
292
            for d in s:
 
293
                c = c + cm * int(d)
 
294
                if cm == 3:
 
295
                    cm = 1
 
296
                else:
 
297
                    cm = 3
 
298
 
 
299
            d = 10 - (int(d) % 10)
 
300
            s = s + `d`
 
301
 
 
302
        self.encoded = s
 
303
 
 
304
    def decompose(self):
 
305
        dval = self.patterns['start']
 
306
 
 
307
        for i in range(0, len(self.encoded), 2):
 
308
            b = self.patterns['B' + self.encoded[i]]
 
309
            s = self.patterns['S' + self.encoded[i+1]]
 
310
 
 
311
            for i in range(0, len(b)):
 
312
                dval = dval + b[i] + s[i]
 
313
 
 
314
        self.decomposed = dval + self.patterns['stop']
 
315
        return self.decomposed
 
316
 
 
317
 
 
318
 
 
319
class MSI(Barcode):
 
320
    """
 
321
    MSI is a numeric-only barcode.
 
322
 
 
323
    Options that may be passed to constructor:
 
324
 
 
325
        value (int, or numeric string. required.):
 
326
            The value to encode.
 
327
   
 
328
        xdim (float, default .0075):
 
329
            X-Dimension, or width of the smallest element
 
330
            
 
331
        ratio (float, default 2.2):
 
332
            The ratio of wide elements to narrow elements.
 
333
            
 
334
        gap (float or None, default None):
 
335
            width of intercharacter gap. None means "use xdim".
 
336
        
 
337
        height (float, see default below):
 
338
            Height of the symbol.  Default is the height of the two
 
339
            bearer bars (if they exist) plus the greater of .25 inch
 
340
            or .15 times the symbol's length.
 
341
 
 
342
        checksum (bool, default 1):
 
343
            Wether to compute and include the check digit
 
344
            
 
345
        bearers (float, in units of xdim. default 0):
 
346
            Height of bearer bars (horizontal bars along the top and
 
347
            bottom of the barcode). Default is 0 (no bearers).
 
348
            
 
349
        lquiet (float, see default below):
 
350
            Quiet zone size to left of code, if quiet is true.
 
351
            Default is the greater of .25 inch, or 10 xdims.
 
352
            
 
353
        rquiet (float, defaults as above):
 
354
            Quiet zone size to right left of code, if quiet is true.
 
355
            
 
356
    Sources of Information on MSI Bar Code:
 
357
 
 
358
    http://www.semiconductor.agilent.com/barcode/sg/Misc/msi_code.html
 
359
    http://www.adams1.com/pub/russadam/plessy.html
 
360
    """
 
361
 
 
362
    patterns = {
 
363
        'start' : 'Bs',          'stop' : 'bSb',
 
364
 
 
365
        '0' : 'bSbSbSbS',        '1' : 'bSbSbSBs',
 
366
        '2' : 'bSbSBsbS',        '3' : 'bSbSBsBs',
 
367
        '4' : 'bSBsbSbS',        '5' : 'bSBsbSBs',
 
368
        '6' : 'bSBsBsbS',        '7' : 'bSBsBsBs',
 
369
        '8' : 'BsbSbSbS',        '9' : 'BsbSbSBs'
 
370
    }
 
371
 
 
372
    def __init__(self, value="", **args):
 
373
        self.height = None
 
374
        self.xdim = inch * 0.0075
 
375
        self.ratio = 2.2
 
376
        self.checksum = 1
 
377
        self.bearers = 0.0
 
378
        self.quiet = 1
 
379
        self.lquiet = self.rquiet = None
 
380
 
 
381
        if type(value) == type(1):
 
382
            value = str(value)
 
383
 
 
384
        for (k, v) in args.items():
 
385
            setattr(self, k, v)
 
386
 
 
387
        if self.quiet:
 
388
            if self.lquiet is None:
 
389
                self.lquiet = max(inch * 0.25, self.xdim * 10.0)
 
390
                self.rquiet = max(inch * 0.25, self.xdim * 10.0)
 
391
        else:
 
392
            self.lquiet = self.rquiet = 0.0
 
393
 
 
394
        Barcode.__init__(self, value)
 
395
 
 
396
    def validate(self):
 
397
        vval = ""
 
398
        self.valid = 1
 
399
        for c in string.strip(self.value):
 
400
            if c not in string.digits:
 
401
                self.valid = 0
 
402
                continue
 
403
            vval = vval + c
 
404
        self.validated = vval
 
405
        return vval
 
406
 
 
407
    def encode(self):
 
408
        s = self.validated
 
409
 
 
410
        if self.checksum:
 
411
            c = ''
 
412
            for i in range(1, len(s), 2):
 
413
                c = c + s[i]
 
414
            d = str(int(c) * 2)
 
415
            t = 0
 
416
            for c in d:
 
417
                t = t + int(c)
 
418
            for i in range(0, len(s), 2):
 
419
                t = t + int(s[i])
 
420
            c = 10 - (t % 10)
 
421
 
 
422
            s = s + str(c)
 
423
 
 
424
        self.encoded = s
 
425
 
 
426
    def decompose(self):
 
427
        dval = self.patterns['start']
 
428
 
 
429
        for c in self.encoded:
 
430
            dval = dval + self.patterns[c]
 
431
 
 
432
        self.decomposed = dval + self.patterns['stop']
 
433
        return self.decomposed
 
434
 
 
435
 
 
436
 
 
437
class Codabar(Barcode):
 
438
    """
 
439
    Codabar is a numeric plus some puntuation ("-$:/.+") barcode
 
440
    with four start/stop characters (A, B, C, and D).
 
441
 
 
442
    Options that may be passed to constructor:
 
443
 
 
444
        value (string. required.):
 
445
            The value to encode.
 
446
   
 
447
        xdim (float, default .0065):
 
448
            X-Dimension, or width of the smallest element
 
449
            minimum is 6.5 mils (.0065 inch)
 
450
            
 
451
        ratio (float, default 2.0):
 
452
            The ratio of wide elements to narrow elements.
 
453
            
 
454
        gap (float or None, default None):
 
455
            width of intercharacter gap. None means "use xdim".
 
456
        
 
457
        height (float, see default below):
 
458
            Height of the symbol.  Default is the height of the two
 
459
            bearer bars (if they exist) plus the greater of .25 inch
 
460
            or .15 times the symbol's length.
 
461
 
 
462
        checksum (bool, default 0):
 
463
            Wether to compute and include the check digit
 
464
            
 
465
        bearers (float, in units of xdim. default 0):
 
466
            Height of bearer bars (horizontal bars along the top and
 
467
            bottom of the barcode). Default is 0 (no bearers).
 
468
            
 
469
        quiet (bool, default 1):
 
470
            Wether to include quiet zones in the symbol.
 
471
            
 
472
        lquiet (float, see default below):
 
473
            Quiet zone size to left of code, if quiet is true.
 
474
            Default is the greater of .25 inch, or 10 xdim
 
475
            
 
476
        rquiet (float, defaults as above):
 
477
            Quiet zone size to right left of code, if quiet is true.
 
478
            
 
479
    Sources of Information on Codabar
 
480
 
 
481
    http://www.semiconductor.agilent.com/barcode/sg/Misc/codabar.html
 
482
    http://www.barcodeman.com/codabar.html
 
483
 
 
484
    Official Spec, "ANSI/AIM BC3-1995, USS" is available for US$45 from
 
485
    http://www.aimglobal.org/aimstore/
 
486
    """
 
487
 
 
488
    patterns = {
 
489
        '0':    'bsbsbSB',        '1':    'bsbsBSb',        '2':    'bsbSbsB',
 
490
        '3':    'BSbsbsb',        '4':    'bsBsbSb',        '5':    'BsbsbSb',
 
491
        '6':    'bSbsbsB',        '7':    'bSbsBsb',        '8':    'bSBsbsb',
 
492
        '9':    'BsbSbsb',        '-':    'bsbSBsb',        '$':    'bsBSbsb',
 
493
        ':':    'BsbsBsB',        '/':    'BsBsbsB',        '.':    'BsBsBsb',
 
494
        '+':    'bsBsBsB',        'A':    'bsBSbSb',        'B':    'bSbSbsB',
 
495
        'C':    'bsbSbSB',        'D':    'bsbSBSb'
 
496
    }
 
497
 
 
498
    values = {
 
499
        '0' : 0,    '1' : 1,    '2' : 2,    '3' : 3,    '4' : 4,
 
500
        '5' : 5,    '6' : 6,    '7' : 7,    '8' : 8,    '9' : 9,
 
501
        '-' : 10,   '$' : 11,   ':' : 12,   '/' : 13,   '.' : 14,
 
502
        '+' : 15,   'A' : 16,   'B' : 17,   'C' : 18,   'D' : 19
 
503
    }
 
504
 
 
505
    chars = string.digits + "-$:/.+"
 
506
 
 
507
    def __init__(self, value='', **args):
 
508
        self.height = None
 
509
        self.xdim = inch * 0.0065
 
510
        self.ratio = 2.0 # XXX ?
 
511
        self.checksum = 0
 
512
        self.bearers = 0.0
 
513
        self.quiet = 1
 
514
        self.lquiet = self.rquiet = None
 
515
 
 
516
        if type(value) == type(1):
 
517
            value = str(value)
 
518
 
 
519
        for (k, v) in args.items():
 
520
            setattr(self, k, v)
 
521
 
 
522
        if self.quiet:
 
523
            if self.lquiet is None:
 
524
                self.lquiet = min(inch * 0.25, self.xdim * 10.0)
 
525
                self.rquiet = min(inch * 0.25, self.xdim * 10.0)
 
526
        else:
 
527
            self.lquiet = self.rquiet = 0.0
 
528
 
 
529
        Barcode.__init__(self, value)
 
530
 
 
531
    def validate(self):
 
532
        vval = ""
 
533
        self.valid = 1
 
534
        s = string.strip(self.value)
 
535
        for i in range(0, len(s)):
 
536
            c = s[i]
 
537
            if c not in self.chars:
 
538
                if ((i != 0) and (i != len(s) - 1)) or (c not in 'ABCD'):
 
539
                    self.Valid = 0
 
540
                    continue
 
541
            vval = vval + c
 
542
 
 
543
        if vval[0] not in 'ABCD':
 
544
            vval = 'A' + vval
 
545
        if vval[-1] not in 'ABCD':
 
546
            vval = vval + vval[0]
 
547
 
 
548
        self.validated = vval
 
549
        return vval
 
550
 
 
551
    def encode(self):
 
552
        s = self.validated
 
553
 
 
554
        if self.checksum:
 
555
            v = 0
 
556
            for c in s:
 
557
                v = v + self.values[v]
 
558
            v = 16 - (v % 16)
 
559
            s = s + self.chars[v]
 
560
 
 
561
        self.encoded = s
 
562
 
 
563
    def decompose(self):
 
564
        dval = ""
 
565
        for c in self.encoded:
 
566
            dval = dval + self.patterns[c] + 'i'
 
567
        self.decomposed = dval[:-1]            
 
568
        return self.decomposed
 
569
 
 
570
 
 
571
 
 
572
class Code11(Barcode):
 
573
    """
 
574
    Code 11 is an almost-numeric barcode. It encodes the digits 0-9 plus
 
575
    dash ("-"). 11 characters total, hence the name.
 
576
    
 
577
        value (int or string. required.):
 
578
            The value to encode.
 
579
   
 
580
        xdim (float, default .0075):
 
581
            X-Dimension, or width of the smallest element
 
582
            
 
583
        ratio (float, default 2.2):
 
584
            The ratio of wide elements to narrow elements.
 
585
            
 
586
        gap (float or None, default None):
 
587
            width of intercharacter gap. None means "use xdim".
 
588
        
 
589
        height (float, see default below):
 
590
            Height of the symbol.  Default is the height of the two
 
591
            bearer bars (if they exist) plus the greater of .25 inch
 
592
            or .15 times the symbol's length.
 
593
 
 
594
        checksum (0 none, 1 1-digit, 2 2-digit, -1 auto, default -1):
 
595
            How many checksum digits to include. -1 ("auto") means
 
596
            1 if the number of digits is 10 or less, else 2.
 
597
            
 
598
        bearers (float, in units of xdim. default 0):
 
599
            Height of bearer bars (horizontal bars along the top and
 
600
            bottom of the barcode). Default is 0 (no bearers).
 
601
            
 
602
        quiet (bool, default 1):
 
603
            Wether to include quiet zones in the symbol.
 
604
            
 
605
        lquiet (float, see default below):
 
606
            Quiet zone size to left of code, if quiet is true.
 
607
            Default is the greater of .25 inch, or 10 xdim
 
608
            
 
609
        rquiet (float, defaults as above):
 
610
            Quiet zone size to right left of code, if quiet is true.
 
611
            
 
612
    Sources of Information on Code 11:
 
613
 
 
614
    http://www.cwi.nl/people/dik/english/codes/barcodes.html
 
615
    """
 
616
    
 
617
    chars = string.digits + '-'
 
618
    
 
619
    patterns = {
 
620
        '0' : 'bsbsB',        '1' : 'BsbsB',        '2' : 'bSbsB',
 
621
        '3' : 'BSbsb',        '4' : 'bsBsB',        '5' : 'BsBsb',
 
622
        '6' : 'bSBsb',        '7' : 'bsbSB',        '8' : 'BsbSb',
 
623
        '9' : 'Bsbsb',        '-' : 'bsBsb',        'S' : 'bsBSb' # Start/Stop
 
624
    }
 
625
 
 
626
    values = {
 
627
        '0' : 0,    '1' : 1,    '2' : 2,    '3' : 3,    '4' : 4,
 
628
        '5' : 5,    '6' : 6,    '7' : 7,    '8' : 8,    '9' : 9,
 
629
        '-' : 10,
 
630
    }
 
631
 
 
632
    def __init__(self, value='', **args):
 
633
        self.height = None
 
634
        self.xdim = inch * 0.0075
 
635
        self.ratio = 2.2 # XXX ?
 
636
        self.checksum = -1 # Auto 
 
637
        self.bearers = 0.0
 
638
        self.quiet = 1
 
639
        self.lquiet = self.rquiet = None
 
640
 
 
641
        if type(value) == type(1):
 
642
            value = str(value)
 
643
 
 
644
        for (k, v) in args.items():
 
645
            setattr(self, k, v)
 
646
 
 
647
        if self.quiet:
 
648
            if self.lquiet is None:
 
649
                self.lquiet = min(inch * 0.25, self.xdim * 10.0)
 
650
                self.rquiet = min(inch * 0.25, self.xdim * 10.0)
 
651
        else:
 
652
            self.lquiet = self.rquiet = 0.0
 
653
 
 
654
        Barcode.__init__(self, value)
 
655
 
 
656
    def validate(self):
 
657
        vval = ""
 
658
        self.valid = 1
 
659
        s = string.strip(self.value)
 
660
        for i in range(0, len(s)):
 
661
            c = s[i]
 
662
            if c not in self.chars:
 
663
                self.Valid = 0
 
664
                continue
 
665
            vval = vval + c
 
666
 
 
667
        self.validated = vval
 
668
        return vval
 
669
 
 
670
    def encode(self):
 
671
        s = self.validated
 
672
 
 
673
        if self.checksum == -1:
 
674
            if len(s) <= 10:
 
675
                self.checksum = 1
 
676
            else:
 
677
                self.checksum = 2
 
678
 
 
679
        if self.checksum > 0:
 
680
            # compute first checksum
 
681
            i = 0; v = 1; c = 0
 
682
            while i < len(s):
 
683
                c = c + v * string.index(self.chars, s[-(i+1)])
 
684
                i = i + 1; v = v + 1
 
685
                if v > 10:
 
686
                    v = 1
 
687
            s = s + self.chars[c % 11]
 
688
 
 
689
        if self.checksum > 1:
 
690
            # compute second checksum
 
691
            i = 0; v = 1; c = 0
 
692
            while i < len(s):
 
693
                c = c + v * string.index(self.chars, s[-(i+1)])
 
694
                i = i + 1; v = v + 1
 
695
                if v > 9:
 
696
                    v = 1
 
697
            s = s + self.chars[c % 10]
 
698
 
 
699
        self.encoded = 'S' + s + 'S'
 
700
 
 
701
    def decompose(self):
 
702
        dval = ""
 
703
        for c in self.encoded:
 
704
            dval = dval + self.patterns[c] + 'i'
 
705
        self.decomposed = dval[:-1]            
 
706
        return self.decomposed
 
707
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: