def render(digits): '''This function converts its input, a string of decimal digits, into a barcode, using the interleaved 2 of 5 format. The input string must not contain an odd number of digits. The output is an SVG string. Wikipedia [ITF Format]: http://en.wikipedia.org/wiki/Interleaved_2_of_5 ''' top = '' bar = '' barcode = [top.format(len(digits) * 14 + 24)] byte_map = { '0': (2, 2, 4, 4, 2), '1': (4, 2, 2, 2, 4), '2': (2, 4, 2, 2, 4), '3': (4, 4, 2, 2, 2), '4': (2, 2, 4, 2, 4), '5': (4, 2, 4, 2, 2), '6': (2, 4, 4, 2, 2), '7': (2, 2, 2, 4, 4), '8': (4, 2, 2, 4, 2), '9': (2, 4, 2, 4, 2) } byte = lambda i: byte_map[digits[i]] def encode(bits, i=0): '''Encodes a string of decimal digits. The output's a binary string, but as a list of ints, all 2s and 4s, rather than zeros and ones, as the bars in the SVG barcode are rendered 2px wide for zeros, 4px for ones.''' if i == len(digits): return bits for odd, even in zip(byte(i), byte(i+1)): bits.extend([odd, even]) return encode(bits, i+2) def svg(bits, i=0, x=4): '''Converts the list of ints returned by `encode` to a list of SVG elements that can be joined to form an SVG string.''' if i == len(bits): return barcode + [''] odd, even = bits[i:i+2] barcode.append(bar.format(x, odd)) return svg(bits, i+2, x+odd+even) # The call to `encode` passes in the itf start code, and the itf end # code's added to the list that `encode` returns. The complete list # is passed to `svg`, which returns a list of SVG element strings # that're joined with newlines to create the actual SVG output. return '\n'.join(svg(encode([2, 2, 2, 2]) + [4, 2, 2, 0]))