~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to share/extensions/Barcode/UPCE.py

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
'''
2
 
Copyright (C) 2007 Martin Owens
3
 
 
4
 
Thanks to Lineaire Chez of Inkbar ( www.inkbar.lineaire.net )
5
 
 
6
 
This program is free software; you can redistribute it and/or modify
7
 
it under the terms of the GNU General Public License as published by
8
 
the Free Software Foundation; either version 2 of the License, or
9
 
(at your option) any later version.
10
 
 
11
 
This program is distributed in the hope that it will be useful,
12
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
GNU General Public License for more details.
15
 
 
16
 
You should have received a copy of the GNU General Public License
17
 
along with this program; if not, write to the Free Software
18
 
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
'''
20
 
 
21
 
import EAN13
22
 
from EAN13 import mapLeftFaimly, guardBar, centerBar
 
1
#
 
2
# Copyright (C) 2010 Martin Owens
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
#
 
18
"""
 
19
Python barcode renderer for UPCE barcodes. Designed for use with Inkscape.
 
20
"""
 
21
 
 
22
from BaseEan import EanBarcode
23
23
import sys
24
24
 
25
 
mapFamily  = [ '000111','001011','001101','001110','010011','011001','011100','010101','010110','011010' ]
26
 
 
27
 
class Object(EAN13.Object):
28
 
        def encode(self, number):
29
 
                result = ''
30
 
 
31
 
                l = len(number)
32
 
 
33
 
                if (l != 6 and l != 7  and l != 11 and l != 12) or not number.isdigit():
34
 
                        sys.stderr.write("Can not encode '" + number + "' into UPC-E Barcode, Size must be 6 numbers only, and 1 check digit (optional)\nOr a convertable 11 digit UPC-A number with 1 check digit (also optional).\n")
35
 
                        return
36
 
 
37
 
                echeck = None
38
 
                if l==7 or l==12:
39
 
                        echeck = number[-1]
40
 
                        number = number[:-1]
41
 
                        sys.stderr.write("CHECKSUM FOUND!")
42
 
                        l -= 1
43
 
 
44
 
                if l==6:
45
 
                        number = self.ConvertEtoA(number)
46
 
 
47
 
                if not echeck:
48
 
                        echeck = self.getChecksum(number)
49
 
                else:
50
 
                        if not self.verifyChecksum(number + echeck):
51
 
                                sys.stderr.write("UPC-E Checksum not correct for this barcode, omit last character to generate new checksum.\n")
52
 
                                return
53
 
 
54
 
                number = self.ConvertAtoE(number)
55
 
                if not number:
56
 
                        sys.stderr.write("UPC-A code could not be converted into a UPC-E barcode, please follow the UPC guide or enter a 6 digit UPC-E number..\n")
57
 
                        return
58
 
 
59
 
                number = number
60
 
 
61
 
                result = result + guardBar
62
 
                # The check digit isn't stored as bars but as a mirroring system. :-(
63
 
                family = mapFamily[int(echeck)]
64
 
 
65
 
                i = 0
66
 
                for i in range(0,6):
67
 
                        result += mapLeftFaimly[int(family[i])-1][int(number[i])]
68
 
 
69
 
                result = result + centerBar + '2';
70
 
 
71
 
                self.label    = '0  ' + number[:6] + '  ' + echeck
72
 
                self.inclabel = self.label
73
 
                return result;
74
 
 
75
 
        def fontSize(self):
76
 
                return '10'
77
 
 
78
 
        def ConvertAtoE(self, number):
79
 
                # Converting UPC-A to UPC-E
80
 
 
81
 
                # All UPC-E Numbers use number system 0
82
 
                if number[0] != '0' or len(number)!=11:
83
 
                        # If not then the code is invalid
84
 
                        return None
85
 
 
86
 
                # Most of the conversions deal
87
 
                # with the specific code parts
88
 
                manufacturer = number[1:6]
89
 
                product = number[6:11]
90
 
 
91
 
                # There are 4 cases to convert:
92
 
                if manufacturer[2:] == '000' or manufacturer[2:] == '100' or manufacturer[2:] == '200':
93
 
                        # Maxium number product code digits can be encoded
94
 
                        if product[:2]=='00':
95
 
                                return manufacturer[:2] + product[2:] + manufacturer[2]
96
 
                elif manufacturer[3:5] == '00':
97
 
                        # Now only 2 product code digits can be used
98
 
                        if product[:3]=='000':
99
 
                                return manufacturer[:3] + product[3:] + '3'
100
 
                elif manufacturer[4] == '0':
101
 
                        # With even more manufacturer code we have less room for product code
102
 
                        if product[:4]=='0000':
103
 
                                return manufacturer[0:4] + product[4] + '4'
104
 
                elif product[:4]=='0000' and int(product[4]) > 4:
105
 
                        # The last recorse is to try and squeeze it in the last 5 numbers
