summaryrefslogtreecommitdiffstats
path: root/share/extensions/barcode/Code128.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/barcode/Code128.py')
-rw-r--r--share/extensions/barcode/Code128.py246
1 files changed, 246 insertions, 0 deletions
diff --git a/share/extensions/barcode/Code128.py b/share/extensions/barcode/Code128.py
new file mode 100644
index 0000000..e5f8701
--- /dev/null
+++ b/share/extensions/barcode/Code128.py
@@ -0,0 +1,246 @@
+# coding=utf-8
+#
+# Authored by Martin Owens <doctormo@gmail.com>
+# Debugged by Ralf Heinecke & Martin Siepmann 2007-09-07
+# Horst Schottky 2010-02-27
+#
+# Copyright (C) 2007 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.
+#
+"""
+Renderer for Code128/EAN128 codes. Designed for use with Inkscape.
+"""
+
+import re
+
+from .Base import Barcode
+
+CODE_MAP = [
+ "11011001100",
+ "11001101100",
+ "11001100110",
+ "10010011000",
+ "10010001100",
+ "10001001100",
+ "10011001000",
+ "10011000100",
+ "10001100100",
+ "11001001000",
+ "11001000100",
+ "11000100100",
+ "10110011100",
+ "10011011100",
+ "10011001110",
+ "10111001100",
+ "10011101100",
+ "10011100110",
+ "11001110010",
+ "11001011100",
+ "11001001110",
+ "11011100100",
+ "11001110100",
+ "11101101110",
+ "11101001100",
+ "11100101100",
+ "11100100110",
+ "11101100100",
+ "11100110100",
+ "11100110010",
+ "11011011000",
+ "11011000110",
+ "11000110110",
+ "10100011000",
+ "10001011000",
+ "10001000110",
+ "10110001000",
+ "10001101000",
+ "10001100010",
+ "11010001000",
+ "11000101000",
+ "11000100010",
+ "10110111000",
+ "10110001110",
+ "10001101110",
+ "10111011000",
+ "10111000110",
+ "10001110110",
+ "11101110110",
+ "11010001110",
+ "11000101110",
+ "11011101000",
+ "11011100010",
+ "11011101110",
+ "11101011000",
+ "11101000110",
+ "11100010110",
+ "11101101000",
+ "11101100010",
+ "11100011010",
+ "11101111010",
+ "11001000010",
+ "11110001010",
+ "10100110000",
+ "10100001100",
+ "10010110000",
+ "10010000110",
+ "10000101100",
+ "10000100110",
+ "10110010000",
+ "10110000100",
+ "10011010000",
+ "10011000010",
+ "10000110100",
+ "10000110010",
+ "11000010010",
+ "11001010000",
+ "11110111010",
+ "11000010100",
+ "10001111010",
+ "10100111100",
+ "10010111100",
+ "10010011110",
+ "10111100100",
+ "10011110100",
+ "10011110010",
+ "11110100100",
+ "11110010100",
+ "11110010010",
+ "11011011110",
+ "11011110110",
+ "11110110110",
+ "10101111000",
+ "10100011110",
+ "10001011110",
+ "10111101000",
+ "10111100010",
+ "11110101000",
+ "11110100010",
+ "10111011110",
+ "10111101110",
+ "11101011110",
+ "11110101110",
+ "11010000100",
+ "11010010000",
+ "11010011100",
+ "11000111010",
+ "11",
+]
+
+
+def map_extra(data, chars):
+ """Maps the data into the chars"""
+ result = list(data)
+ for char in chars:
+ result.append(chr(char))
+ result.append("FNC3")
+ result.append("FNC2")
+ result.append("SHIFT")
+ return result
+
+
+# The map_extra method is used to slim down the amount
+# of pre code and instead we generate the lists
+CHAR_AB = list(" !\"#$%&'()*+,-./0123456789:;<=>?@" "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_")
+CHAR_A = map_extra(CHAR_AB, range(0, 31)) # Offset 64
+CHAR_B = map_extra(CHAR_AB, range(96, 127)) # Offset -32
+
+
+class Code128(Barcode):
+ """Main barcode object, generates the encoding bits here"""
+
+ def encode(self, text):
+ blocks = []
+ block = ""
+
+ # Split up into sections of numbers, or characters
+ # This makes sure that all the characters are encoded
+ # In the best way possible for Code128
+ for datum in re.findall(r"(?:(?:\d\d){2,})|(?:^\d\d)|.", text):
+ if len(datum) == 1:
+ block = block + datum
+ else:
+ if block:
+ blocks.append(self.best_block(block))
+ block = ""
+ blocks.append(["C", datum])
+
+ if block:
+ blocks.append(Code128.best_block(block))
+ block = ""
+
+ return Code128.encode_blocks(blocks)
+
+ @staticmethod
+ def best_block(block):
+ """If this has characters above 63, select B over A"""
+ if any(ord(x) > 63 for x in block):
+ return ["B", block]
+ return ["A", block]
+
+ @staticmethod
+ def encode_blocks(blocks):
+ """Encode the given blocks into A, B or C codes"""
+ encode = ""
+ total = 0
+ pos = 0
+
+ for block in blocks:
+ b_set = block[0]
+ datum = block[1]
+
+ # POS : 0, 1
+ # A : 101, 103
+ # B : 100, 104
+ # C : 99, 105
+ num = 0
+ if b_set == "A":
+ num = 103
+ elif b_set == "B":
+ num = 104
+ elif b_set == "C":
+ num = 105
+
+ i = pos
+ if pos:
+ num = 204 - num
+ else:
+ i = 1
+
+ total = total + num * i
+ encode = encode + CODE_MAP[num]
+ pos += 1
+
+ if b_set in ("A", "B"):
+ chars = CHAR_B
+ if b_set == "A":
+ chars = CHAR_A
+
+ for char in datum:
+ total = total + (chars.index(char) * pos)
+ encode = encode + CODE_MAP[chars.index(char)]
+ pos += 1
+ else:
+ for char in (datum[i : i + 2] for i in range(0, len(datum), 2)):
+ total = total + (int(char) * pos)
+ encode = encode + CODE_MAP[int(char)]
+ pos += 1
+
+ checksum = total % 103
+ encode = encode + CODE_MAP[checksum]
+ encode = encode + CODE_MAP[106]
+ encode = encode + CODE_MAP[107]
+
+ return encode