1
0
Fork 0
inkscape/share/extensions/barcode/Code128.py
Daniel Baumann 02d935e272
Adding upstream version 1.4.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 23:40:13 +02:00

246 lines
6 KiB
Python

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