106
 
                        # so long as the product is 00005-00009 so as not to conflict with
107
 
                        # the 0-4 used above.
108
 
                        return manufacturer + product[4]
109
 
                else:
110
 
                        # Invalid UPC-A Numbe
111
 
                        return None
112
 
 
113
 
        def ConvertEtoA(self, number):
114
 
                # Convert UPC-E to UPC-A
115
 
 
116
 
                # It's more likly to convert this without fault
117
 
                # But we still must be mindful of the 4 conversions
118
 
                if len(number)!=6:
119
 
                        return None
120
 
 
121
 
                if number[5]=='0' or number[5]=='1' or number[5]=='2':
122
 
                        return '0' + number[:2] + number[5] + '0000' + number[2:5]
123
 
                elif number[5]=='3':
124
 
                        return '0' + number[:3] + '00000' + number[3:5]
125
 
                elif number[5]=='4':
126
 
                        return '0' + number[:4] + '00000' + number[4]
127
 
                else:
128
 
                        return '0' + number[:5] + '0000' + number[5]
 
25
# This is almost exactly the same as the standard FAMILIES
 
26
# But flipped around and with the first 111000 instead of 000000.
 
27
FAMS  = [ '111000', '110100', '110010', '110001', '101100',
 
28
          '100110', '100011', '101010', '101001', '100101' ]
 
29
 
 
30
class Object(EanBarcode):
 
31
    """Generate EAN6/UPC-E barcode generator"""
 
32
    name    = 'upce'
 
33
    lengths = [ 6, 11 ]
 
34
    checks  = [ 7, 12 ]
 
35
 
 
36
    def _encode(self, n):
 
37
        """Generate a UPC-E Barcode"""
 
38
        self.label = self.space(['0'], 2, n[:6], 2, n[-1])
 
39
        code = self.encode_interleaved(n[-1], n[:6], FAMS)
 
40
        # 202(guard) + code + 020(center) + 202(guard)
 
41
        return self.enclose(code, center='020')
 
42
 
 
43
    def appendChecksum(self, number):
 
44
        """Generate a UPCE Checksum"""
 
45
        if len(number) == 6:
 
46
            number = self.ConvertEtoA(number)
 
47
        result = self.getChecksum(number)
 
48
        return self.ConvertAtoE(number) + result
 
49
 
 
50
    def fontSize(self):
 
51
        """We need a font size of 10"""
 
52
        return 10
 
53
 
 
54
    def ConvertAtoE(self, number):
 
55
        """Converting UPC-A to UPC-E, may cause errors."""
 
56
        # All UPC-E Numbers use number system 0
 
57
        if number[0] != '0' or len(number)!=11:
 
58
            # If not then the code is invalid
 
59
            return None
 
60
 
 
61
        # Most of the conversions deal
 
62
        # with the specific code parts
 
63
        manufacturer = number[1:6]
 
64
        product = number[6:11]
 
65
 
 
66
        # There are 4 cases to convert:
 
67
        if manufacturer[2:] == '000' or manufacturer[2:] == '100' or manufacturer[2:] == '200':
 
68
            # Maxium number product code digits can be encoded
 
69
            if product[:2]=='00':
 
70
                return manufacturer[:2] + product[2:] + manufacturer[2]
 
71
        elif manufacturer[3:5] == '00':
 
72
            # Now only 2 product code digits can be used
 
73
            if product[:3]=='000':
 
74
                return manufacturer[:3] + product[3:] + '3'
 
75
        elif manufacturer[4] == '0':
 
76
            # With even more manufacturer code we have less room for product code
 
77
            if product[:4]=='0000':
 
78
                return manufacturer[0:4] + product[4] + '4'
 
79
        elif product[:4]=='0000' and int(product[4]) > 4:
 
80
            # The last recorse is to try and squeeze it in the last 5 numbers
 
81
            # so long as the product is 00005-00009 so as not to conflict with
 
82
            # the 0-4 used above.
 
83
            return manufacturer + product[4]
 
84
        else:
 
85
            # Invalid UPC-A Numbe
 
86
            return None
 
87
 
 
88
    def ConvertEtoA(self, number):
 
89
        """Convert UPC-E to UPC-A by padding with zeros"""
 
90
        # It's more likly to convert this without fault
 
91
        # But we still must be mindful of the 4 conversions
 
92
        if len(number) != 6:
 
93
            return None
 
94
 
 
95
        if number[5] in ['0', '1', '2']:
 
96
            return '0' + number[:2] + number[5] + '0000' + number[2:5]
 
97
        elif number[5] == '3':
 
98
            return '0' + number[:3] + '00000' + number[3:5]
 
99
        elif number[5] == '4':
 
100
            return '0' + number[:4] + '00000' + number[4]
 
101
        else:
 
102
            return '0' + number[:5] + '0000' + number[5]
129
103