summaryrefslogtreecommitdiffstats
path: root/share/extensions/barcode/Upce.py
blob: 9404ca2cc6617cc856a98688b1c667ceee79df03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# coding=utf-8
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.
#
"""
Python barcode renderer for UPCE barcodes. Designed for use with Inkscape.
"""

from .BaseEan import EanBarcode
from inkex.localization import inkex_gettext as _

# 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"
    font_size = 10
    lengths = [6, 11]
    checks = [7, 12]
    center_bar = "020"

    def _encode(self, num, guide=False):
        """Generate a UPC-E Barcode"""
        self.text = EanBarcode.space(["0"], 2, num[:6], 2, num[-1])
        code = EanBarcode.encode_interleaved(num[-1], num[:6], FAMS)
        return self.enclose(code)

    def append_checksum(self, number):
        """Generate a UPCE Checksum"""
        if len(number) == 6:
            number = Upce.convert_e2a(number)
        result = self.get_checksum(number)
        return Upce.convert_a2e(number) + result

    @staticmethod
    def convert_a2e(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
        maker = number[1:6]
        product = number[6:11]

        # There are 4 cases to convert:
        if maker[2:] == "000" or maker[2:] == "100" or maker[2:] == "200":
            # Maximum number product code digits can be encoded
            if product[:2] == "00":
                return maker[:2] + product[2:] + maker[2]
        elif maker[3:5] == "00":
            # Now only 2 product code digits can be used
            if product[:3] == "000":
                return maker[:3] + product[3:] + "3"
        elif maker[4] == "0":
            # With even more maker code we have less room for product code
            if product[:4] == "0000":
                return maker[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 maker + product[4]
        # Invalid UPC-A Numbe
        raise ValueError(_("Invalid UPC Number"))

    @staticmethod
    def convert_e2a(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]
        if number[5] == "3":
            return "0" + number[:3] + "00000" + number[3:5]
        if number[5] == "4":
            return "0" + number[:4] + "00000" + number[4]
        return "0" + number[:5] + "0000" + number[5]