* Merge software and hardware barcodes to one method * Fix wrong sw barcode heigh/width * Add missing param to _sw_barcode call * Make barcode() smarter, improvements and clean up * Use param font_size in sw_barcode() * Update docstrings * Update barcode examples and docs * Add --force_software option to CLI * Attempt to match the sw and hw barcode sizes * Better approximation to native font size * Fix docs build * Update tests at test_function_softbarcode * Fix exception * Move image dpi setting to writter_options * Fix _sw_barcode() docstring param * Fix wrong default param in docstring * improve linkage in documentation --------- Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com> Co-authored-by: Patrick Kanzler <dev@pkanzler.de>
This commit is contained in:
parent
676d2840de
commit
3c11c1b9ab
|
@ -1,17 +1,18 @@
|
||||||
Printing Barcodes
|
Printing Barcodes
|
||||||
-----------------
|
-----------------
|
||||||
:Last Reviewed: 2016-07-31
|
:Last Reviewed: 2023-05-16
|
||||||
|
|
||||||
Most ESC/POS-printers implement barcode-printing.
|
Many printers implement barcode printing natively.
|
||||||
The barcode-commandset is implemented in the barcode-method.
|
This hardware renderered barcodes are fast but the supported formats are limited by the printer itself and different between models.
|
||||||
For a list of compatible barcodes you should check the manual of your printer.
|
However, almost all printers support printing images, so barcode renderization can be performed externally by software and then sent to the printer as an image.
|
||||||
As a rule of thumb: even older Epson-models support most 1D-barcodes.
|
As a drawback, this operation is much slower and the user needs to know and choose the image implementation method supported by the printer's commandset.
|
||||||
To be sure just try some implementations and have a look at the notices below.
|
|
||||||
|
|
||||||
barcode-method
|
barcode-method
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
The barcode-method is rather low-level and orients itself on the implementation of ESC/POS.
|
Since version 3.0, the ``barcode`` method unifies the previous ``barcode`` (hardware) and ``soft_barcode`` (software) methods.
|
||||||
In the future this class could be supplemented by a high-level class that helps the user generating the payload.
|
It is able to choose automatically the best printer implementation for barcode printing based on the capabilities of the printer and the type of barcode desired.
|
||||||
|
To achieve this, it relies on the information contained in the escpos-printer-db profiles.
|
||||||
|
The chosen profile needs to match the capabilities of the printer as closely as possible.
|
||||||
|
|
||||||
.. py:currentmodule:: escpos.escpos
|
.. py:currentmodule:: escpos.escpos
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ from escpos.printer import Usb
|
||||||
|
|
||||||
|
|
||||||
# Adapt to your needs
|
# Adapt to your needs
|
||||||
p = Usb(0x0416, 0x5011, profile="POS-5890")
|
p = Usb(0x0416, 0x5011, profile="TM-T88II")
|
||||||
|
|
||||||
# Print software and then hardware barcode with the same content
|
# Print software and then hardware barcode with the same content
|
||||||
p.soft_barcode("code39", "123456")
|
p.barcode("123456", "CODE39", width=2, force_software=True)
|
||||||
p.text("\n")
|
p.text("\n")
|
||||||
p.text("\n")
|
p.text("\n")
|
||||||
p.barcode("123456", "CODE39")
|
p.barcode("123456", "CODE39")
|
||||||
|
|
|
@ -5,5 +5,5 @@ from escpos.printer import Usb
|
||||||
p = Usb(0x0416, 0x5011, profile="POS-5890")
|
p = Usb(0x0416, 0x5011, profile="POS-5890")
|
||||||
|
|
||||||
# Some software barcodes
|
# Some software barcodes
|
||||||
p.soft_barcode("code128", "Hello")
|
p.barcode("Hello", "code128", width=2, force_software="bitImageRaster")
|
||||||
p.soft_barcode("code39", "1234")
|
p.barcode("1234", "code39", width=2, force_software=True)
|
||||||
|
|
|
@ -161,6 +161,11 @@ ESCPOS_COMMANDS = [
|
||||||
"help": "ESCPOS function type",
|
"help": "ESCPOS function type",
|
||||||
"choices": ["A", "B"],
|
"choices": ["A", "B"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"option_strings": ("--force_software",),
|
||||||
|
"help": "Force render and print barcode as an image",
|
||||||
|
"choices": ["graphics", "bitImageColumn", "bitImageRaster"],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,12 +27,12 @@ FS = b"\x1c"
|
||||||
GS = b"\x1d"
|
GS = b"\x1d"
|
||||||
|
|
||||||
# Feed control sequences
|
# Feed control sequences
|
||||||
CTL_LF = b"\n" # Print and line feed
|
CTL_LF = b"\n" #: Print and line feed
|
||||||
CTL_FF = b"\f" # Form feed
|
CTL_FF = b"\f" #: Form feed
|
||||||
CTL_CR = b"\r" # Carriage return
|
CTL_CR = b"\r" #: Carriage return
|
||||||
CTL_HT = b"\t" # Horizontal tab
|
CTL_HT = b"\t" #: Horizontal tab
|
||||||
CTL_SET_HT = ESC + b"\x44" # Set horizontal tab positions
|
CTL_SET_HT = ESC + b"\x44" #: Set horizontal tab positions
|
||||||
CTL_VT = b"\v" # Vertical tab
|
CTL_VT = b"\v" #: Vertical tab
|
||||||
|
|
||||||
# Printer hardware
|
# Printer hardware
|
||||||
HW_INIT = ESC + b"@" # Clear data in buffer and reset modes
|
HW_INIT = ESC + b"@" # Clear data in buffer and reset modes
|
||||||
|
@ -57,8 +57,8 @@ CD_KICK_5 = _CASH_DRAWER(b"\x01", 50, 50) # Sends a pulse to pin 5 []
|
||||||
|
|
||||||
# Paper Cutter
|
# Paper Cutter
|
||||||
_CUT_PAPER = lambda m: GS + b"V" + m
|
_CUT_PAPER = lambda m: GS + b"V" + m
|
||||||
PAPER_FULL_CUT = _CUT_PAPER(b"\x00") # Full cut paper
|
PAPER_FULL_CUT = _CUT_PAPER(b"\x00") #: Full cut paper
|
||||||
PAPER_PART_CUT = _CUT_PAPER(b"\x01") # Partial cut paper
|
PAPER_PART_CUT = _CUT_PAPER(b"\x01") #: Partial cut paper
|
||||||
|
|
||||||
# Beep (please note that the actual beep sequence may differ between devices)
|
# Beep (please note that the actual beep sequence may differ between devices)
|
||||||
BEEP = b"\x07"
|
BEEP = b"\x07"
|
||||||
|
@ -168,8 +168,8 @@ TXT_STYLE = {
|
||||||
|
|
||||||
# Fonts
|
# Fonts
|
||||||
SET_FONT = lambda n: ESC + b"\x4d" + n
|
SET_FONT = lambda n: ESC + b"\x4d" + n
|
||||||
TXT_FONT_A = SET_FONT(b"\x00") # Font type A
|
TXT_FONT_A = SET_FONT(b"\x00") #: Font type A
|
||||||
TXT_FONT_B = SET_FONT(b"\x01") # Font type B
|
TXT_FONT_B = SET_FONT(b"\x01") #: Font type B
|
||||||
|
|
||||||
# Spacing
|
# Spacing
|
||||||
LINESPACING_RESET = ESC + b"2"
|
LINESPACING_RESET = ESC + b"2"
|
||||||
|
@ -179,23 +179,23 @@ LINESPACING_FUNCS = {
|
||||||
180: ESC + b"3", # line_spacing/180 of an inch, 0 <= line_spacing <= 255
|
180: ESC + b"3", # line_spacing/180 of an inch, 0 <= line_spacing <= 255
|
||||||
}
|
}
|
||||||
|
|
||||||
# Prefix to change the codepage. You need to attach a byte to indicate
|
#: Prefix to change the codepage. You need to attach a byte to indicate
|
||||||
# the codepage to use. We use escpos-printer-db as the data source.
|
#: the codepage to use. We use escpos-printer-db as the data source.
|
||||||
CODEPAGE_CHANGE = ESC + b"\x74"
|
CODEPAGE_CHANGE = ESC + b"\x74"
|
||||||
|
|
||||||
# Barcode format
|
# Barcode format
|
||||||
_SET_BARCODE_TXT_POS = lambda n: GS + b"H" + n
|
_SET_BARCODE_TXT_POS = lambda n: GS + b"H" + n
|
||||||
BARCODE_TXT_OFF = _SET_BARCODE_TXT_POS(b"\x00") # HRI barcode chars OFF
|
BARCODE_TXT_OFF = _SET_BARCODE_TXT_POS(b"\x00") #: HRI barcode chars OFF
|
||||||
BARCODE_TXT_ABV = _SET_BARCODE_TXT_POS(b"\x01") # HRI barcode chars above
|
BARCODE_TXT_ABV = _SET_BARCODE_TXT_POS(b"\x01") #: HRI barcode chars above
|
||||||
BARCODE_TXT_BLW = _SET_BARCODE_TXT_POS(b"\x02") # HRI barcode chars below
|
BARCODE_TXT_BLW = _SET_BARCODE_TXT_POS(b"\x02") #: HRI barcode chars below
|
||||||
BARCODE_TXT_BTH = _SET_BARCODE_TXT_POS(b"\x03") # HRI both above and below
|
BARCODE_TXT_BTH = _SET_BARCODE_TXT_POS(b"\x03") #: HRI both above and below
|
||||||
|
|
||||||
_SET_HRI_FONT = lambda n: GS + b"f" + n
|
_SET_HRI_FONT = lambda n: GS + b"f" + n
|
||||||
BARCODE_FONT_A = _SET_HRI_FONT(b"\x00") # Font type A for HRI barcode chars
|
BARCODE_FONT_A = _SET_HRI_FONT(b"\x00") #: Font type A for HRI barcode chars
|
||||||
BARCODE_FONT_B = _SET_HRI_FONT(b"\x01") # Font type B for HRI barcode chars
|
BARCODE_FONT_B = _SET_HRI_FONT(b"\x01") #: Font type B for HRI barcode chars
|
||||||
|
|
||||||
BARCODE_HEIGHT = GS + b"h" # Barcode Height [1-255]
|
BARCODE_HEIGHT = GS + b"h" #: Barcode Height [1-255]
|
||||||
BARCODE_WIDTH = GS + b"w" # Barcode Width [2-6]
|
BARCODE_WIDTH = GS + b"w" #: Barcode Width [2-6]
|
||||||
|
|
||||||
# NOTE: This isn't actually an ESC/POS command. It's the common prefix to the
|
# NOTE: This isn't actually an ESC/POS command. It's the common prefix to the
|
||||||
# two "print bar code" commands:
|
# two "print bar code" commands:
|
||||||
|
@ -204,7 +204,7 @@ BARCODE_WIDTH = GS + b"w" # Barcode Width [2-6]
|
||||||
# The latter command supports more barcode types
|
# The latter command supports more barcode types
|
||||||
_SET_BARCODE_TYPE = lambda m: GS + b"k" + six.int2byte(m)
|
_SET_BARCODE_TYPE = lambda m: GS + b"k" + six.int2byte(m)
|
||||||
|
|
||||||
# Barcodes for printing function type A
|
#: Barcodes for printing function type A
|
||||||
BARCODE_TYPE_A = {
|
BARCODE_TYPE_A = {
|
||||||
"UPC-A": _SET_BARCODE_TYPE(0),
|
"UPC-A": _SET_BARCODE_TYPE(0),
|
||||||
"UPC-E": _SET_BARCODE_TYPE(1),
|
"UPC-E": _SET_BARCODE_TYPE(1),
|
||||||
|
@ -216,8 +216,8 @@ BARCODE_TYPE_A = {
|
||||||
"CODABAR": _SET_BARCODE_TYPE(6), # Same as NW7
|
"CODABAR": _SET_BARCODE_TYPE(6), # Same as NW7
|
||||||
}
|
}
|
||||||
|
|
||||||
# Barcodes for printing function type B
|
#: Barcodes for printing function type B
|
||||||
# The first 8 are the same barcodes as type A
|
#: The first 8 are the same barcodes as type A
|
||||||
BARCODE_TYPE_B = {
|
BARCODE_TYPE_B = {
|
||||||
"UPC-A": _SET_BARCODE_TYPE(65),
|
"UPC-A": _SET_BARCODE_TYPE(65),
|
||||||
"UPC-E": _SET_BARCODE_TYPE(66),
|
"UPC-E": _SET_BARCODE_TYPE(66),
|
||||||
|
@ -236,6 +236,7 @@ BARCODE_TYPE_B = {
|
||||||
"GS1 DATABAR EXPANDED": _SET_BARCODE_TYPE(78),
|
"GS1 DATABAR EXPANDED": _SET_BARCODE_TYPE(78),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#: supported barcode formats
|
||||||
BARCODE_FORMATS = {
|
BARCODE_FORMATS = {
|
||||||
"UPC-A": ([(11, 12)], "^[0-9]{11,12}$"),
|
"UPC-A": ([(11, 12)], "^[0-9]{11,12}$"),
|
||||||
"UPC-E": ([(7, 8), (11, 12)], "^([0-9]{7,8}|[0-9]{11,12})$"),
|
"UPC-E": ([(7, 8), (11, 12)], "^([0-9]{7,8}|[0-9]{11,12})$"),
|
||||||
|
|
|
@ -87,6 +87,19 @@ from escpos.image import EscposImage
|
||||||
from escpos.capabilities import get_profile, BARCODE_B
|
from escpos.capabilities import get_profile, BARCODE_B
|
||||||
|
|
||||||
|
|
||||||
|
# Remove special characters and whitespaces of the supported barcode names,
|
||||||
|
# convert to uppercase and map them to their original names.
|
||||||
|
HW_BARCODE_NAMES = {
|
||||||
|
"".join([char for char in name.upper() if char.isalnum()]): name
|
||||||
|
for bc_type in BARCODE_TYPES.values()
|
||||||
|
for name in bc_type
|
||||||
|
}
|
||||||
|
SW_BARCODE_NAMES = {
|
||||||
|
"".join([char for char in name.upper() if char.isalnum()]): name
|
||||||
|
for name in barcode.PROVIDED_BARCODES
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(ABCMeta)
|
@six.add_metaclass(ABCMeta)
|
||||||
class Escpos(object):
|
class Escpos(object):
|
||||||
"""ESC/POS Printer object
|
"""ESC/POS Printer object
|
||||||
|
@ -411,6 +424,24 @@ class Escpos(object):
|
||||||
regex, code
|
regex, code
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _dpi(self) -> int:
|
||||||
|
"""Printer's DPI resolution."""
|
||||||
|
try:
|
||||||
|
dpi = int(self.profile.profile_data["media"]["dpi"])
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
# Calculate the printer's DPI from the width info of the profile.
|
||||||
|
try:
|
||||||
|
px = self.profile.profile_data["media"]["width"]["pixels"]
|
||||||
|
mm = self.profile.profile_data["media"]["width"]["mm"]
|
||||||
|
mm -= 10 # paper width minus margin =~ printable area
|
||||||
|
dpi = int(px / (mm / 25.4))
|
||||||
|
except (KeyError, TypeError, ZeroDivisionError):
|
||||||
|
# Value on error.
|
||||||
|
dpi = 180
|
||||||
|
print(f"No printer's DPI info was found: Defaulting to {dpi}.")
|
||||||
|
self.profile.profile_data["media"]["dpi"] = dpi
|
||||||
|
return dpi
|
||||||
|
|
||||||
def barcode(
|
def barcode(
|
||||||
self,
|
self,
|
||||||
code,
|
code,
|
||||||
|
@ -422,6 +453,128 @@ class Escpos(object):
|
||||||
align_ct=True,
|
align_ct=True,
|
||||||
function_type=None,
|
function_type=None,
|
||||||
check=True,
|
check=True,
|
||||||
|
force_software=False,
|
||||||
|
):
|
||||||
|
"""Print barcode.
|
||||||
|
|
||||||
|
Automatic hardware|software barcode renderer according to the printer capabilities.
|
||||||
|
|
||||||
|
Defaults to hardware barcode and its format types if supported.
|
||||||
|
Automatically switches to software barcode renderer if hardware does not
|
||||||
|
support a barcode type that is supported by software. (e.g. JAN, ISSN, etc.).
|
||||||
|
|
||||||
|
Set force_software=True to force the software renderer according to the profile.
|
||||||
|
Set force_software=graphics|bitImageColumn|bitImageRaster to specify a renderer.
|
||||||
|
|
||||||
|
Ignores caps, special chars and whitespaces in barcode type names.
|
||||||
|
So "EAN13", "ean-13", "Ean_13", "EAN 13" are all accepted.
|
||||||
|
|
||||||
|
:param code: alphanumeric data to be printed as bar code (payload).
|
||||||
|
|
||||||
|
:param bc: barcode format type (EAN13, CODE128, JAN, etc.).
|
||||||
|
|
||||||
|
:param height: barcode module height (in printer dots), has to be between 1 and 255.
|
||||||
|
*default*: 64
|
||||||
|
:type height: int
|
||||||
|
|
||||||
|
:param width: barcode module width (in printer dots), has to be between 2 and 6.
|
||||||
|
*default*: 3
|
||||||
|
:type width: int
|
||||||
|
|
||||||
|
:param pos: text position (ABOVE, BELOW, BOTH, OFF) relative to the barcode
|
||||||
|
(ignored in software renderer).
|
||||||
|
*default*: BELOW
|
||||||
|
|
||||||
|
:param font: select font A or B (ignored in software renderer).
|
||||||
|
*default*: A
|
||||||
|
|
||||||
|
:param align_ct: If *True*, center the barcode.
|
||||||
|
*default*: True
|
||||||
|
:type align_ct: bool
|
||||||
|
|
||||||
|
:param function_type: ESCPOS function type A or B. None to guess it from profile
|
||||||
|
(ignored in software renderer).
|
||||||
|
*default*: None
|
||||||
|
|
||||||
|
:param check: If *True*, checks that the code meets the requirements of the barcode type.
|
||||||
|
*default*: True
|
||||||
|
:type check: bool
|
||||||
|
|
||||||
|
:param force_software: If *True*, force the use of software barcode renderer from profile.
|
||||||
|
If *"graphics", "bitImageColumn" or "bitImageRaster"*, force the use of specific renderer.
|
||||||
|
:type force_software: bool | str
|
||||||
|
|
||||||
|
:raises: :py:exc:`~escpos.exceptions.BarcodeCodeError`,
|
||||||
|
:py:exc:`~escpos.exceptions.BarcodeTypeError`
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Get all supported formats at:
|
||||||
|
- Hardware: :py:const:`~escpos.constants.BARCODE_FORMATS`
|
||||||
|
- Software: `Python barcode documentation <https://python-barcode.readthedocs.io/en/stable/supported-formats.html>`_
|
||||||
|
"""
|
||||||
|
hw_modes = ["barcodeA", "barcodeB"]
|
||||||
|
sw_modes = ["graphics", "bitImageColumn", "bitImageRaster"]
|
||||||
|
capable = {
|
||||||
|
"hw": [mode for mode in hw_modes if self.profile.supports(mode)] or None,
|
||||||
|
"sw": [mode for mode in sw_modes if self.profile.supports(mode)] or None,
|
||||||
|
}
|
||||||
|
if (not capable["hw"] and not capable["sw"]) or (
|
||||||
|
not capable["sw"] and force_software
|
||||||
|
):
|
||||||
|
raise BarcodeTypeError(
|
||||||
|
f"""Profile {
|
||||||
|
self.profile.profile_data['name']
|
||||||
|
} - hw barcode: {capable['hw']}, sw barcode: {capable['sw']}"""
|
||||||
|
)
|
||||||
|
|
||||||
|
bc_alnum = "".join([char for char in bc.upper() if char.isalnum()])
|
||||||
|
capable_bc = {
|
||||||
|
"hw": HW_BARCODE_NAMES.get(bc_alnum),
|
||||||
|
"sw": SW_BARCODE_NAMES.get(bc_alnum),
|
||||||
|
}
|
||||||
|
if not any([*capable_bc.values()]):
|
||||||
|
raise BarcodeTypeError(f"Not supported or wrong barcode name {bc}.")
|
||||||
|
|
||||||
|
if force_software or not capable["hw"] or not capable_bc["hw"]:
|
||||||
|
# Select the best possible capable render mode
|
||||||
|
impl = capable["sw"][0]
|
||||||
|
if force_software in capable["sw"]:
|
||||||
|
# Force to a specific mode
|
||||||
|
impl = force_software
|
||||||
|
print(f"Using {impl} software barcode renderer")
|
||||||
|
# Set barcode type
|
||||||
|
bc = capable_bc["sw"] or bc
|
||||||
|
# Get mm per point of the printer
|
||||||
|
mmxpt = 25.4 / self._dpi()
|
||||||
|
self._sw_barcode(
|
||||||
|
bc,
|
||||||
|
code,
|
||||||
|
impl=impl,
|
||||||
|
module_height=height * mmxpt,
|
||||||
|
module_width=width * mmxpt,
|
||||||
|
text_distance=3, # TODO: _hw_barcode() size equivalence
|
||||||
|
font_size=9, # TODO: _hw_barcode() size equivalence
|
||||||
|
center=align_ct,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Using hardware barcode renderer")
|
||||||
|
bc = capable_bc["hw"] or bc
|
||||||
|
self._hw_barcode(
|
||||||
|
code, bc, height, width, pos, font, align_ct, function_type, check
|
||||||
|
)
|
||||||
|
|
||||||
|
def _hw_barcode(
|
||||||
|
self,
|
||||||
|
code,
|
||||||
|
bc,
|
||||||
|
height=64,
|
||||||
|
width=3,
|
||||||
|
pos="BELOW",
|
||||||
|
font="A",
|
||||||
|
align_ct=True,
|
||||||
|
function_type=None,
|
||||||
|
check=True,
|
||||||
):
|
):
|
||||||
"""Print Barcode
|
"""Print Barcode
|
||||||
|
|
||||||
|
@ -444,9 +597,6 @@ class Escpos(object):
|
||||||
automatic centering. Please note that when you use center alignment, then the alignment of text will be changed
|
automatic centering. Please note that when you use center alignment, then the alignment of text will be changed
|
||||||
automatically to centered. You have to manually restore the alignment if necessary.
|
automatically to centered. You have to manually restore the alignment if necessary.
|
||||||
|
|
||||||
.. todo:: If further barcode-types are needed they could be rendered transparently as an image. (This could also
|
|
||||||
be of help if the printer does not support types that others do.)
|
|
||||||
|
|
||||||
:param code: alphanumeric data to be printed as bar code
|
:param code: alphanumeric data to be printed as bar code
|
||||||
:param bc: barcode format, possible values are for type A are:
|
:param bc: barcode format, possible values are for type A are:
|
||||||
|
|
||||||
|
@ -506,27 +656,12 @@ class Escpos(object):
|
||||||
:py:exc:`~escpos.exceptions.BarcodeTypeError`,
|
:py:exc:`~escpos.exceptions.BarcodeTypeError`,
|
||||||
:py:exc:`~escpos.exceptions.BarcodeCodeError`
|
:py:exc:`~escpos.exceptions.BarcodeCodeError`
|
||||||
"""
|
"""
|
||||||
if function_type is None:
|
# If function_type is specified, otherwise use guessing.
|
||||||
# Choose the function type automatically.
|
ft_guess = [ft for ft in ["A", "B"] if bc in BARCODE_TYPES.get(ft)]
|
||||||
if bc in BARCODE_TYPES["A"]:
|
ft_guess = ft_guess or [None]
|
||||||
function_type = "A"
|
function_type = function_type or ft_guess[0]
|
||||||
else:
|
|
||||||
if bc in BARCODE_TYPES["B"]:
|
|
||||||
if not self.profile.supports(BARCODE_B):
|
|
||||||
raise BarcodeTypeError(
|
|
||||||
(
|
|
||||||
"Barcode type '{bc} not supported for "
|
|
||||||
"the current printer profile"
|
|
||||||
).format(bc=bc)
|
|
||||||
)
|
|
||||||
function_type = "B"
|
|
||||||
else:
|
|
||||||
raise BarcodeTypeError(
|
|
||||||
("Barcode type '{bc} is not valid").format(bc=bc)
|
|
||||||
)
|
|
||||||
|
|
||||||
bc_types = BARCODE_TYPES[function_type.upper()]
|
if not function_type or not BARCODE_TYPES.get(function_type.upper()):
|
||||||
if bc.upper() not in bc_types.keys():
|
|
||||||
raise BarcodeTypeError(
|
raise BarcodeTypeError(
|
||||||
(
|
(
|
||||||
"Barcode '{bc}' not valid for barcode function type "
|
"Barcode '{bc}' not valid for barcode function type "
|
||||||
|
@ -536,6 +671,7 @@ class Escpos(object):
|
||||||
function_type=function_type,
|
function_type=function_type,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
bc_types = BARCODE_TYPES[function_type.upper()]
|
||||||
|
|
||||||
if check and not self.check_barcode(bc, code):
|
if check and not self.check_barcode(bc, code):
|
||||||
raise BarcodeCodeError(
|
raise BarcodeCodeError(
|
||||||
|
@ -587,16 +723,71 @@ class Escpos(object):
|
||||||
if function_type.upper() == "A":
|
if function_type.upper() == "A":
|
||||||
self._raw(NUL)
|
self._raw(NUL)
|
||||||
|
|
||||||
def soft_barcode(
|
def _sw_barcode(
|
||||||
self,
|
self,
|
||||||
barcode_type,
|
barcode_type,
|
||||||
data,
|
data,
|
||||||
impl="bitImageColumn",
|
impl="bitImageColumn",
|
||||||
module_height=5,
|
module_height=5,
|
||||||
module_width=0.2,
|
module_width=0.2,
|
||||||
text_distance=1,
|
text_distance=5,
|
||||||
|
font_size=10,
|
||||||
center=True,
|
center=True,
|
||||||
):
|
):
|
||||||
|
"""Print Barcode
|
||||||
|
|
||||||
|
This method allows to print barcodes. The rendering of the barcode is done by
|
||||||
|
the `barcode` library and sent to the printer as image through one of the
|
||||||
|
printer's supported implementations: graphics, bitImageColumn or bitImageRaster.
|
||||||
|
|
||||||
|
:param barcode_type: barcode format, possible values are:
|
||||||
|
* ean8
|
||||||
|
* ean8-guard
|
||||||
|
* ean13
|
||||||
|
* ean13-guard
|
||||||
|
* ean
|
||||||
|
* gtin
|
||||||
|
* ean14
|
||||||
|
* jan
|
||||||
|
* upc
|
||||||
|
* upca
|
||||||
|
* isbn
|
||||||
|
* isbn13
|
||||||
|
* gs1
|
||||||
|
* isbn10
|
||||||
|
* issn
|
||||||
|
* code39
|
||||||
|
* pzn
|
||||||
|
* code128
|
||||||
|
* itf
|
||||||
|
* gs1_128
|
||||||
|
* codabar
|
||||||
|
* nw-7
|
||||||
|
:type data: str
|
||||||
|
|
||||||
|
:param data: alphanumeric data to be printed as bar code (payload).
|
||||||
|
:type data: str
|
||||||
|
|
||||||
|
:param impl: image printing mode:
|
||||||
|
* graphics
|
||||||
|
* bitImageColumn
|
||||||
|
* bitImageRaster
|
||||||
|
|
||||||
|
:param module_height: barcode module height (in mm).
|
||||||
|
:type module_height: int | float
|
||||||
|
|
||||||
|
:param module_width: barcode module width (in mm).
|
||||||
|
:type module_width: int | float
|
||||||
|
|
||||||
|
:param text_distance: distance from the barcode to the code text (in mm).
|
||||||
|
:type text_distance: int | float
|
||||||
|
|
||||||
|
:param font_size: font size of the code text (in dots).
|
||||||
|
:type font_size: int
|
||||||
|
|
||||||
|
:param center: center the barcode.
|
||||||
|
:type center: bool
|
||||||
|
"""
|
||||||
image_writer = ImageWriter()
|
image_writer = ImageWriter()
|
||||||
|
|
||||||
# Check if barcode type exists
|
# Check if barcode type exists
|
||||||
|
@ -610,11 +801,15 @@ class Escpos(object):
|
||||||
# Render the barcode
|
# Render the barcode
|
||||||
barcode_class = barcode.get_barcode_class(barcode_type)
|
barcode_class = barcode.get_barcode_class(barcode_type)
|
||||||
my_code = barcode_class(data, writer=image_writer)
|
my_code = barcode_class(data, writer=image_writer)
|
||||||
|
|
||||||
my_code.render(
|
my_code.render(
|
||||||
writer_options={
|
writer_options={
|
||||||
"module_height": module_height,
|
"module_height": module_height,
|
||||||
"module_width": module_width,
|
"module_width": module_width,
|
||||||
|
"quiet_zone": 0, # horizontal padding
|
||||||
"text_distance": text_distance,
|
"text_distance": text_distance,
|
||||||
|
"font_size": font_size,
|
||||||
|
"dpi": self._dpi(), # Image dpi has to match the printer's dpi
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,13 @@ def instance():
|
||||||
def test_soft_barcode_ean8_invalid(instance):
|
def test_soft_barcode_ean8_invalid(instance):
|
||||||
"""test with an invalid barcode"""
|
"""test with an invalid barcode"""
|
||||||
with pytest.raises(barcode.errors.BarcodeError):
|
with pytest.raises(barcode.errors.BarcodeError):
|
||||||
instance.soft_barcode("ean8", "1234")
|
instance.barcode("1234", "ean8", force_software=True)
|
||||||
|
|
||||||
|
|
||||||
def test_soft_barcode_ean8(instance):
|
def test_soft_barcode_ean8(instance):
|
||||||
"""test with a valid ean8 barcode"""
|
"""test with a valid ean8 barcode"""
|
||||||
instance.soft_barcode("ean8", "1234567")
|
instance.barcode("1234567", "ean8", force_software=True)
|
||||||
|
|
||||||
|
|
||||||
def test_soft_barcode_ean8_nocenter(instance):
|
def test_soft_barcode_ean8_nocenter(instance):
|
||||||
instance.soft_barcode("ean8", "1234567", center=False)
|
instance.barcode("1234567", "ean8", align_ct=False, force_software=True)
|
||||||
|
|
Loading…
Reference in New Issue