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 """
22 from BaseEan import EanBarcode
23 import sys
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' ]
30 class Object(EanBarcode):
31 """Generate EAN6/UPC-E barcode generator"""
32 name = 'upce'
33 lengths = [ 6, 11 ]
34 checks = [ 7, 12 ]
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')
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
50 def fontSize(self):
51 """We need a font size of 10"""
52 return 10
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
61 # Most of the conversions deal
62 # with the specific code parts
63 manufacturer = number[1:6]
64 product = number[6:11]
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
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
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]