Newer
Older
GB_Printer / Dump / share / extensions / Barcode / Upce.py
#
# Copyright (C) 2010 Martin Owens
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
"""
Python barcode renderer for UPCE barcodes. Designed for use with Inkscape.
"""

from BaseEan import EanBarcode
import sys

# This is almost exactly the same as the standard FAMILIES
# But flipped around and with the first 111000 instead of 000000.
FAMS  = [ '111000', '110100', '110010', '110001', '101100',
          '100110', '100011', '101010', '101001', '100101' ]

class Upce(EanBarcode):
    """Generate EAN6/UPC-E barcode generator"""
    name    = 'upce'
    lengths = [ 6, 11 ]
    checks  = [ 7, 12 ]

    def _encode(self, n):
        """Generate a UPC-E Barcode"""
        self.label = self.space(['0'], 2, n[:6], 2, n[-1])
        code = self.encode_interleaved(n[-1], n[:6], FAMS)
        # 202(guard) + code + 020(center) + 202(guard)
        return self.enclose(code, center='020')

    def appendChecksum(self, number):
        """Generate a UPCE Checksum"""
        if len(number) == 6:
            number = self.ConvertEtoA(number)
        result = self.getChecksum(number)
        return self.ConvertAtoE(number) + result

    def fontSize(self):
        """We need a font size of 10"""
        return 10

    def ConvertAtoE(self, number):
        """Converting UPC-A to UPC-E, may cause errors."""
        # All UPC-E Numbers use number system 0
        if number[0] != '0' or len(number)!=11:
            # If not then the code is invalid
            raise ValueError("Invalid UPC Number")

        # Most of the conversions deal
        # with the specific code parts
        manufacturer = number[1:6]
        product = number[6:11]

        # There are 4 cases to convert:
        if manufacturer[2:] == '000' or manufacturer[2:] == '100' or manufacturer[2:] == '200':
            # Maxium number product code digits can be encoded
            if product[:2]=='00':
                return manufacturer[:2] + product[2:] + manufacturer[2]
        elif manufacturer[3:5] == '00':
            # Now only 2 product code digits can be used
            if product[:3]=='000':
                return manufacturer[:3] + product[3:] + '3'
        elif manufacturer[4] == '0':
            # With even more manufacturer code we have less room for product code
            if product[:4]=='0000':
                return manufacturer[0:4] + product[4] + '4'
        elif product[:4]=='0000' and int(product[4]) > 4:
            # The last recorse is to try and squeeze it in the last 5 numbers
            # so long as the product is 00005-00009 so as not to conflict with
            # the 0-4 used above.
            return manufacturer + product[4]
        else:
            # Invalid UPC-A Numbe
            raise ValueError("Invalid UPC Number")

    def ConvertEtoA(self, number):
        """Convert UPC-E to UPC-A by padding with zeros"""
        # It's more likly to convert this without fault
        # But we still must be mindful of the 4 conversions
        if len(number) != 6:
            return None

        if number[5] in ['0', '1', '2']:
            return '0' + number[:2] + number[5] + '0000' + number[2:5]
        elif number[5] == '3':
            return '0' + number[:3] + '00000' + number[3:5]
        elif number[5] == '4':
            return '0' + number[:4] + '00000' + number[4]
        else:
            return '0' + number[:5] + '0000' + number[5]