summaryrefslogtreecommitdiffstats
path: root/share/extensions/barcode
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/barcode')
-rw-r--r--share/extensions/barcode/Base.py166
-rw-r--r--share/extensions/barcode/BaseEan.py158
-rw-r--r--share/extensions/barcode/Code128.py158
-rw-r--r--share/extensions/barcode/Code25i.py69
-rw-r--r--share/extensions/barcode/Code39.py98
-rw-r--r--share/extensions/barcode/Code39Ext.py68
-rw-r--r--share/extensions/barcode/Code93.py116
-rw-r--r--share/extensions/barcode/Ean13.py43
-rw-r--r--share/extensions/barcode/Ean2.py39
-rw-r--r--share/extensions/barcode/Ean5.py39
-rw-r--r--share/extensions/barcode/Ean8.py38
-rw-r--r--share/extensions/barcode/Rm4scc.py136
-rw-r--r--share/extensions/barcode/Upca.py39
-rw-r--r--share/extensions/barcode/Upce.py100
-rw-r--r--share/extensions/barcode/__init__.py73
-rw-r--r--share/extensions/barcode/__pycache__/Base.cpython-39.pycbin0 -> 4524 bytes
-rw-r--r--share/extensions/barcode/__pycache__/BaseEan.cpython-39.pycbin0 -> 5102 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Code128.cpython-39.pycbin0 -> 3824 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Code25i.cpython-39.pycbin0 -> 1132 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Code39.cpython-39.pycbin0 -> 1650 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Code39Ext.cpython-39.pycbin0 -> 1283 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Code93.cpython-39.pycbin0 -> 2765 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Ean13.cpython-39.pycbin0 -> 946 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Ean2.cpython-39.pycbin0 -> 890 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Ean5.cpython-39.pycbin0 -> 1054 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Ean8.cpython-39.pycbin0 -> 817 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Rm4scc.cpython-39.pycbin0 -> 2502 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Upca.cpython-39.pycbin0 -> 907 bytes
-rw-r--r--share/extensions/barcode/__pycache__/Upce.cpython-39.pycbin0 -> 2333 bytes
-rw-r--r--share/extensions/barcode/__pycache__/__init__.cpython-39.pycbin0 -> 1600 bytes
30 files changed, 1340 insertions, 0 deletions
diff --git a/share/extensions/barcode/Base.py b/share/extensions/barcode/Base.py
new file mode 100644
index 0000000..a4680a7
--- /dev/null
+++ b/share/extensions/barcode/Base.py
@@ -0,0 +1,166 @@
+# 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.
+#
+"""
+Base module for rendering barcodes for Inkscape.
+"""
+
+import itertools
+import sys
+
+from inkex import Group, TextElement, Rectangle
+
+(TEXT_POS_BOTTOM, TEXT_POS_TOP) = range(2)
+(WHITE_BAR, BLACK_BAR, TALL_BAR) = range(3)
+TEXT_TEMPLATE = 'font-size:%dpx;text-align:center;text-anchor:middle;'
+
+try:
+ from typing import Optional
+except ImportError:
+ pass
+
+class Barcode(object):
+ """Provide a base class for all barcode renderers"""
+ default_height = 30
+ font_size = 9
+ name = None # type: Optional[str]
+
+ def error(self, text, msg):
+ """Cause an error to be reported"""
+ sys.stderr.write(
+ "Error encoding '{}' as {} barcode: {}\n".format(text, self.name, msg))
+ return "ERROR"
+
+ def encode(self, text):
+ """
+ Replace this with the encoding function, it should return
+ a string of ones and zeros
+ """
+ raise NotImplementedError("You need to write an encode() function.")
+
+ def __init__(self, param):
+ param = param or {}
+ self.document = param.get('document', None)
+ self.known_ids = []
+ self._extra = []
+
+ self.pos_x = int(param.get('x', 0))
+ self.pos_y = int(param.get('y', 0))
+ self.text = param.get('text', None)
+ self.scale = param.get('scale', 1)
+ self.height = param.get('height', self.default_height)
+ self.pos_text = param.get('text_pos', TEXT_POS_BOTTOM)
+
+ if self.document:
+ self.known_ids = list(self.document.xpath('//@id'))
+
+ if not self.text:
+ raise ValueError("No string specified for barcode.")
+
+ def get_id(self, name='element'):
+ """Get the next useful id (and claim it)"""
+ index = 0
+ while name in self.known_ids:
+ index += 1
+ name = 'barcode{:d}'.format(index)
+ self.known_ids.append(name)
+ return name
+
+ def add_extra_barcode(self, barcode, **kw):
+ """Add an extra barcode along side this one, used for ean13 extras"""
+ from . import get_barcode
+ kw['height'] = self.height
+ kw['document'] = self.document
+ kw['scale'] = None
+ self._extra.append(get_barcode(barcode, **kw).generate())
+
+ def generate(self):
+ """Generate the actual svg from the coding"""
+ string = self.encode(self.text)
+
+ if string == 'ERROR':
+ return
+
+ name = self.get_id('barcode')
+
+ # use an svg group element to contain the barcode
+ barcode = Group()
+ barcode.set('id', name)
+ barcode.set('style', 'fill: black;')
+
+ barcode.transform.add_translate(self.pos_x, self.pos_y)
+ if self.scale:
+ barcode.transform.add_scale(self.scale)
+
+ bar_id = 1
+ bar_offset = 0
+ tops = set()
+
+ for datum in self.graphical_array(string):
+ # Datum 0 tells us what style of bar is to come next
+ style = self.get_style(int(datum[0]))
+ # Datum 1 tells us what width in units,
+ # style tells us how wide a unit is
+ width = int(datum[1]) * int(style['width'])
+
+ if style['write']:
+ tops.add(style['top'])
+ rect = Rectangle()
+ rect.set('x', str(bar_offset))
+ rect.set('y', str(style['top']))
+ if self.pos_text == TEXT_POS_TOP:
+ rect.set('y', str(style['top'] + self.font_size))
+ rect.set('id', "{}_bar{:d}".format(name, bar_id))
+ rect.set('width', str(width))
+ rect.set('height', str(style['height']))
+ barcode.append(rect)
+ bar_offset += width
+ bar_id += 1
+
+ for extra in self._extra:
+ if extra is not None:
+ barcode.append(extra)
+
+ bar_width = bar_offset
+ # Add text at the bottom of the barcode
+ text = TextElement()
+ text.set('x', str(int(bar_width / 2)))
+ text.set('y', str(min(tops) + self.font_size - 1))
+ if self.pos_text == TEXT_POS_BOTTOM:
+ text.set('y', str(self.height + max(tops) + self.font_size))
+ text.set('style', TEXT_TEMPLATE % self.font_size)
+ text.set('xml:space', 'preserve')
+ text.set('id', '{}_text'.format(name))
+ text.text = str(self.text)
+ barcode.append(text)
+ return barcode
+
+ def graphical_array(self, code):
+ """Converts black and white markets into a space array"""
+ return [(x, len(list(y))) for x, y in itertools.groupby(code)]
+
+ def get_style(self, index):
+ """Returns the styles that should be applied to each bar"""
+ result = {'width': 1, 'top': 0, 'write': True}
+ if index == BLACK_BAR:
+ result['height'] = int(self.height)
+ if index == TALL_BAR:
+ result['height'] = int(self.height) + int(self.font_size / 2)
+ if index == WHITE_BAR:
+ result['write'] = False
+ return result
diff --git a/share/extensions/barcode/BaseEan.py b/share/extensions/barcode/BaseEan.py
new file mode 100644
index 0000000..d1c4352
--- /dev/null
+++ b/share/extensions/barcode/BaseEan.py
@@ -0,0 +1,158 @@
+# 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.
+#
+"""
+Some basic common code shared between EAN and UCP generators.
+"""
+
+from .Base import Barcode, TEXT_POS_TOP
+
+try:
+ from typing import Optional, List, Dict
+except ImportError:
+ pass
+
+MAPPING = [
+ # Left side of barcode Family '0'
+ ["0001101", "0011001", "0010011", "0111101", "0100011",
+ "0110001", "0101111", "0111011", "0110111", "0001011"],
+ # Left side of barcode Family '1' and flipped to right side.
+ ["0100111", "0110011", "0011011", "0100001", "0011101",
+ "0111001", "0000101", "0010001", "0001001", "0010111"],
+]
+# This chooses which of the two encodings above to use.
+FAMILIES = ('000000', '001011', '001101', '001110', '010011',
+ '011001', '011100', '010101', '010110', '011010')
+
+
+class EanBarcode(Barcode):
+ """Simple base class for all EAN type barcodes"""
+ lengths = None # type: Optional[List[int]]
+ length = None # type: Optional[int]
+ checks = [] # type: List[int]
+ extras = {} # type: Dict[int, str]
+ magic = 10
+ guard_bar = '202'
+ center_bar = '02020'
+
+ def intarray(self, number):
+ """Convert a string of digits into an array of ints"""
+ return [int(i) for i in number]
+
+ def encode_interleaved(self, family, number, fams=FAMILIES):
+ """Encode any side of the barcode, interleaved"""
+ result = []
+ encset = self.intarray(fams[family])
+ for i in range(len(number)):
+ thismap = MAPPING[encset[i]]
+ result.append(thismap[number[i]])
+ return result
+
+ def encode_right(self, number):
+ """Encode the right side of the barcode, non-interleaved"""
+ result = []
+ for num in number:
+ # The right side is always the reverse of the left's family '1'
+ result.append(MAPPING[1][num][::-1])
+ return result
+
+ def encode_left(self, number):
+ """Encode the left side of the barcode, non-interleaved"""
+ result = []
+ for num in number:
+ result.append(MAPPING[0][num])
+ return result
+
+ def space(self, *spacing):
+ """Space out an array of numbers"""
+ result = ''
+ for space in spacing:
+ if isinstance(space, list):
+ for i in space:
+ result += str(i)
+ elif isinstance(space, int):
+ result += ' ' * space
+ return result
+
+ def get_lengths(self):
+ """Return a list of acceptable lengths"""
+ if self.length:
+ return [self.length]
+ return self.lengths[:]
+
+ def encode(self, code):
+ """Encode any EAN barcode"""
+ code = code.replace(' ', '').strip()
+ guide = code.endswith('>')
+ code = code.strip('>')
+
+ if not code.isdigit():
+ return self.error(code, 'Not a Number, must be digits 0-9 only')
+ lengths = self.get_lengths() + self.checks
+
+ # Allow extra barcodes after the first one
+ if len(code) not in lengths:
+ for extra in self.extras:
+ sep = len(code) - extra
+ if sep in lengths:
+ # Generate a barcode along side this one.
+ self.add_extra_barcode(self.extras[extra], text=code[sep:],
+ x=self.pos_x + 400 * self.scale, text_pos=TEXT_POS_TOP)
+ code = code[:sep]
+
+ if len(code) not in lengths:
+ return self.error(code, 'Wrong size {:d}, must be {} digits'.format(len(code), ', '.join([str(length) for length in lengths])))
+
+ if self.checks:
+ if len(code) not in self.checks:
+ code = self.append_checksum(code)
+ elif not self.verify_checksum(code):
+ return self.error(code, 'Checksum failed, omit for new sum')
+ return self._encode(self.intarray(code), guide=guide)
+
+ def _encode(self, num, guide=False):
+ """
+ Write your EAN encoding function, it's passed in an array of int and
+ it should return a string on 1 and 0 for black and white parts
+ """
+ raise NotImplementedError("_encode should be provided by parent EAN")
+
+ def enclose(self, left, right=()):
+ """Standard Enclosure"""
+ parts = [self.guard_bar] + left
+ parts.append(self.center_bar)
+ parts += list(right) + [self.guard_bar]
+ return ''.join(parts)
+
+ def get_checksum(self, num):
+ """Generate a UPCA/EAN13/EAN8 Checksum"""
+ # Left to right,checksum based on first digits.
+ total = sum([int(n) * (3, 1)[x % 2] for x, n in enumerate(num[::-1])])
+ # Modulous result to a single digit checksum
+ checksum = self.magic - (total % self.magic)
+ if checksum < 0 or checksum >= self.magic:
+ return '0'
+ return str(checksum)
+
+ def append_checksum(self, number):
+ """Apply the checksum to a short number"""
+ return number + self.get_checksum(number)
+
+ def verify_checksum(self, number):
+ """Verify any checksum"""
+ return self.get_checksum(number[:-1]) == number[-1]
diff --git a/share/extensions/barcode/Code128.py b/share/extensions/barcode/Code128.py
new file mode 100644
index 0000000..20876b3
--- /dev/null
+++ b/share/extensions/barcode/Code128.py
@@ -0,0 +1,158 @@
+# 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, 125)) # 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(self.best_block(block))
+ block = ''
+
+ return self.encode_blocks(blocks)
+
+ def best_block(self, block):
+ """If this has lower case then select B over A"""
+ if block.upper() == block:
+ return ['A', block]
+ return ['B', block]
+
+ def encode_blocks(self, 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 == 'A' or b_set == '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
diff --git a/share/extensions/barcode/Code25i.py b/share/extensions/barcode/Code25i.py
new file mode 100644
index 0000000..e655f6c
--- /dev/null
+++ b/share/extensions/barcode/Code25i.py
@@ -0,0 +1,69 @@
+# coding=utf-8
+#
+# Copyright (C) 2010 Geoffrey Mosini
+#
+# 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.
+#
+"""
+Generate barcodes for Code25-interleaved 2 of 5, for Inkscape.
+"""
+
+from .Base import Barcode
+
+# 1 means thick, 0 means thin
+ENCODE = {
+ '0': '00110',
+ '1': '10001',
+ '2': '01001',
+ '3': '11000',
+ '4': '00101',
+ '5': '10100',
+ '6': '01100',
+ '7': '00011',
+ '8': '10010',
+ '9': '01010',
+}
+
+
+class Code25i(Barcode):
+ """Convert a text into string binary of black and white markers"""
+
+ # Start and stop code are already encoded into white (0) and black(1) bars
+ def encode(self, number):
+ if not number.isdigit():
+ return self.error(number, "CODE25 can only encode numbers.")
+
+ # Number of figures to encode must be even,
+ # a 0 is added to the left in case it's odd.
+ if len(number) % 2 > 0:
+ number = '0' + number
+
+ # Number is encoded by pairs of 2 figures
+ size = len(number) // 2
+ encoded = '1010'
+ for i in range(size):
+ # First in the pair is encoded in black (1), second in white (0)
+ black = ENCODE[number[i * 2]]
+ white = ENCODE[number[i * 2 + 1]]
+ for j in range(5):
+ if black[j] == '1':
+ encoded += '11'
+ else:
+ encoded += '1'
+ if white[j] == '1':
+ encoded += '00'
+ else:
+ encoded += '0'
+ return encoded + '1101'
diff --git a/share/extensions/barcode/Code39.py b/share/extensions/barcode/Code39.py
new file mode 100644
index 0000000..a0ee2e2
--- /dev/null
+++ b/share/extensions/barcode/Code39.py
@@ -0,0 +1,98 @@
+# coding=utf-8
+#
+# 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.
+#
+"""
+Python barcode renderer for Code39 barcodes. Designed for use with Inkscape.
+"""
+
+from .Base import Barcode
+
+ENCODE = {
+ '0': '000110100',
+ '1': '100100001',
+ '2': '001100001',
+ '3': '101100000',
+ '4': '000110001',
+ '5': '100110000',
+ '6': '001110000',
+ '7': '000100101',
+ '8': '100100100',
+ '9': '001100100',
+ 'A': '100001001',
+ 'B': '001001001',
+ 'C': '101001000',
+ 'D': '000011001',
+ 'E': '100011000',
+ 'F': '001011000',
+ 'G': '000001101',
+ 'H': '100001100',
+ 'I': '001001100',
+ 'J': '000011100',
+ 'K': '100000011',
+ 'L': '001000011',
+ 'M': '101000010',
+ 'N': '000010011',
+ 'O': '100010010',
+ 'P': '001010010',
+ 'Q': '000000111',
+ 'R': '100000110',
+ 'S': '001000110',
+ 'T': '000010110',
+ 'U': '110000001',
+ 'V': '011000001',
+ 'W': '111000000',
+ 'X': '010010001',
+ 'Y': '110010000',
+ 'Z': '011010000',
+ '-': '010000101',
+ '*': '010010100',
+ '+': '010001010',
+ '$': '010101000',
+ '%': '000101010',
+ '/': '010100010',
+ '.': '110000100',
+ ' ': '011000100',
+}
+
+
+class Code39(Barcode):
+ """Convert a text into string binary of black and white markers"""
+
+ def encode(self, text):
+ self.text = text.upper()
+ result = ''
+ # It is possible for us to encode code39
+ # into full ascii, but this feature is
+ # not enabled here
+ for char in '*' + self.text + '*':
+ if char not in ENCODE:
+ char = '-'
+ result = result + ENCODE[char] + '0'
+
+ # Now we need to encode the code39, best read
+ # the code to understand what it's up to:
+ encoded = ''
+ colour = '1' # 1 = Black, 0 = White
+ for data in result:
+ if data == '1':
+ encoded = encoded + colour + colour
+ else:
+ encoded = encoded + colour
+ colour = colour == '1' and '0' or '1'
+
+ return encoded
diff --git a/share/extensions/barcode/Code39Ext.py b/share/extensions/barcode/Code39Ext.py
new file mode 100644
index 0000000..e9e804a
--- /dev/null
+++ b/share/extensions/barcode/Code39Ext.py
@@ -0,0 +1,68 @@
+# coding=utf-8
+#
+# 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-1301, USA.
+#
+"""
+Python barcode renderer for Code39 Extended barcodes. Designed for Inkscape.
+"""
+
+from .Code39 import Code39
+
+encode = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
+
+map = {}
+
+i = 0
+for char in encode:
+ map[char] = i
+ i += 1
+
+
+# Extended encoding maps for full ASCII Code93
+def getMap(array):
+ result = {}
+ y = 0
+ for x in array:
+ result[chr(x)] = encode[y]
+ y += 1
+
+ return result
+
+
+# MapA is eclectic, but B, C, D are all ASCII ranges
+mapA = getMap([27, 28, 29, 30, 31, 59, 60, 61, 62, 63, 91, 92, 93, 94, 95, 123, 124, 125, 126, 127, 0, 64, 96, 127, 127, 127]) # %
+mapB = getMap(range(1, 26)) # $
+mapC = getMap(range(33, 58)) # /
+mapD = getMap(range(97, 122)) # +
+
+
+class Code39Ext(Code39):
+ def encode(self, text):
+ # We are only going to extend the Code39 barcodes
+ result = ''
+ for char in text:
+ if char in mapA:
+ char = '%' + mapA[char]
+ elif char in mapB:
+ char = '$' + mapB[char]
+ elif char in mapC:
+ char = '/' + mapC[char]
+ elif char in mapD:
+ char = '+' + mapD[char]
+ result = result + char
+
+ return Code39.encode(self, result)
diff --git a/share/extensions/barcode/Code93.py b/share/extensions/barcode/Code93.py
new file mode 100644
index 0000000..e7af072
--- /dev/null
+++ b/share/extensions/barcode/Code93.py
@@ -0,0 +1,116 @@
+# coding=utf-8
+#
+# 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.
+#
+"""
+Python barcode renderer for Code93 barcodes. Designed for use with Inkscape.
+"""
+
+from .Base import Barcode
+
+PALLET = list('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%')
+PALLET.append('($)')
+PALLET.append('(/)')
+PALLET.append('(+)')
+PALLET.append('(%)')
+PALLET.append('MARKER')
+
+MAP = dict((PALLET[i], i) for i in range(len(PALLET)))
+
+
+def get_map(array):
+ """Extended ENCODE maps for full ASCII Code93"""
+ result = {}
+ pos = 10
+ for char in array:
+ result[chr(char)] = PALLET[pos]
+ pos += 1
+ return result
+
+
+# MapA is eclectic, but B, C, D are all ASCII ranges
+MAP_A = get_map([27, 28, 29, 30, 31, 59, 60, 61, 62, 63, 91, 92, 93, 94, 95,
+ 123, 124, 125, 126, 127, 0, 64, 96, 127, 127, 127]) # %
+MAP_B = get_map(range(1, 26)) # $
+MAP_C = get_map(range(33, 58)) # /
+MAP_D = get_map(range(97, 122)) # +
+
+ENCODE = [
+ '100010100', '101001000', '101000100', '101000010', '100101000',
+ '100100100', '100100010', '101010000', '100010010', '100001010',
+ '110101000', '110100100', '110100010', '110010100', '110010010',
+ '110001010', '101101000', '101100100', '101100010', '100110100',
+ '100011010', '101011000', '101001100', '101000110', '100101100',
+ '100010110', '110110100', '110110010', '110101100', '110100110',
+ '110010110', '110011010', '101101100', '101100110', '100110110',
+ '100111010', '100101110', '111010100', '111010010', '111001010',
+ '101101110', '101110110', '110101110', '100100110', '111011010',
+ '111010110', '100110010', '101011110', ''
+]
+
+
+class Code93(Barcode):
+ def encode(self, text):
+ # start marker
+ bits = ENCODE[MAP.get('MARKER', -1)]
+
+ # Extend to ASCII charset ( return Array )
+ text = self.encode_ascii(text)
+
+ # Calculate the checksums
+ text.append(self.checksum(text, 20)) # C
+ text.append(self.checksum(text, 15)) # K
+
+ # Now convert text into the ENCODE bits (black and white stripes)
+ for char in text:
+ bits = bits + ENCODE[MAP.get(char, -1)]
+
+ # end marker and termination bar
+ return bits + ENCODE[MAP.get('MARKER', -1)] + '1'
+
+ def checksum(self, text, mod):
+ """Generate a code 93 checksum"""
+ weight = len(text) % mod
+ check = 0
+ for char in text:
+ check = check + (MAP[char] * weight)
+ # Reset the weight is required
+ weight -= 1
+ if weight == 0:
+ weight = mod
+
+ return PALLET[check % 47]
+
+ # Some characters need re-ENCODE into the code93 specification
+ def encode_ascii(self, text):
+ result = []
+ for char in text:
+ if char in MAP:
+ result.append(char)
+ elif char in MAP_A:
+ result.append('(%)')
+ result.append(MAP_A[char])
+ elif char in MAP_B:
+ result.append('($)')
+ result.append(MAP_B[char])
+ elif char in MAP_C:
+ result.append('(/)')
+ result.append(MAP_C[char])
+ elif char in MAP_D:
+ result.append('(+)')
+ result.append(MAP_D[char])
+ return result
diff --git a/share/extensions/barcode/Ean13.py b/share/extensions/barcode/Ean13.py
new file mode 100644
index 0000000..2f41a9c
--- /dev/null
+++ b/share/extensions/barcode/Ean13.py
@@ -0,0 +1,43 @@
+# coding=utf-8
+#
+# Copyright (C) 2010 Martin Owens
+#
+# Thanks to Lineaire Chez of Inkbar ( www.inkbar.lineaire.net )
+#
+# 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 EAN13 barcodes. Designed for use with Inkscape.
+"""
+
+from .BaseEan import EanBarcode
+
+
+class Ean13(EanBarcode):
+ """Provide an Ean13 barcode generator"""
+ name = 'ean13'
+ extras = {2: 'Ean2', 5: 'Ean5'}
+ checks = [13]
+ lengths = [12]
+
+ def _encode(self, num, guide=False):
+ """Encode an ean13 barcode"""
+ self.text = self.space(num[0:1], 4, num[1:7], 5, num[7:], 7)
+ if guide:
+ self.text = self.text[:-4] + '>'
+ return self.enclose(
+ self.encode_interleaved(num[0], num[1:7]),
+ self.encode_right(num[7:])
+ )
diff --git a/share/extensions/barcode/Ean2.py b/share/extensions/barcode/Ean2.py
new file mode 100644
index 0000000..08c990a
--- /dev/null
+++ b/share/extensions/barcode/Ean2.py
@@ -0,0 +1,39 @@
+# coding=utf-8
+#
+# Copyright (C) 2016 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 EAN2 barcodes. Designed for use with Inkscape.
+"""
+
+from .BaseEan import EanBarcode
+
+FAMS = ['00', '01', '10', '11']
+START = '01011'
+
+
+class Ean2(EanBarcode):
+ """Provide an Ean5 barcode generator"""
+ length = 2
+ name = 'ean5'
+
+ def _encode(self, num, guide=False):
+ if len(num) != 2:
+ num = ([0, 0] + num)[-2:]
+ self.text = ' '.join(self.space(num))
+ family = ((num[0] * 10) + num[1]) % 4
+ return START + '01'.join(self.encode_interleaved(family, num, FAMS))
diff --git a/share/extensions/barcode/Ean5.py b/share/extensions/barcode/Ean5.py
new file mode 100644
index 0000000..074c970
--- /dev/null
+++ b/share/extensions/barcode/Ean5.py
@@ -0,0 +1,39 @@
+# coding=utf-8
+#
+# Copyright (C) 2009 Aaron C Spike
+# 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 EAN5 barcodes. Designed for use with Inkscape.
+"""
+
+from .BaseEan import EanBarcode
+
+FAMS = ['11000', '10100', '10010', '10001', '01100',
+ '00110', '00011', '01010', '01001', '00101']
+START = '01011'
+
+
+class Ean5(EanBarcode):
+ """Provide an Ean5 barcode generator"""
+ name = 'ean5'
+ length = 5
+
+ def _encode(self, num, guide=False):
+ self.text = ' '.join(self.space(num))
+ family = sum([int(n) * int(m) for n, m in zip(num, '39393')]) % 10
+ return START + '01'.join(self.encode_interleaved(family, num, FAMS))
diff --git a/share/extensions/barcode/Ean8.py b/share/extensions/barcode/Ean8.py
new file mode 100644
index 0000000..d8fb2d8
--- /dev/null
+++ b/share/extensions/barcode/Ean8.py
@@ -0,0 +1,38 @@
+# 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 EAN8 barcodes. Designed for use with Inkscape.
+"""
+
+from .BaseEan import EanBarcode
+
+
+class Ean8(EanBarcode):
+ """Provide an EAN8 barcode generator"""
+ name = 'ean8'
+ checks = [8]
+ lengths = [7]
+
+ def _encode(self, num, guide=False):
+ """Encode an ean8 barcode"""
+ self.text = self.space(num[:4], 3, num[4:])
+ return self.enclose(
+ self.encode_left(num[:4]),
+ self.encode_right(num[4:])
+ )
diff --git a/share/extensions/barcode/Rm4scc.py b/share/extensions/barcode/Rm4scc.py
new file mode 100644
index 0000000..5687f63
--- /dev/null
+++ b/share/extensions/barcode/Rm4scc.py
@@ -0,0 +1,136 @@
+# coding=utf-8
+#
+# 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-1301, USA.
+#
+"""
+Python barcode renderer for RM4CC barcodes. Designed for use with Inkscape.
+"""
+
+from .Base import Barcode
+
+map = {
+ '(': '25',
+ ')': '3',
+ '0': '05053535',
+ '1': '05152535',
+ '2': '05153525',
+ '3': '15052535',
+ '4': '15053525',
+ '5': '15152525',
+ '6': '05251535',
+ '7': '05350535',
+ '8': '05351525',
+ '9': '15250535',
+ 'A': '15251525',
+ 'B': '15350525',
+ 'C': '05253515',
+ 'D': '05352515',
+ 'E': '05353505',
+ 'F': '15252515',
+ 'G': '15253505',
+ 'H': '15352505',
+ 'I': '25051535',
+ 'J': '25150535',
+ 'K': '25151525',
+ 'L': '35050535',
+ 'M': '35051525',
+ 'N': '35150525',
+ 'O': '25053525',
+ 'P': '25152515',
+ 'Q': '25153505',
+ 'R': '35052515',
+ 'S': '35053505',
+ 'T': '35152505',
+ 'U': '25251515',
+ 'V': '25350515',
+ 'W': '25351505',
+ 'X': '35250515',
+ 'Y': '35251505',
+ 'Z': '35350505',
+}
+
+check = ['ZUVWXY', '501234', 'B6789A', 'HCDEFG', 'NIJKLM', 'TOPQRS']
+(BAR_TRACK, BAR_DOWN, BAR_UP, BAR_FULL, BAR_NONE, WHITE_SPACE) = range(6)
+
+
+class Rm4scc(Barcode):
+ default_height = 18
+
+ def encode(self, text):
+ result = ''
+
+ text = text.upper()
+ text.replace('(', '')
+ text.replace(')', '')
+
+ text = '(' + text + self.checksum(text) + ')'
+
+ i = 0
+ for char in text:
+ if char in map:
+ result = result + map[char]
+ i += 1
+
+ return result
+
+ # given a string of data, return the check character
+ def checksum(self, text):
+ total_lower = 0
+ total_upper = 0
+ for char in text:
+ if char in map:
+ bars = map[char][0:8:2]
+ lower = 0
+ upper = 0
+
+ if int(bars[0]) & 1:
+ lower += 4
+ if int(bars[1]) & 1:
+ lower += 2
+ if int(bars[2]) & 1:
+ lower += 1
+ if int(bars[0]) & 2:
+ upper += 4
+ if int(bars[1]) & 2:
+ upper += 2
+ if int(bars[2]) & 2:
+ upper += 1
+ total_lower += lower % 6
+ total_upper += upper % 6
+
+ total_lower = total_upper % 6
+ total_upper %= 6
+
+ checkchar = check[total_upper][total_lower]
+ return checkchar
+
+ def get_style(self, index):
+ """Royal Mail Barcodes use a completely different style"""
+ result = {'width': 2, 'write': True, 'top': 0}
+ if index == BAR_TRACK: # Track Bar
+ result['top'] = 6
+ result['height'] = 5
+ elif index == BAR_DOWN: # Decender Bar
+ result['top'] = 6
+ result['height'] = 11
+ elif index == BAR_UP: # Accender Bar
+ result['height'] = 11
+ elif index == BAR_FULL: # Full Bar
+ result['height'] = 17
+ elif index == WHITE_SPACE: # White Space
+ result['write'] = False
+ return result
diff --git a/share/extensions/barcode/Upca.py b/share/extensions/barcode/Upca.py
new file mode 100644
index 0000000..77cb415
--- /dev/null
+++ b/share/extensions/barcode/Upca.py
@@ -0,0 +1,39 @@
+# coding=utf-8
+#
+# 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.
+#
+"""
+Python barcode renderer for UPCA barcodes. Designed for use with Inkscape.
+"""
+
+from .BaseEan import EanBarcode
+
+
+class Upca(EanBarcode):
+ """Provides a renderer for EAN12 aka UPC-A Barcodes"""
+ name = 'upca'
+ font_size = 10
+ lengths = [11]
+ checks = [12]
+
+ def _encode(self, num, guide=False):
+ """Encode for a UPC-A Barcode"""
+ self.text = self.space(num[0:1], 3, num[1:6], 4, num[6:11], 3, num[11:])
+ return self.enclose(
+ self.encode_left(num[0:6]),
+ self.encode_right(num[6:12]),
+ )
diff --git a/share/extensions/barcode/Upce.py b/share/extensions/barcode/Upce.py
new file mode 100644
index 0000000..e341bdd
--- /dev/null
+++ b/share/extensions/barcode/Upce.py
@@ -0,0 +1,100 @@
+# 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
+
+# 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 = self.space(['0'], 2, num[:6], 2, num[-1])
+ code = self.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 = self.convert_e2a(number)
+ result = self.get_checksum(number)
+ return self.convert_a2e(number) + result
+
+ def convert_a2e(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
+ 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]
+ else:
+ # Invalid UPC-A Numbe
+ raise ValueError("Invalid UPC Number")
+
+ def convert_e2a(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]
diff --git a/share/extensions/barcode/__init__.py b/share/extensions/barcode/__init__.py
new file mode 100644
index 0000000..f68d947
--- /dev/null
+++ b/share/extensions/barcode/__init__.py
@@ -0,0 +1,73 @@
+# coding=utf-8
+#
+# Copyright (C) 2014 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-1301, USA.
+#
+# pylint: disable=no-self-use
+"""
+Renderer for barcodes, SVG extension for Inkscape.
+
+For supported barcodes see Barcode module directory.
+"""
+
+
+# This lists all known Barcodes missing from this package
+# ===== UPC-Based Extensions ====== #
+# Code11
+# ========= Code25-Based ========== #
+# Codabar
+# Postnet
+# ITF25
+# ========= Alpha-numeric ========= #
+# Code39Mod
+# USPS128
+# =========== 2D Based ============ #
+# PDF417
+# PDF417-Macro
+# PDF417-Truncated
+# PDF417-GLI
+
+class NoBarcode(object):
+ """Simple class for no barcode"""
+
+ def __init__(self, msg):
+ self.msg = msg
+
+ def encode(self, text):
+ """Encode the text into a barcode pattern"""
+ raise ValueError("No barcode encoder: {}".format(self.msg))
+
+ def generate(self):
+ """Generate actual svg from the barcode pattern"""
+ return None
+
+
+def get_barcode(code, **kw):
+ """Gets a barcode from a list of available barcode formats"""
+ if not code:
+ return NoBarcode("No barcode format given.")
+
+ code = str(code).replace('-', '').strip()
+ module = 'barcode.' + code
+ lst = ['barcode']
+ try:
+ return getattr(__import__(module, fromlist=lst), code)(kw)
+ except ImportError as err:
+ if code in str(err):
+ return NoBarcode("Invalid type of barcode: {}.{}".format(module, code))
+ raise
+ except AttributeError:
+ return NoBarcode("Barcode module is missing barcode class: {}.{}".format(module, code))
diff --git a/share/extensions/barcode/__pycache__/Base.cpython-39.pyc b/share/extensions/barcode/__pycache__/Base.cpython-39.pyc
new file mode 100644
index 0000000..aa8da7a
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Base.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/BaseEan.cpython-39.pyc b/share/extensions/barcode/__pycache__/BaseEan.cpython-39.pyc
new file mode 100644
index 0000000..28ad0ad
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/BaseEan.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Code128.cpython-39.pyc b/share/extensions/barcode/__pycache__/Code128.cpython-39.pyc
new file mode 100644
index 0000000..da22eb5
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Code128.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Code25i.cpython-39.pyc b/share/extensions/barcode/__pycache__/Code25i.cpython-39.pyc
new file mode 100644
index 0000000..fc11498
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Code25i.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Code39.cpython-39.pyc b/share/extensions/barcode/__pycache__/Code39.cpython-39.pyc
new file mode 100644
index 0000000..fd4bab3
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Code39.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Code39Ext.cpython-39.pyc b/share/extensions/barcode/__pycache__/Code39Ext.cpython-39.pyc
new file mode 100644
index 0000000..dac67f3
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Code39Ext.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Code93.cpython-39.pyc b/share/extensions/barcode/__pycache__/Code93.cpython-39.pyc
new file mode 100644
index 0000000..d03fac4
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Code93.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Ean13.cpython-39.pyc b/share/extensions/barcode/__pycache__/Ean13.cpython-39.pyc
new file mode 100644
index 0000000..e69a658
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Ean13.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Ean2.cpython-39.pyc b/share/extensions/barcode/__pycache__/Ean2.cpython-39.pyc
new file mode 100644
index 0000000..d8e9cf9
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Ean2.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Ean5.cpython-39.pyc b/share/extensions/barcode/__pycache__/Ean5.cpython-39.pyc
new file mode 100644
index 0000000..9d24001
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Ean5.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Ean8.cpython-39.pyc b/share/extensions/barcode/__pycache__/Ean8.cpython-39.pyc
new file mode 100644
index 0000000..8dad384
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Ean8.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Rm4scc.cpython-39.pyc b/share/extensions/barcode/__pycache__/Rm4scc.cpython-39.pyc
new file mode 100644
index 0000000..bbc1a35
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Rm4scc.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Upca.cpython-39.pyc b/share/extensions/barcode/__pycache__/Upca.cpython-39.pyc
new file mode 100644
index 0000000..74d648e
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Upca.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/Upce.cpython-39.pyc b/share/extensions/barcode/__pycache__/Upce.cpython-39.pyc
new file mode 100644
index 0000000..888e4a7
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/Upce.cpython-39.pyc
Binary files differ
diff --git a/share/extensions/barcode/__pycache__/__init__.cpython-39.pyc b/share/extensions/barcode/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..3b09d89
--- /dev/null
+++ b/share/extensions/barcode/__pycache__/__init__.cpython-39.pyc
Binary files differ