Code

Add doctormo's barcode extension. Patch 1681456. Still need to make it work with...
authoracspike <acspike@users.sourceforge.net>
Wed, 25 Apr 2007 00:53:02 +0000 (00:53 +0000)
committeracspike <acspike@users.sourceforge.net>
Wed, 25 Apr 2007 00:53:02 +0000 (00:53 +0000)
14 files changed:
share/extensions/Barcode/Base.py [new file with mode: 0644]
share/extensions/Barcode/Code128.py [new file with mode: 0644]
share/extensions/Barcode/Code39.py [new file with mode: 0644]
share/extensions/Barcode/Code39Ext.py [new file with mode: 0644]
share/extensions/Barcode/Code93.py [new file with mode: 0644]
share/extensions/Barcode/EAN13.py [new file with mode: 0644]
share/extensions/Barcode/EAN8.py [new file with mode: 0644]
share/extensions/Barcode/RM4CC.py [new file with mode: 0644]
share/extensions/Barcode/UPCA.py [new file with mode: 0644]
share/extensions/Barcode/UPCE.py [new file with mode: 0644]
share/extensions/Barcode/__init__.py [new file with mode: 0644]
share/extensions/Makefile.am
share/extensions/render_barcode.inx [new file with mode: 0644]
share/extensions/render_barcode.py [new file with mode: 0644]

