1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
988c5f1b3494ed6af1e6baabd472eda9f8913f25Martin Owens# Authored by Martin Owens <doctormo@gmail.com>
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# Debugged by Ralf Heinecke & Martin Siepmann 2007-09-07
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# Horst Schottky 2010-02-27
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# Copyright (C) 2007 Martin Owens
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# This program is free software; you can redistribute it and/or modify
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# it under the terms of the GNU General Public License as published by
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# the Free Software Foundation; either version 2 of the License, or
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# (at your option) any later version.
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# This program is distributed in the hope that it will be useful,
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# but WITHOUT ANY WARRANTY; without even the implied warranty of
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# GNU General Public License for more details.
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# You should have received a copy of the GNU General Public License
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico# along with this program; if not, write to the Free Software
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico#
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico"""
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin OwensRenderer for Code128/EAN128 codes. Designed for use with Inkscape.
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico"""
040e298be5b23e77e33309d65449072183c82d5cacspike
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owensfrom .Base import Barcode
040e298be5b23e77e33309d65449072183c82d5cacspikeimport re
040e298be5b23e77e33309d65449072183c82d5cacspike
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin OwensCODE_MAP = [
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11011001100', '11001101100', '11001100110', '10010011000', '10010001100',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10001001100', '10011001000', '10011000100', '10001100100', '11001001000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11001000100', '11000100100', '10110011100', '10011011100', '10011001110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10111001100', '10011101100', '10011100110', '11001110010', '11001011100',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11001001110', '11011100100', '11001110100', '11101101110', '11101001100',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11100101100', '11100100110', '11101100100', '11100110100', '11100110010',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11011011000', '11011000110', '11000110110', '10100011000', '10001011000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10001000110', '10110001000', '10001101000', '10001100010', '11010001000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11000101000', '11000100010', '10110111000', '10110001110', '10001101110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10111011000', '10111000110', '10001110110', '11101110110', '11010001110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11000101110', '11011101000', '11011100010', '11011101110', '11101011000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11101000110', '11100010110', '11101101000', '11101100010', '11100011010',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11101111010', '11001000010', '11110001010', '10100110000', '10100001100',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10010110000', '10010000110', '10000101100', '10000100110', '10110010000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10110000100', '10011010000', '10011000010', '10000110100', '10000110010',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11000010010', '11001010000', '11110111010', '11000010100', '10001111010',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10100111100', '10010111100', '10010011110', '10111100100', '10011110100',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10011110010', '11110100100', '11110010100', '11110010010', '11011011110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11011110110', '11110110110', '10101111000', '10100011110', '10001011110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10111101000', '10111100010', '11110101000', '11110100010', '10111011110',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '10111101110', '11101011110', '11110101110', '11010000100', '11010010000',
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens '11010011100', '11000111010', '11']
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owensdef map_extra(data, chars):
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens """Maps the data into the chars"""
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens result = list(data)
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico for char in chars:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico result.append(chr(char))
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico result.append('FNC3')
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico result.append('FNC2')
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico result.append('SHIFT')
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico return result
040e298be5b23e77e33309d65449072183c82d5cacspike
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens# The map_extra method is used to slim down the amount
040e298be5b23e77e33309d65449072183c82d5cacspike# of pre code and instead we generate the lists
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin OwensCHAR_AB = list(" !\"#$%&\'()*+,-./0123456789:;<=>?@"
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_")
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin OwensCHAR_A = map_extra(CHAR_AB, range(0, 31)) # Offset 64
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin OwensCHAR_B = map_extra(CHAR_AB, range(96, 125)) # Offset -32
040e298be5b23e77e33309d65449072183c82d5cacspike
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owensclass Code128(Barcode):
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens """Main barcode object, generates the encoding bits here"""
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico def encode(self, text):
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico blocks = []
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens block = ''
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # Split up into sections of numbers, or charicters
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # This makes sure that all the charicters are encoded
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # In the best way posible for Code128
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico for datum in re.findall(r'(?:(?:\d\d){2,})|(?:^\d\d)|.', text):
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico if len(datum) == 1:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico block = block + datum
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico else:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico if block:
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens blocks.append(self.best_block(block))
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico block = ''
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens blocks.append(['C', datum])
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico if block:
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens blocks.append(self.best_block(block))
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens block = ''
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens return self.encode_blocks(blocks)
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens def best_block(self, block):
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens """If this has lower case then select B over A"""
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico if block.upper() == block:
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens return ['A', block]
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens return ['B', block]
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens def encode_blocks(self, blocks):
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens """Encode the given blocks into A, B or C codes"""
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = ''
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens total = 0
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens pos = 0
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico for block in blocks:
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens b_set = block[0]
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico datum = block[1]
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # POS : 0, 1
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # A : 101, 103
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # B : 100, 104
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico # C : 99, 105
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens num = 0
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens if b_set == 'A':
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico num = 103
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens elif b_set == 'B':
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico num = 104
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens elif b_set == 'C':
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico num = 105
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico i = pos
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico if pos:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico num = 204 - num
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico else:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico i = 1
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico total = total + num * i
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[num]
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico pos = pos + 1
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens if b_set == 'A' or b_set == 'B':
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens chars = CHAR_B
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens if b_set == 'A':
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens chars = CHAR_A
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico for char in datum:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico total = total + (chars.index(char) * pos)
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[chars.index(char)]
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico pos = pos + 1
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico else:
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico for char in (datum[i:i+2] for i in range(0, len(datum), 2)):
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico total = total + (int(char) * pos)
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[int(char)]
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico pos = pos + 1
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico checksum = total % 103
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[checksum]
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[106]
ad9933c3bdd809813acc78673fcc580cd326bcd6Martin Owens encode = encode + CODE_MAP[107]
12a239f8730c2bb6e3738d5e75b3237877594d07Martin Owens
1ef3c8b1b935901dd133c337031a7300334db424JazzyNico return encode
040e298be5b23e77e33309d65449072183c82d5cacspike