diff --git a/share/extensions/Barcode/Base.py b/share/extensions/Barcode/Base.py
new file mode 100644 (file)
index 0000000..e8d5e56
--- /dev/null
@@ -0,0 +1,127 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+import itertools
+import sys
+
+class Barcode:
+       def __init__(self, param={}):
+               self.document = None
+               self.x = 0
+               self.y = 0
+
+               if param.has_key('document'):
+                       self.document = param['document']
+               if param.has_key('x'):
+                       self.x = param['x']
+               if param.has_key('y'):
+                       self.y = param['y']
+
+               if param.has_key('height'):
+                       self.height = param['height']
+               else:
+                       self.height = 30
+
+               self.text   = param['text']
+               self.label  = self.text
+               self.string = self.encode( self.text )
+               if not self.string:
+                       return
+               self.width  = len(self.string)
+               self.data   = self.graphicalArray(self.string)
+
+       def generate(self):
+               if not self.string or not self.data:
+                       return
+
+               data = self.data;
+       
+               # create an SVG document if required
+#              if not self.document:
+#                      self.document = UNKNOWN
+       
+               if not self.document:
+                       sys.stderr.write("No document defined to add barcode to\n")
+                       return
+
+               # We don't have svg documents so lets do something raw:
+               name  = 'barcode'
+
+               # Make sure that the id/name is inique
+               index = 0
+               while (self.document.getElementById(name)):
+                       name = 'barcode' + str(index)
+                       index = index + 1
+
+               # use an svg group element to contain the barcode
+               barcode = self.document.createElement('svg:g')
+               barcode.setAttribute('id', name)
+               barcode.setAttribute('style', 'fill: black;')
+
+               draw    = 1
+               wOffset = int(self.x)
+               id        = 1
+
+               for datum in data:
+                       # Datum 0 tells us what style of bar is to come next
+                       style = self.getStyle(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']:
+                               # Add height for styles such as EA8 where
+                               # the barcode goes into the text
+                               
+                               rect = self.document.createElement('svg:rect')
+                               rect.setAttribute('x',    str(wOffset))
+                               rect.setAttribute('y',    str(style['top']))
+                               rect.setAttribute('width',  str(width))
+                               rect.setAttribute('height', str(style['height']))
+                               rect.setAttribute('id', name + '_bar' + str(id))
+                               barcode.appendChild(rect)
+                       wOffset = int(wOffset) + int(width)
+                       id        = id + 1
+
+               barwidth = wOffset - int(self.x)
+               # Add text at the bottom of the barcode
+               text = self.document.createElement('svg:text')
+               text.setAttribute( 'x', str(int(self.x) + int(barwidth / 2)) )
+               text.setAttribute( 'y', str(int(self.height) + 10 + int(self.y)) )
+               text.setAttribute( 'style', 'font-size:' + self.fontSize() + 'px;text-align:center;text-anchor:middle;' )
+               text.setAttribute( 'xml:space', 'preserve' )
+               text.setAttribute( 'id', name + '_bottomtext' )
+
+               text.appendChild(self.document.createTextNode(str(self.label)))
+               barcode.appendChild(text)
+
+               return barcode
+
+       # Converts black and white markers into a space array
+       def graphicalArray(self, code):
+               return [(x,len(list(y))) for x, y in itertools.groupby(code)]
+
+       def getStyle(self, index):
+               result = { 'width' : 1, 'top' : int(self.y), 'write' : False }
+               if index==1: # Black Bar
+                       result['height'] = int(self.height)
+                       result['write']  = True
+               return result
+
+       def fontSize(self):
+               return '9'
diff --git a/share/extensions/Barcode/Code128.py b/share/extensions/Barcode/Code128.py
new file mode 100644 (file)
index 0000000..0ba9cf2
--- /dev/null
@@ -0,0 +1,123 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+from Base import Barcode
+import math
+import re
+
+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 mapExtra(sd, chars):
+       result = list(sd)
+       for char in chars:
+               result.append(chr(char))
+       result.append('FNC3')
+       result.append('FNC2')
+       result.append('SHIFT')
+       return result
+
+# The mapExtra method is used to slim down the amount
+# of pre code and instead we generate the lists
+charAB = list(r' !"#$%&\()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQSTUVWXYZ\]^_')
+charA = mapExtra(charAB, range(0, 31)) # Offset 64
+charB = mapExtra(charAB, range(96, 125)) # Offset -32
+
+class Object(Barcode):
+       def encode(self, text):
+               result = ''
+               blocks = []
+               block  = ''
+
+               # Split up into sections of numbers, or charicters
+               # This makes sure that all the charicters are encoded
+               # In the best way posible for Code128
+               for datum in re.findall(r'(?:(?:\d\d){2,})|.', text):
+                       if len(datum) == 1:
+                               block = block + datum
+                       else:
+                               if block:
+                                       blocks.append(self.bestBlock(block))
+                                       block = ''
+                               blocks.append( [ 'C', datum ] )
+
+               if block:
+                       blocks.append(self.bestBlock(block))
+                       block = '';
+               
+               self.inclabel = text
+               return self.encodeBlocks(blocks)
+
+       def bestBlock(self, block):
+               # If this has lower case then select B over A
+               if block.upper() == block:
+                       return [ 'B', block ]
+               return [ 'A', block ]
+               
+       def encodeBlocks(self, blocks):
+               total  = 0
+               pos    = 0
+               encode = '';
+       
+               for block in blocks:
+                       set   = block[0]
+                       datum = block[1]
+
+                       # POS :   0,   1
+                       # A   : 101, 103
+                       # B   : 100, 104
+                       # C   :  99, 105
+                       num = 0;
+                       if set == 'A':
+                               num = 101
+                       elif set == 'B':
+                               num = 100
+                       elif set == 'C':
+                               num = 99
+
+                       i = pos
+                       if pos:
+                               num = num + (math.abs(num - 102) * 2)
+                       else:
+                               i = 1
+
+                       total = total + num * i
+                       encode = encode + map[num]
+                       pos = pos + 1
+
+                       if set == 'A' or set == 'B':
+                               chars = charB
+                               if set == 'B':
+                                       chars = charA
+
+                               for char in datum:
+                                       total = total + (chars.index(char) * pos)
+                                       encode = encode + map[chars.index(char)]
+                                       pos = 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 + map[int(char)]
+                                       pos = pos + 1
+       
+               checksum = total % 103
+               encode = encode + map[checksum]
+               encode = encode + map[106]
+               encode = encode + map[107]
+       
+               return encode
+
diff --git a/share/extensions/Barcode/Code39.py b/share/extensions/Barcode/Code39.py
new file mode 100644 (file)
index 0000000..650d27d
--- /dev/null
@@ -0,0 +1,100 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+from Base import Barcode
+
+encoding = {
+       '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 Object(Barcode):
+       # Convert a text into string binary of black and white markers
+       def encode(self, text):
+               text       = text.upper()
+               self.label = text
+               text       = '*' + text + '*'
+               result     = ''
+               # It isposible for us to encode code39
+               # into full ascii, but this feature is
+               # not enabled here
+               for char in text:
+                       if not encoding.has_key(char):
+                               char = '-';
+
+                       result = result + encoding[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
+                       if colour == '1':
+                               colour = '0'
+                       else:
+                               colour = '1'
+
+               self.inclabel = text
+               return encoded;
+
diff --git a/share/extensions/Barcode/Code39Ext.py b/share/extensions/Barcode/Code39Ext.py
new file mode 100644 (file)
index 0000000..d1682a6
--- /dev/null
@@ -0,0 +1,62 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+import Code39
+
+encode = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
+
+map = {}
+
+i = 0
+for char in encode:
+       map[char] = i
+       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 = 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 Object(Code39.Object):
+       def encode(self, text):
+               # We are only going to extend the Code39 barcodes
+               result = ''
+               for char in text:
+                       if mapA.has_key(char):
+                               char = '%' + mapA[char]
+                       elif mapB.has_key(char):
+                               char = '$' + mapB[char]
+                       elif mapC.has_key(char):
+                               char = '/' + mapC[char]
+                       elif mapD.has_key(char):
+                               char = '+' + mapD[char]
+                       result = result + char
+
+               return Code39.Object.encode(self, result);
+
diff --git a/share/extensions/Barcode/Code93.py b/share/extensions/Barcode/Code93.py
new file mode 100644 (file)
index 0000000..5b013c5
--- /dev/null
@@ -0,0 +1,111 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+from Base import Barcode
+
+chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%'
+encode = list(chars)
+encode.append('($)')
+encode.append('(/)')
+encode.append('(+)')
+encode.append('(%)')
+encode.append('MARKER')
+
+map = {}
+
+i = 0
+for char in encode:
+       map[char] = i
+       i = i + 1
+
+# Extended encoding maps for full ASCII Code93
+def getMap(array):
+
+       result = {}
+       y = 10
+
+       for x in array:
+               result[chr(x)] = encode[y]
+               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)) # +
+
+encoding = '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'.split()
+
+class Object(Barcode):
+       def encode(self, text):
+               bits = self.encode93('MARKER')
+
+               # Extend to ASCII charset ( return Array )
+               text = self.encodeAscii(text)
+
+               # Calculate the checksums
+               text.append(self.checksum(text, 20)) # C
+               text.append(self.checksum(text, 15)) # K
+
+               # Now convert text into the encoding bits (black and white stripes)     
+               for char in text:
+                       bits = bits + self.encode93(char)
+
+               self.inclabel = text
+               return bits
+
+       def checksum(self, text, mod):
+               weight = len(text) % mod
+               check  = 0
+               for char in text:
+                       check = check + (map[char] * weight)
+                       # Reset the weight is required
+                       weight = weight - 1
+                       if weight == 0:
+                               weight = mod
+
+               return encode[check % 47]
+
+       # Some charicters need re-encoding into the code93 specification
+       def encodeAscii(self, text):
+               result = []
+               for char in text:
+                       if map.has_key(char):
+                               result.append(char)
+                       elif mapA.has_key(char):
+                               result.append('(%)')
+                               result.append(mapA[char])
+                       elif mapB.has_key(char):
+                               result.append('($)')
+                               result.append(mapB[char])
+                       elif mapC.has_key(char):
+                               result.append('(/)')
+                               result.append(mapC[char])
+                       elif mapD.has_key(char):
+                               result.append('(+)')
+                               result.append(mapD[char])
+                               
+               return result
+
+       def encode93(self, char):
+               if map.has_key(char):
+                       return encoding[map[char]]
+               return ''
+
diff --git a/share/extensions/Barcode/EAN13.py b/share/extensions/Barcode/EAN13.py
new file mode 100644 (file)
index 0000000..c1d7286
--- /dev/null
@@ -0,0 +1,100 @@
+'''
+Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+from Base import Barcode
+import sys
+
+mapLeftFaimly = [
+       [ "0001101","0011001","0010011","0111101","0100011","0110001","0101111","0111011","0110111","0001011" ],
+       [ "0100111","0110011","0011011","0100001","0011101","0111001","0000101","0010001","0001001","0010111" ],
+]
+mapRight   = [ "1110010","1100110","1101100","1000010","1011100","1001110","1010000","1000100","1001000","1110100" ]
+mapFaimly  = [ '000000','001011','001101','001110','010011','011001','011100','010101','010110','011010' ]
+
+guardBar = '202';
+centerBar = '02020';
+
+class Object(Barcode):
+       def encode(self, number):
+               result = ''
+
+               if len(number) < 12 or len(number) > 13 or not number.isdigit():
+                       sys.stderr.write("Can not encode '" + number + "' into EAN13 Barcode, Size must be 12 numbers only\n")
+                       return
+
+               if len(number) == 12:
+                       number = number + self.getChecksum(number)
+               else:
+                       if not self.varifyChecksum(number):
+                               sys.stderr.write("EAN13 Checksum not correct for this barcode, omit last charicter to generate new checksum.\n")
+                               return
+
+               result = result + guardBar
+               family = mapFaimly[int(number[0])]
+
+               i = 0
+               for i in range(0,6):
+                       mapLeft = mapLeftFaimly[int(family[i])]
+                       result += mapLeft[int(number[i+1])]
+
+               result += centerBar
+
+               for i in range (7,13):
+                       result += mapRight[int(number[i])]
+
+               result = result + guardBar;
+
+               self.label    = number[0] + '    ' + number[1:7] + '    ' + number[7:] + '       '
+               self.inclabel = self.label
+               return result;
+
+       def getChecksum(self, number):
+               # UPCA/EAN13
+               weight=[3,1]*6
+               magic=10
+               sum = 0
+               # We need to work from left to right so reverse
+               number = number[::-1]
+               # checksum based on first 12 digits.
+               for i in range(len(number)):
+                  sum = sum + int(number[i]) * weight[i]
+
+               # Mod it down to a single digit
+               z = ( magic - (sum % magic) ) % magic
+               if z < 0 or z >= magic:
+                  return 0
+
+               return str(z)
+
+       def varifyChecksum(self, number):
+               new = self.computeChecksum(number[:12])
+               existing = number[12]
+               return new == existing
+
+       def getStyle(self, index):
+               result = { 'width' : '1', 'top' : int(self.y), 'write' : True }
+               if index==0: # White Space
+                       result['write'] = False
+               elif index==1: # Black Bar
+                       result['height'] = int(self.height)
+               elif index==2: # Guide Bar
+                       result['height'] = int(self.height) + 5
+               return result
+
diff --git a/share/extensions/Barcode/EAN8.py b/share/extensions/Barcode/EAN8.py
new file mode 100644 (file)
index 0000000..e0534ec
--- /dev/null
@@ -0,0 +1,83 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+from Base import Barcode
+import sys
+
+leftMap = [ '0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011' ]
+rightMap = [ '1110010', '1100110', '1101100', '1000010', '1011100', '1001110', '1010000', '1000100', '1001000', '1110100' ]
+weightMap = [ 3, 1, 3, 1, 3, 1, 3 ]
+
+guardBar = '202';
+centerBar = '02020';
+
+class Object(Barcode):
+       def encode(self, number):
+               result = ''
+
+               # Rejig the label for use
+               self.label = number[:4] + '   ' + number[4:]
+
+               if len(number) < 7 or len(number) > 8 or not number.isdigit():
+                       sys.stderr.write("Can not encode '" + number + "' into EAN8 Barcode, Size must be 7 or 8 Numbers only\n")
+
+               if len(number) == 7:
+                       number = number + self.calculateChecksum(number)
+
+               result = result + guardBar
+       
+               i = 0
+               for num in number:
+                       if i >= 4:
+                               result = result + rightMap[int(num)]
+                       else:
+                               result = result + leftMap[int(num)]
+                       
+                       i = i + 1
+                       if i == 4:
+                               result = result + centerBar;
+
+               result = result + guardBar;
+
+               self.inclabel = '  ' + number[:4] + '   ' + number[4:]
+               return result;
+
+
+       def calculateChecksum(self, number):
+               weight = 0;
+               i = 0;
+       
+               for num in number:
+                       weight = weight + (int(num) * weightMap[i])
+                       i = i + 1
+       
+               weight = 10 - (weight % 10)
+               if weight == 10:
+                       weight = 0
+               return str(weight);
+
+       def getStyle(self, index):
+               result = { 'width' : '1', 'top' : int(self.y), 'write' : True }
+               if index==0: # White Space
+                       result['write'] = False
+               elif index==1: # Black Bar
+                       result['height'] = int(self.height)
+               elif index==2: # Guide Bar
+                       result['height'] = int(self.height) + 8
+               return result
+
diff --git a/share/extensions/Barcode/RM4CC.py b/share/extensions/Barcode/RM4CC.py
new file mode 100644 (file)
index 0000000..7b5f54e
--- /dev/null
@@ -0,0 +1,130 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+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']
+
+class Object(Barcode):
+       def encode(self, text):
+               result = ''
+
+               self.height = 18
+               text = text.upper()
+               text.replace('(', '')
+               text.replace(')', '')
+
+               text = '(' + text + self.checksum(text) + ')'
+
+               i = 0
+               for char in text:
+                       if map.has_key(char):
+                               result = result + map[char]
+                       
+                               i = i + 1
+
+               self.inclabel = text
+               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 map.has_key(char):
+                               bars = map[char][0:8:2]
+                               lower = 0
+                               upper = 0
+
+                               if int(bars[0]) & 1:
+                                       lower = lower + 4 
+                               if int(bars[1]) & 1:
+                                       lower = lower + 2
+                               if int(bars[2]) & 1:
+                                       lower = lower + 1
+                               if int(bars[0]) & 2:
+                                       upper = upper + 4
+                               if int(bars[1]) & 2:
+                                       upper = upper + 2
+                               if int(bars[2]) & 2:
+                                       upper = upper + 1
+                       total_lower = total_lower + (lower % 6)
+                       total_upper = total_upper + (upper % 6)
+
+               total_lower = total_upper % 6
+               total_upper = total_upper % 6
+       
+               checkchar = check[total_upper][total_lower]
+               return checkchar
+
+       def getStyle(self, index):
+               result = { 'width' : 2, 'write' : True, 'top' : int(self.y) }
+               if index==0: # Track Bar
+                       result['top']   = result['top'] + 6
+                       result['height'] = 5
+               elif index==1: # Decender Bar
+                       result['top']   = result['top'] + 6
+                       result['height'] = 11
+               elif index==2: # Accender Bar
+                       result['height'] = 11
+               elif index==3: # Full Bar
+                       result['height'] = 17
+               elif index==5: # 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 (file)
index 0000000..b67d083
--- /dev/null
@@ -0,0 +1,58 @@
+'''
+Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+import EAN13
+from EAN13 import mapLeftFaimly, guardBar, centerBar, mapRight
+import sys
+
+class Object(EAN13.Object):
+       def encode(self, number):
+               result = ''
+
+               if len(number) < 11 or len(number) > 12 or not number.isdigit():
+                       sys.stderr.write("Can not encode '" + number + "' into UPC-A Barcode, Size must be 11 numbers only, and 1 check digit (optional).\n")
+                       return
+
+               if len(number) == 11:
+                       number = number + self.getChecksum(number)
+               else:
+                       if not self.varifyChecksum(number):
+                               sys.stderr.write("EAN13 Checksum not correct for this barcode, omit last charicter to generate new checksum.\n")
+                               return
+
+               result = result + guardBar
+
+               i = 0
+               for i in range(0,6):
+                       result += mapLeftFaimly[0][int(number[i])]
+
+               result += centerBar
+
+               for i in range (6,12):
+                       result += mapRight[int(number[i])]
+
+               result = result + guardBar;
+
+               self.label    = number[0] + '   ' + number[1:6] + '    ' + number[6:11] + '   ' + number[11]
+               self.inclabel = self.label
+               return result;
+
+       def fontSize(self):
+               return '10'
diff --git a/share/extensions/Barcode/UPCE.py b/share/extensions/Barcode/UPCE.py
new file mode 100644 (file)
index 0000000..0ad5186
--- /dev/null
@@ -0,0 +1,129 @@
+'''
+Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+import EAN13
+from EAN13 import mapLeftFaimly, guardBar, centerBar
+import sys
+
+mapFamily  = [ '000111','001011','001101','001110','010011','011001','011100','010101','010110','011010' ]
+
+class Object(EAN13.Object):
+       def encode(self, number):
+               result = ''
+
+               l = len(number)
+
+               if (l != 6 and l != 7  and l != 11 and l != 12) or not number.isdigit():
+                       sys.stderr.write("Can not encode '" + number + "' into UPC-E Barcode, Size must be 6 numbers only, and 1 check digit (optional)\nOr a convertable 11 digit UPC-A number with 1 check digit (also optional).\n")
+                       return
+
+               echeck = None
+               if l==7 or l==12:
+                       echeck = number[-1]
+                       number = number[:-1]
+                       sys.stderr.write("CHECKSUM FOUND!")
+                       l -= 1
+
+               if l==6:
+                       number = self.ConvertEtoA(number)
+
+               if not echeck:
+                       echeck = self.getChecksum(number)
+               else:
+                       if not self.varifyChecksum(number + echeck):
+                               sys.stderr.write("UPC-E Checksum not correct for this barcode, omit last charicter to generate new checksum.\n")
+                               return
+
+               number = self.ConvertAtoE(number)
+               if not number:
+                       sys.stderr.write("UPC-A code could not be converted into a UPC-E barcode, please follow the UPC guide or enter a 6 digit UPC-E number..\n")
+                       return
+
+               number = number
+
+               result = result + guardBar
+               # The check digit isn't stored as bars but as a mirroring system. :-(
+               family = mapFamily[int(echeck)]
+
+               i = 0
+               for i in range(0,6):
+                       result += mapLeftFaimly[int(family[i])-1][int(number[i])]
+
+               result = result + centerBar + '2';
+
+               self.label    = '0  ' + number[:6] + '  ' + echeck
+               self.inclabel = self.label
+               return result;
+
+       def fontSize(self):
+               return '10'
+
+       def ConvertAtoE(self, number):
+               # Converting UPC-A to UPC-E
+
+               # All UPC-E Numbers use number system 0
+               if number[0] != '0' or len(number)!=11:
+                       # If not then the code is invalid
+                       return None
+
+               # 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
+                       return None
+
+       def ConvertEtoA(self, number):
+               # Convert UPC-E to UPC-A
+
+               # 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]=='0' or number[5]=='1' or number[5]=='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 (file)
index 0000000..a455c3b
--- /dev/null
@@ -0,0 +1,81 @@
+
+'''
+Barcodes SVG Extention
+
+Supported Barcodes: EAN8, EAN13, Code39, Code39 Extended, Code93, Code128, RM4CC(RM4SCC)
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+# This lists all known Barcodes missing from this package
+# =========== UPC-Based =========== #
+# ISBN (EAN13)
+# ===== UPC-Based Extensions ====== #
+# Code11
+# ========= Code25-Based ========== #
+# Code25
+# Codabar
+# Postnet
+# ITF25
+# ========= Alpha-numeric ========= #
+# Code39Mod
+# EAN128 (Code128)
+# USPS128 
+# =========== 2D Based ============ #
+# PDF417
+# PDF417-Macro
+# PDF417-Truncated
+# PDF417-GLI
+
+import sys
+
+def getBarcode(format, param={}):
+       if format:
+               format = str(format).lower()
+               format = format.replace('-', '')
+               format = format.replace(' ', '')
+               if format=='code39':
+                       import Code39
+                       return Code39.Object(param)
+               elif format=='code39ext':
+                       import Code39Ext
+                       return Code39Ext.Object(param)
+               elif format=='code93':
+                       import Code93
+                       return Code93.Object(param)
+               elif format=='code128':
+                       import Code128
+                       return Code128.Object(param)
+
+               elif format in ['rm4cc', 'rm4scc']:
+                       import RM4CC
+                       return RM4CC.Object(param)
+
+               elif format == 'upca':
+                       import UPCA
+                       return UPCA.Object(param)
+               elif format == 'upce':
+                       import UPCE
+                       return UPCE.Object(param)
+               elif format in ['ean13', 'ucc13','jan']:
+                       import EAN13
+                       return EAN13.Object(param)
+               elif format in ['ean8', 'ucc8']:
+                       import EAN8
+                       return EAN8.Object(param)
+       sys.stderr.write("Invalid format for barcode: " + str(format) + "\n")
+
index 0ce2bba4af6056625bf973141b8d3833295574bb..46cb372a9124be576aa1a4ba5789fff1f216540f 100644 (file)
@@ -66,6 +66,7 @@ extensions = \
        ps2pdf.sh \
        pturtle.py \
        radiusrand.py \
+       render_barcode.py \
        rtree.py \
        rubberstretch.py\
        simplepath.py \
@@ -151,6 +152,7 @@ modules = \
        radiusrand.inx \
        randompnt.inx \
        randompos.inx \
+       render_barcode.inx \
        rtree.inx \
        sk_input.inx \
        straightseg.inx \
diff --git a/share/extensions/render_barcode.inx b/share/extensions/render_barcode.inx
new file mode 100644 (file)
index 0000000..05062de
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<inkscape-extension>
+  <_name>Barcode</_name>
+  <id>org.inkscape.render.barcode</id>
+  <dependency type="executable" location="extensions">inkex.py</dependency>
+  <dependency type="executable" location="extensions">render_barcode.py</dependency>
+  <param name="type" type="enum" _gui-text="Barcode Type:">
+    <item value="ean13">EAN13</item>
+       <item value="ean8">EAN8</item>
+    <item value="ean13">UPC-A</item>
+    <item value="ean13">UPC-E</item>
+    <item value="ean13">UPC-5</item>
+    <item value="code39">Code39</item>
+    <item value="code39ext">Code39Ext</item>
+    <item value="code93">Code93</item>
+    <item value="code128">Code128</item>
+    <item value="rm4scc">RM4SCC</item>
+  </param>
+  <param name="text" type="string" _gui-text="Barcode Data:"></param>
+  <param name="height" type="int" _gui-text="Bar Height:" min="20" max="80">30</param>
+  <effect>
+    <object-type>all</object-type>
+    <effects-menu>
+      <submenu _name="Render"/>
+    </effects-menu>
+  </effect>
+  <script>
+    <command reldir="extensions" interpreter="python">render_barcode.py</command>
+  </script>
+</inkscape-extension>
diff --git a/share/extensions/render_barcode.py b/share/extensions/render_barcode.py
new file mode 100644 (file)
index 0000000..c35507a
--- /dev/null
@@ -0,0 +1,59 @@
+'''
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+'''
+
+import inkex
+import sys
+from Barcode import getBarcode
+
+class InsertBarcode(inkex.Effect):
+       def __init__(self):
+               inkex.Effect.__init__(self)
+               self.OptionParser.add_option("-l", "--height",
+                                               action="store", type="int",
+                                               dest="height", default=30,
+                                               help="Barcode Height")
+               self.OptionParser.add_option("-t", "--type",
+                                               action="store", type="string",
+                                               dest="type", default='',
+                                               help="Barcode Type")
+               self.OptionParser.add_option("-d", "--text",
+                                               action="store", type="string",
+                                               dest="text", default='',
+                                               help="Text to print on barcode")
+
+       def effect(self):
+               x, y = self.view_center
+               object = getBarcode( self.options.type, {
+                       'text'     : self.options.text,
+                       'height'   : self.options.height,
+                       'document' : self.document,
+                       'x'        : x,
+                       'y'        : y,
+               } )
+               if object:
+                       barcode = object.generate()
+                       if barcode:
+                               self.current_layer.appendChild(barcode)
+                       else:
+                               sys.stderr.write("No barcode was generated\n")
+               else:
+                       sys.stderr.write("Unable to make barcode with: " + str(self.options) + "\n")
+
+e = InsertBarcode()
+e.affect()
+