36 Commits
Author SHA1 Message Date
Dominic Radermacher 02be73c75b update translations 2026-09-25 09:56:10 +02:00
James A 7fa1e1ac46 add --serial and --list-connected to pick one of several printers
When more than one printer is connected, ptouch-print used the first
one it found. --serial <serial> now uses only the printer with that USB
serial number, and --list-connected lists the connected printers with
their serials.

libptouch gets ptouch_open_serial() and ptouch_list_connected();
ptouch_open() keeps its signature and calls ptouch_open_serial() with
NULL. The serial is checked before the P-Lite and unsupported-raster
checks, so a different printer in the wrong mode no longer ends the
search, and the "found on USB bus" line now shows the serial. The early
error returns in the open loop now free the device list.
2026-09-25 09:51:25 +02:00
James A d05d31bb86 copy min_timeout into devinfo in ptouch_open()
devinfo is malloc'd and min_timeout was never set, so the status
timeout was whatever happened to be in memory (seen as
"timeout (1086334400 sec) while waiting for status response").
2026-09-25 09:50:43 +02:00
Dominic Radermacher 434df678d2 fix compile warnings about missing field initializers in struct _pt_dev_info 2026-09-12 16:19:43 +02:00
Dominic Radermacher 54e046f190 Enable FLAG_HAS_PRECUT for PT-2430PC
The PT-2430PC (0x04f9:0x202d) was flagged FLAG_NONE, so --precut was
silently a no-op on this model: printing a --chain'd batch of labels
produced one continuous strip with no cut between individual labels.

This printer shares the same head width and DPI (128px @ 180dpi) as
the PT-2700 (0x04f9:0x201f), which already has FLAG_HAS_PRECUT set.
That similarity prompted testing precut on real PT-2430PC hardware:
sending --chain on the first label and --precut on the second
produces a real cut between the two labels, with no errors and no
adverse effect on the surrounding print.

Tested on: PT-2430PC, USB ID 04f9:202d, tape: 12mm laminated.

Only the non-PLite entry is changed; the "(PLite Mode)" variant
(0x04f9:0x2031) was not tested and is left as FLAG_PLITE.
2026-09-12 16:12:38 +02:00
Kevin Bradenstein 41c4af0d0d allow a printer to raise the default status timeout
The PT-E560BT stays busy about 2.2 s after even an 8 mm label, so the
1 second default timeout cannot succeed on a job sent straight after
another: printing five chained labels gives a strip carrying three of
them. ptouch-print reports the timeout and exits non-zero correctly every
time, but no amount of waiting helps when the default is below the
printer's fixed overhead.

Add a trailing min_timeout to the device table. Every other row keeps its
initialiser and gets 0, which resolves to the old default of 1; only the
E560BT carries a value. An explicit --timeout always wins.

Raising the global default would also be defensible: ptouch_getstatus()
returns as soon as the status arrives, measured 0.13 s with --timeout 30
against 0.14 s with --timeout 1, so a higher ceiling costs nothing on a
printer that is ready. But that is a judgement about printers I do not
have, so this keeps it to the one that was measured.
2026-09-08 07:19:13 +02:00
Kevin Bradenstein ef6e6f4925 cmake: let the argp probe pass where argp-standalone needs strchrnul
On macOS with Homebrew's argp-standalone, Findargp's link test for
argp_parse fails with an undefined strchrnul, because libargp.a itself
references that GNU extension and the platform has none. The module then
stops with "does not have a symbol named argp_parse", which is not what
is wrong.

Probe for strchrnul first (with _GNU_SOURCE, so glibc answers correctly).
Where it exists, the test is unchanged. Where it is missing, run the same
argp_parse test with a local definition of strchrnul, and have ptouch-print
supply that definition for the real build.

On glibc nothing changes: the probe finds strchrnul and the original test
runs. Checked on Debian stable in the same session.
2026-09-08 07:16:31 +02:00
Kevin Bradenstein 97a9576c6e cmake: link libusb by its full path
pkg_check_modules gives both LIBUSB_LIBRARIES (bare names, -lusb-1.0) and
LIBUSB_LINK_LIBRARIES (absolute paths). Passing both links libusb twice,
and the bare name only resolves when libusb is in the default library
search path - which it is on Linux and is not under Homebrew on macOS,
where the link fails with "library not found for -lusb-1.0". The full
path alone is enough everywhere.
2026-09-08 07:16:25 +02:00
Guido Steinhauer 15ea891fad add PT-9700PC support 2026-09-01 10:30:48 +02:00
Dominic Radermacher f7cce68609 fix compile warnings about missing field initializer 2026-07-18 08:07:42 +02:00
Tobias Klausmann 921206cd5f print_img: correct off-center print area via per-device pin_offset
On the PT-P900W the print area is not centered on the 560-pin printhead:
its center sits at pin 272 rather than the head center (pin 280), a fixed
8-pin offset that is constant across all tape widths. Centering the raster
data on the head therefore prints ~0.5mm off-center (measured as a constant
~1mm margin delta across 12/18/36mm tapes, confirmed against the spec).

Add a pin_offset field to _pt_dev_info (0 = centered, the default for all
existing printers) and apply it in print_img. Set it to -8 for the
PT-P900Wc, which reproduces the spec left-margin exactly for every tape
width ((560-print_area)/2 - 8 = documented left margin).

Reference: Brother "Software Developer's Manual - Raster Command Reference,
PT-P900/P900W/P950NW", section 2.3.5 "Raster line" (per-tape left/right
margin and print-area pin counts for the 560-pin head).
https://download.brother.com/welcome/docp100407/cv_ptp900_eng_raster_102.pdf
2026-07-18 08:01:24 +02:00
Tobias Klausmann 9af6276135 add support for PT-P900Wc (04f9:2085, 360dpi, 36mm)
Add the PT-P900Wc with a 560px printhead and 360dpi resolution, using the
P700 init sequence, PackBits raster, the print-information command and
precut support. Verified printing on 36mm laminated tape.

The existing 360dpi handling doubled the 180dpi tape widths, which is wrong
for wide tapes: the 180dpi values are clamped by those printers' 128-pin
printheads, not the true printable area. Add a separate px360 column with
Brother's documented print areas (36mm = 454px, confirmed on hardware; the
narrower widths are from the raster reference and untested) and clamp the
result to max_px so 360dpi printers with a narrower head (PT-9200DX) stay
safe.

Also add the udev uaccess rule for 2085.
2026-07-18 07:56:55 +02:00
Tobias Klausmann c8ce56e054 libptouch: fix stack buffer overflow in ptouch_sendraster
The raster packet buffer was fixed at 64 bytes, but a full raster line is
max_px/8 bytes plus up to 4 header bytes. For printers with a printhead
wider than 480px this overflows the buffer and smashes the stack. No
previously supported printer was wide enough to trigger it (the widest,
PT-9200DX at 384px, needs 52 bytes), but a 560px printhead needs 74.

Size the buffer to 128 bytes, which is the maximum a single packet can be
since ptouch_send() caps transfers at 128 bytes.
2026-07-18 07:52:44 +02:00
Dominic Radermacher 5cf946bf43 add udev rules for some missing printers 2026-04-20 07:30:44 +02:00
Dominic Radermacher 57084a30e6 improve support for 360dpi printers (untested) 2026-03-09 08:01:30 +01:00
Dominic Radermacher 9cd8a5bc22 preparing for support of printers with 360 dpi 2026-03-08 10:26:46 +01:00
Pascal de Bruijn 25e7a8c876 write_png: show physical output size 2026-03-08 09:30:59 +01:00
Pascal de Bruijn cb76f2ae75 set output PNG resolution to 180 2026-03-08 09:29:16 +01:00
Pascal de Bruijn 245aa4aad0 add fontmargin to manual page 2026-03-08 09:28:09 +01:00
Pascal de Bruijn 0db6ba4477 add missing break introduced in c489e026971d00f5616a4f3c87c10dfb40b7d2b9 2026-03-08 09:27:41 +01:00
Pascal de Bruijn 5e5e833bcd gdImageStringFT_180dpi wrapper 2026-03-08 09:26:49 +01:00
Pascal de Bruijn c08a456bfd find_fontsize: always account for common ascenders and descenders 2026-03-08 09:25:30 +01:00
Pascal de Bruijn 2d4ffd6112 implement font margin 2026-03-08 09:24:14 +01:00
Pascal de Bruijn 118afc7694 get_baselineoffset: rounded letters are usually not on the baseline 2026-03-08 09:22:40 +01:00
Dominic Radermacher 76c419f952 Add support for using \n for new line (thanks to github.com/probonopd/) 2026-03-06 08:20:32 +01:00
Dominic Radermacher bdd724fef5 added PT-9200DX with different entry (thanks to Christian Pauls) 2026-02-27 07:50:15 +01:00
Dominic Radermacher 3e026ef26b fix strange output when calling ptouch-print --help multiple times 2026-01-23 08:12:51 +01:00
Ed Maste 5cbc680f63 Use CMake-argp to find agrp include and library paths
On at least FreeBSD argp is a separate library that needs to have its
path specified in order to link.
2025-12-15 07:15:21 +01:00
Ed Maste 7ef61111bc Import CMake-argp
From https://github.com/alehaa/CMake-argp at commit 5523dc6b7de7.
2025-12-15 07:15:10 +01:00
Dominic Radermacher fd526f9dbe add param --align for aligning multi-line text centered or right-aligned 2025-12-08 15:33:06 +01:00
Jonas Konrad d2a3bac46e Add command line flag for toggling precut For devices that support cutting before the current label ("precut"), change the default to no precut and add a command line flag to turn it on.
Odd behavior in testing with my PT-H500: When printing with precut, and then printing the next label without precut, the next label still gets a precut. i.e. the label with the precut flag gets cut on both ends, even if the next label does not have this flag. The label after that works as expected.

I'm unsure if this is printer behavior or if it could be resolved by sending additional commands somehow (maybe resetting the flag).
2025-12-01 20:35:45 +01:00
Jonas Konrad c2b607be7c Enable pre-cut for PT-H500 2025-12-01 19:38:37 +01:00
Michael Richter 7509ef765c Add support for HSe-251E (heatshrink-tube) tapes 2025-12-01 19:35:59 +01:00
Dominic Radermacher b3ab878bfb updated translation files 2025-11-02 12:56:16 +01:00
Dominic Radermacher a27a320672 add PT-E560BT (thanks to Paul-Kenji Cahier) 2025-10-31 08:04:08 +01:00
Markus Schramma d8a4ed71e2 add --timeout option 2025-09-28 08:05:41 +02:00
10 changed files with 1018 additions and 336 deletions
+8 -1
View File
@@ -14,6 +14,12 @@ find_package(GD REQUIRED)
find_package(Git REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(Intl REQUIRED)
find_package(argp REQUIRED)
if(NOT ARGP_IN_LIBC AND NOT HAVE_STRCHRNUL)
# See cmake/Findargp.cmake: argp-standalone needs a strchrnul() the
# platform does not have, so ptouch-print.c defines one.
add_compile_definitions(NEED_STRCHRNUL=1)
endif()
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
@@ -26,13 +32,14 @@ target_include_directories(${PROJECT_NAME} PUBLIC
${GD_INCLUDE_DIR}
${LIBUSB_INCLUDE_DIRS}
${Intl_INCLUDE_DIRS}
${ARGP_INCLUDE_DIR}
)
target_link_libraries(${PROJECT_NAME} PRIVATE
${GD_LIBRARIES}
${LIBUSB_LIBRARIES}
${LIBUSB_LINK_LIBRARIES}
${Intl_LIBRARIES}
${ARGP_LIBRARIES}
)
target_sources(${PROJECT_NAME} PRIVATE
+110
View File
@@ -0,0 +1,110 @@
# This file is part of CMake-argp.
#
# CMake-argp is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 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 Lesser General Public License along
# with this program. If not, see
#
# http://www.gnu.org/licenses/
#
#
# Copyright (c)
# 2016-2017 Alexander Haase <ahaase@alexhaase.de>
#
include(CheckFunctionExists)
include(FindPackageHandleStandardArgs)
include(FindPackageMessage)
# Do the following checks for header, library and argp functions quietly. Only
# print the result at the end of this file.
set(CMAKE_REQUIRED_QUIET TRUE)
# First check if argp is shipped together with libc without linking to any other
# library or including any paths. In that case, no files for argp need to be
# searched and argp may be used out-of-the-box.
check_function_exists("argp_parse" ARGP_IN_LIBC)
if (ARGP_IN_LIBC)
# Set the argp library- and include-paths to empty values, otherwise CMake
# might print warnings about unknown variables and fills them with
# 'xy-NOTFOUND'.
set(ARGP_FOUND TRUE)
set(ARGP_LIBRARIES "")
set(ARGP_INCLUDE_PATH "")
# Print a message, that argp has been successfully found and return from
# this module, as argp doesn't need to be searched as a separate library.
find_package_message(argp "Found argp: built-in" "built-in")
return()
endif()
# Argp is not part of the libc, so it needs to be searched as a separate library
# with its own include directory.
#
# First search the argp header file. If it is not found, any further steps will
# fail.
find_path(ARGP_INCLUDE_PATH "argp.h")
if (ARGP_INCLUDE_PATH)
# Try to find the argp library and check if it has the required argp_parse
# function.
set(CMAKE_REQUIRED_INCLUDES "${ARGP_INCLUDE_PATH}")
find_library(ARGP_LIBRARIES "argp")
# Check if argp_parse is available. Some implementations don't have this
# symbol defined, thus they're not compatible.
#
# argp-standalone itself calls strchrnul(), a GNU extension that the
# platforms needing argp-standalone tend to lack (macOS among them). On
# those the plain link test fails with an undefined strchrnul and would
# report a perfectly good libargp as lacking argp_parse. So probe for
# strchrnul first and, where it is missing, run the argp_parse test with
# a local definition; the project then supplies the same definition.
if (ARGP_LIBRARIES)
set(CMAKE_REQUIRED_LIBRARIES "${ARGP_LIBRARIES}")
include(CheckSymbolExists)
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
check_symbol_exists("strchrnul" "string.h" HAVE_STRCHRNUL)
unset(CMAKE_REQUIRED_DEFINITIONS)
if (HAVE_STRCHRNUL)
check_function_exists("argp_parse" ARGP_EXTERNAL)
else ()
include(CheckCSourceCompiles)
check_c_source_compiles("
#include <string.h>
#include <argp.h>
char *strchrnul(const char *s, int c) {
const char *p = strchr(s, c);
return (char *)(p ? p : s + strlen(s));
}
int main(void) { return argp_parse(0, 1, (char *[]){\"x\"}, 0, 0, 0); }
" ARGP_EXTERNAL)
endif ()
if (NOT ARGP_EXTERNAL)
message(FATAL_ERROR "Your system ships an argp library in "
"${ARGP_LIBRARIES}, but it does not have a symbol "
"named argp_parse.")
endif ()
endif ()
endif ()
# Restore the quiet settings. By default the last check should be printed if not
# disabled in the find_package call.
set(CMAKE_REQUIRED_QUIET ${argp_FIND_QUIETLY})
# Check for all required variables.
find_package_handle_standard_args(argp
DEFAULT_MSG
ARGP_LIBRARIES ARGP_INCLUDE_PATH)
mark_as_advanced(ARGP_LIBRARIES ARGP_INCLUDE_PATH)
+18 -3
View File
@@ -1,7 +1,7 @@
/*
ptouch-print - Print labels with images or text on a Brother P-Touch
Copyright (C) 2015-2023 Dominic Radermacher <dominic@familie-radermacher.ch>
Copyright (C) 2015-2026 Dominic Radermacher <dominic@familie-radermacher.ch>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3 as
@@ -26,7 +26,8 @@
struct _pt_tape_info {
uint8_t mm; /* Tape width in mm */
uint16_t px; /* Printing area in px */
uint16_t px; /* Printing area in px at 180 dpi */
uint16_t px360; /* Printing area in px at 360 dpi */
double margins; /* default tape margins in mm */
};
@@ -56,6 +57,15 @@ struct _pt_dev_info {
int dpi; /* Dots per inch of the printhead */
//size_t bytes_per_line;
int flags;
/* Pins to shift the print area from the centre of the printhead.
On some models the print area is not centred on the head; see the
Brother "Software Developer's Manual - Raster Command Reference,
PT-P900/P900W/P950NW", section 2.3.5 "Raster line". 0 = centred. */
int pin_offset;
/* Seconds to wait for a status response when the user did not ask for a
particular --timeout. 0 means use the global default; a printer only
needs an entry here if the global default is too short for it. */
int min_timeout;
};
typedef struct _pt_dev_info *pt_dev_info;
@@ -97,16 +107,20 @@ struct _ptouch_dev {
typedef struct _ptouch_dev *ptouch_dev;
int ptouch_open(ptouch_dev *ptdev);
int ptouch_open_serial(ptouch_dev *ptdev, const char *serial);
int ptouch_close(ptouch_dev ptdev);
int ptouch_send(ptouch_dev ptdev, uint8_t *data, size_t len);
int ptouch_init(ptouch_dev ptdev);
int ptouch_lf(ptouch_dev ptdev);
int ptouch_ff(ptouch_dev ptdev);
int ptouch_get_dpi(ptouch_dev ptdev);
int ptouch_calc_tape_px(ptouch_dev ptdev, const uint8_t tape_with_mm);
size_t ptouch_get_max_width(ptouch_dev ptdev);
size_t ptouch_get_tape_width(ptouch_dev ptdev);
int ptouch_get_max_lines(ptouch_dev ptdev, int fontsize_px);
int ptouch_page_flags(ptouch_dev ptdev, uint8_t page_flags);
int ptouch_finalize(ptouch_dev ptdev, int chain);
int ptouch_getstatus(ptouch_dev ptdev);
int ptouch_getstatus(ptouch_dev ptdev, int timeout);
int ptouch_getmaxwidth(ptouch_dev ptdev);
int ptouch_send_d460bt_magic(ptouch_dev ptdev);
int ptouch_send_d460bt_chain(ptouch_dev ptdev);
@@ -117,6 +131,7 @@ int ptouch_rasterstart(ptouch_dev ptdev);
int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, size_t len);
void ptouch_rawstatus(uint8_t raw[32]);
void ptouch_list_supported();
int ptouch_list_connected();
const char* pt_mediatype(unsigned char media_type);
const char* pt_tapecolor(unsigned char tape_color);
+134 -72
View File
@@ -6,9 +6,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: ptouch-print 1.3.1\n"
"Project-Id-Version: ptouch-print 1.7\n"
"Report-Msgid-Bugs-To: dominic@familie-radermacher.ch\n"
"POT-Creation-Date: 2025-08-11 09:57+0200\n"
"POT-Creation-Date: 2026-09-25 09:51+0200\n"
"PO-Revision-Date: 2024-05-23 22:27-0400\n"
"Last-Translator: dominic@familie-radermacher.ch\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@@ -19,289 +19,351 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.2\n"
#: src/libptouch.c:105 src/libptouch.c:109 src/libptouch.c:113
#: src/libptouch.c:131 src/libptouch.c:135 src/libptouch.c:139
#, c-format
msgid "out of memory\n"
msgstr "Nicht genug Speicher\n"
#: src/libptouch.c:117
#: src/libptouch.c:143 src/libptouch.c:602
#, c-format
msgid "libusb_init() failed\n"
msgstr "ptouch_init() fehlgeschlagen\n"
#: src/libptouch.c:126
#: src/libptouch.c:152
#, c-format
msgid "failed to get device descriptor"
msgstr ""
#: src/libptouch.c:132
#, c-format
msgid "%s found on USB bus %d, device %d\n"
msgstr "Drucker %s am USB Bus %d, Gerät %d gefunden\n"
#: src/libptouch.c:147
#: src/libptouch.c:160
#, c-format
msgid "libusb_open error :%s\n"
msgstr ""
#: src/libptouch.c:153
#: src/libptouch.c:171
#, fuzzy, c-format
msgid "%s found on USB bus %d, device %d, serial %s\n"
msgstr "Drucker %s am USB Bus %d, Gerät %d gefunden\n"
#: src/libptouch.c:200
#, c-format
msgid "error while detaching kernel driver: %s\n"
msgstr ""
#: src/libptouch.c:157
#: src/libptouch.c:204
#, c-format
msgid "interface claim error: %s\n"
msgstr ""
#: src/libptouch.c:168
#: src/libptouch.c:218
#, c-format
msgid "No P-Touch printer with serial %s found\n"
msgstr ""
#: src/libptouch.c:220 src/ptouch-print.c:722
#, c-format
msgid ""
"No P-Touch printer found on USB (remember to put switch to position E)\n"
msgstr "Kein P-Ptouch Drucker am USB gefunden (Schalter muss auf E stehen)\n"
#: src/libptouch.c:188
#: src/libptouch.c:241
#, c-format
msgid "debug: called ptouch_send() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:195
#: src/libptouch.c:248
#, c-format
msgid "write error: %s\n"
msgstr ""
#: src/libptouch.c:199
#: src/libptouch.c:252
#, fuzzy, c-format
msgid "write error: could send only %i of %ld bytes\n"
msgstr "Lesefehler: %i anstatt 32 bytes empfangen\n"
#: src/libptouch.c:249
#: src/libptouch.c:302
#, c-format
msgid "debug: called ptouch_info_cmd() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:291
#: src/libptouch.c:344
#, fuzzy, c-format
msgid "debug: called ptouch_rasterstart() with NULL ptdev\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/libptouch.c:322
#: src/libptouch.c:384
#, c-format
msgid "debug: called ptouch_finalize() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:337
#: src/libptouch.c:399
#, c-format
msgid "debug: dumping raw status bytes\n"
msgstr ""
#: src/libptouch.c:356
#: src/libptouch.c:418
#, c-format
msgid "debug: called ptouch_getstatus() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:366 src/libptouch.c:402
#: src/libptouch.c:428 src/libptouch.c:459
#, c-format
msgid "read error: %s\n"
msgstr ""
#: src/libptouch.c:371
#: src/libptouch.c:433
#, c-format
msgid "timeout while waiting for status response\n"
msgid "timeout (%i sec) while waiting for status response\n"
msgstr ""
#: src/libptouch.c:385
#: src/libptouch.c:442
#, c-format
msgid "unknown tape width of %imm, please report this.\n"
msgstr "Unbekannte Schriftband breite (%i mm), bitte melden\n"
#: src/libptouch.c:391
#: src/libptouch.c:448
#, c-format
msgid "got only 16 bytes... wondering what they are:\n"
msgstr "nur 16 bytes empfangen... mal gucken was die sind:\n"
#: src/libptouch.c:395
#: src/libptouch.c:452
#, c-format
msgid "read error: got %i instead of 32 bytes\n"
msgstr "Lesefehler: %i anstatt 32 bytes empfangen\n"
#: src/libptouch.c:398
#: src/libptouch.c:455
#, c-format
msgid "strange status:\n"
msgstr "Seltsamer Status:\n"
#: src/libptouch.c:400
#: src/libptouch.c:457
#, c-format
msgid "trying to flush junk\n"
msgstr ""
#: src/libptouch.c:405
#: src/libptouch.c:462
#, c-format
msgid "got another %i bytes. now try again\n"
msgstr "weitere %i bytes empfangen. probiere es nochmal.\n"
#: src/libptouch.c:412
#: src/libptouch.c:469
#, fuzzy, c-format
msgid "debug: called ptouch_get_dpi() with NULL ptdev\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/libptouch.c:478
#, fuzzy, c-format
msgid "debug: called ptouch_cal_tape_width() with NULL ptdev\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/libptouch.c:489
#, c-format
msgid "printer with %d dpi not supported\n"
msgstr ""
#: src/libptouch.c:509
#, fuzzy, c-format
msgid "debug: called ptouch_get_max_lines() with NULL ptdev\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/libptouch.c:513
#, fuzzy, c-format
msgid "debug: called ptouch_get_max_lines() with invalid fontsize_px\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/libptouch.c:516
#, c-format
msgid "debug: calculated max lines %d \n"
msgstr ""
#: src/libptouch.c:523
#, c-format
msgid "debug: called ptouch_get_tape_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:421
#: src/libptouch.c:532
#, c-format
msgid "debug: called ptouch_get_max_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:433
#: src/libptouch.c:547
#, c-format
msgid "debug: called ptouch_sendraster() with NULL ptdev\n"
msgstr ""
#: src/ptouch-print.c:143
#: src/libptouch.c:625
#, fuzzy, c-format
msgid "%s\tserial %s\t(USB bus %d, device %d)%s\n"
msgstr "Drucker %s am USB Bus %d, Gerät %d gefunden\n"
#: src/libptouch.c:629
msgid " - in P-Lite mode, unsupported"
msgstr ""
#: src/libptouch.c:630
msgid " - unsupported"
msgstr ""
#: src/ptouch-print.c:190
#, c-format
msgid "nothing to print\n"
msgstr ""
#: src/ptouch-print.c:151
#: src/ptouch-print.c:198
#, c-format
msgid "image is too large (%ipx x %ipx)\n"
msgstr "Bild ist zu gross (%ipx x %ipx)\n"
#: src/ptouch-print.c:152
#: src/ptouch-print.c:199
#, c-format
msgid "maximum printing width for this tape is %ipx\n"
msgstr "Maximal druckbare Breite für dieses Schriftband sind %ipx\n"
#: src/ptouch-print.c:155
#: src/ptouch-print.c:202
#, fuzzy, c-format
msgid "image size (%ipx x %ipx)\n"
msgstr "Bild ist zu gross (%ipx x %ipx)\n"
#: src/ptouch-print.c:165
#: src/ptouch-print.c:218
#, c-format
msgid "ptouch_rasterstart() failed\n"
msgstr "ptouch_rasterstart() fehlgeschlagen\n"
#: src/ptouch-print.c:171
#: src/ptouch-print.c:224
#, c-format
msgid "send print information command\n"
msgstr ""
#: src/ptouch-print.c:177
#: src/ptouch-print.c:230
#, c-format
msgid "send PT-D460BT magic commands\n"
msgstr ""
#: src/ptouch-print.c:183
#: src/ptouch-print.c:237
#, c-format
msgid "send precut command\n"
msgstr ""
#: src/ptouch-print.c:191
#: src/ptouch-print.c:246
#, c-format
msgid "send PT-D460BT chain commands\n"
msgstr ""
#: src/ptouch-print.c:203
#: src/ptouch-print.c:258
#, fuzzy, c-format
msgid "ptouch_sendraster() failed\n"
msgstr "ptouch_send() fehlgeschlagen\n"
#: src/ptouch-print.c:252
#: src/ptouch-print.c:307
#, c-format
msgid "writing image '%s' failed\n"
msgstr "Schreiben der Bilddatei '%s' fehlgeschlagen\n"
#: src/ptouch-print.c:274
#: src/ptouch-print.c:312
#, c-format
msgid "debug: o baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:275
#, c-format
msgid "debug: text baseline offset - %d\n"
msgid "printing '%s' requires %.1f mm of tape\n"
msgstr ""
#: src/ptouch-print.c:334
#, c-format
msgid "render_text(): %i lines, font = '%s'\n"
msgid "debug: z baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:337
#: src/ptouch-print.c:335
#, c-format
msgid "debug: text baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:408
#, c-format
msgid "render_text(): %i lines, font = '%s', align = '%c'\n"
msgstr ""
#: src/ptouch-print.c:411
#, c-format
msgid "warning: font config not available\n"
msgstr "Warnung: fontconfig ist nicht verfügbar\n"
#: src/ptouch-print.c:341
#: src/ptouch-print.c:415
#, c-format
msgid "setting font size=%i\n"
msgstr "setze Zeichensatzgrösse=%i\n"
#: src/ptouch-print.c:345
#: src/ptouch-print.c:417
#, fuzzy, c-format
msgid "ignoring setting font margin=%i\n"
msgstr "setze Zeichensatzgrösse=%i\n"
#: src/ptouch-print.c:422
#, c-format
msgid "could not estimate needed font size\n"
msgstr "Konnte die notwendige Zeichensatzgrösse nicht bestimmen\n"
#: src/ptouch-print.c:352
#: src/ptouch-print.c:429
#, c-format
msgid "choosing font size=%i\n"
msgstr "Wähle Zeichensatzgrösse %i\n"
#: src/ptouch-print.c:368 src/ptouch-print.c:396
#, c-format
msgid "error in gdImageStringFT: %s\n"
#: src/ptouch-print.c:445 src/ptouch-print.c:479
#, fuzzy, c-format
msgid "error in gdImageStringFT_180dpi: %s\n"
msgstr "Fehler in Funktion gdImageStringFT(): %s\n"
#: src/ptouch-print.c:557
#: src/ptouch-print.c:636
#, c-format
msgid "Only up to %d lines are supported"
msgstr ""
#: src/ptouch-print.c:570
#: src/ptouch-print.c:727
msgid "No arguments supported"
msgstr ""
#: src/ptouch-print.c:575
#: src/ptouch-print.c:732
msgid "Option --writepng missing"
msgstr ""
#: src/ptouch-print.c:578
#: src/ptouch-print.c:735
msgid "Options --force_tape_width and --info can't be used together"
msgstr ""
#: src/ptouch-print.c:609
#: src/ptouch-print.c:766
#, c-format
msgid "ptouch_init() failed\n"
msgstr "ptouch_init() fehlgeschlagen\n"
#: src/ptouch-print.c:612
#: src/ptouch-print.c:775
#, c-format
msgid "ptouch_getstatus() failed\n"
msgstr "ptouch_getstatus() fehlgeschlagen\n"
#: src/ptouch-print.c:626
#: src/ptouch-print.c:789
#, fuzzy, c-format
msgid "maximum printing width for this printer is %ldpx\n"
msgid "printer has %d dpi, maximum printing width is %ld px\n"
msgstr "Maximal druckbare Breite für dieses Schriftband sind %ipx\n"
#: src/ptouch-print.c:627
#: src/ptouch-print.c:790
#, fuzzy, c-format
msgid "maximum printing width for this tape is %ldpx\n"
msgstr "Maximal druckbare Breite für dieses Schriftband sind %ipx\n"
#: src/ptouch-print.c:652
#: src/ptouch-print.c:815
#, c-format
msgid "failed to load image file\n"
msgstr ""
#: src/ptouch-print.c:661
#: src/ptouch-print.c:824
#, c-format
msgid "could not render text\n"
msgstr "Konnte Text nicht rendern\n"
#: src/ptouch-print.c:700
#: src/ptouch-print.c:865
#, c-format
msgid "ptouch_finalize(%d) failed\n"
msgstr "ptouch_finalize(%d) fehlgeschlagen\n"
#, fuzzy, c-format
#~ msgid "maximum printing width for this printer is %ldpx\n"
#~ msgstr "Maximal druckbare Breite für dieses Schriftband sind %ipx\n"
#, c-format
#~ msgid "ptouch-print version %s by Dominic Radermacher\n"
#~ msgstr "ptouch-print Version %s von Dominic Radermacher\n"
+135 -73
View File
@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: ptouch-print 1.3.1\n"
"Project-Id-Version: ptouch-print 1.7\n"
"Report-Msgid-Bugs-To: dominic@familie-radermacher.ch\n"
"POT-Creation-Date: 2025-08-11 09:57+0200\n"
"POT-Creation-Date: 2026-09-25 09:51+0200\n"
"PO-Revision-Date: 2024-05-23 22:26-0400\n"
"Last-Translator: dominic@familie-radermacher.ch\n"
"Language-Team: English <en@translate.freefriends.org>\n"
@@ -18,290 +18,352 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.2\n"
#: src/libptouch.c:105 src/libptouch.c:109 src/libptouch.c:113
#: src/libptouch.c:131 src/libptouch.c:135 src/libptouch.c:139
#, c-format
msgid "out of memory\n"
msgstr "out of memory\n"
#: src/libptouch.c:117
#: src/libptouch.c:143 src/libptouch.c:602
#, c-format
msgid "libusb_init() failed\n"
msgstr "libusb_init() failed\n"
#: src/libptouch.c:126
#: src/libptouch.c:152
#, c-format
msgid "failed to get device descriptor"
msgstr "failed to get device descriptor"
#: src/libptouch.c:132
#, c-format
msgid "%s found on USB bus %d, device %d\n"
msgstr "%s found on USB bus %d, device %d\n"
#: src/libptouch.c:147
#: src/libptouch.c:160
#, c-format
msgid "libusb_open error :%s\n"
msgstr "libusb_open error :%s\n"
#: src/libptouch.c:153
#: src/libptouch.c:171
#, fuzzy, c-format
msgid "%s found on USB bus %d, device %d, serial %s\n"
msgstr "%s found on USB bus %d, device %d\n"
#: src/libptouch.c:200
#, c-format
msgid "error while detaching kernel driver: %s\n"
msgstr "error while detaching kernel driver: %s\n"
#: src/libptouch.c:157
#: src/libptouch.c:204
#, c-format
msgid "interface claim error: %s\n"
msgstr "interface claim error: %s\n"
#: src/libptouch.c:168
#: src/libptouch.c:218
#, c-format
msgid "No P-Touch printer with serial %s found\n"
msgstr ""
#: src/libptouch.c:220 src/ptouch-print.c:722
#, c-format
msgid ""
"No P-Touch printer found on USB (remember to put switch to position E)\n"
msgstr ""
"No P-Touch printer found on USB (remember to put switch to position E)\n"
#: src/libptouch.c:188
#: src/libptouch.c:241
#, c-format
msgid "debug: called ptouch_send() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:195
#: src/libptouch.c:248
#, c-format
msgid "write error: %s\n"
msgstr "write error: %s\n"
#: src/libptouch.c:199
#: src/libptouch.c:252
#, fuzzy, c-format
msgid "write error: could send only %i of %ld bytes\n"
msgstr "write error: could send only %i of %i bytes\n"
#: src/libptouch.c:249
#: src/libptouch.c:302
#, c-format
msgid "debug: called ptouch_info_cmd() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:291
#: src/libptouch.c:344
#, fuzzy, c-format
msgid "debug: called ptouch_rasterstart() with NULL ptdev\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/libptouch.c:322
#: src/libptouch.c:384
#, c-format
msgid "debug: called ptouch_finalize() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:337
#: src/libptouch.c:399
#, c-format
msgid "debug: dumping raw status bytes\n"
msgstr "debug: dumping raw status bytes\n"
#: src/libptouch.c:356
#: src/libptouch.c:418
#, c-format
msgid "debug: called ptouch_getstatus() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:366 src/libptouch.c:402
#: src/libptouch.c:428 src/libptouch.c:459
#, c-format
msgid "read error: %s\n"
msgstr "read error: %s\n"
#: src/libptouch.c:371
#, c-format
msgid "timeout while waiting for status response\n"
#: src/libptouch.c:433
#, fuzzy, c-format
msgid "timeout (%i sec) while waiting for status response\n"
msgstr "timeout while waiting for status response\n"
#: src/libptouch.c:385
#: src/libptouch.c:442
#, c-format
msgid "unknown tape width of %imm, please report this.\n"
msgstr "unknown tape width of %imm, please report this.\n"
#: src/libptouch.c:391
#: src/libptouch.c:448
#, c-format
msgid "got only 16 bytes... wondering what they are:\n"
msgstr "got only 16 bytes... wondering what they are:\n"
#: src/libptouch.c:395
#: src/libptouch.c:452
#, c-format
msgid "read error: got %i instead of 32 bytes\n"
msgstr "read error: got %i instead of 32 bytes\n"
#: src/libptouch.c:398
#: src/libptouch.c:455
#, c-format
msgid "strange status:\n"
msgstr "strange status:\n"
#: src/libptouch.c:400
#: src/libptouch.c:457
#, c-format
msgid "trying to flush junk\n"
msgstr "trying to flush junk\n"
#: src/libptouch.c:405
#: src/libptouch.c:462
#, c-format
msgid "got another %i bytes. now try again\n"
msgstr "got another %i bytes. now try again\n"
#: src/libptouch.c:412
#: src/libptouch.c:469
#, fuzzy, c-format
msgid "debug: called ptouch_get_dpi() with NULL ptdev\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/libptouch.c:478
#, fuzzy, c-format
msgid "debug: called ptouch_cal_tape_width() with NULL ptdev\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/libptouch.c:489
#, c-format
msgid "printer with %d dpi not supported\n"
msgstr ""
#: src/libptouch.c:509
#, fuzzy, c-format
msgid "debug: called ptouch_get_max_lines() with NULL ptdev\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/libptouch.c:513
#, fuzzy, c-format
msgid "debug: called ptouch_get_max_lines() with invalid fontsize_px\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/libptouch.c:516
#, c-format
msgid "debug: calculated max lines %d \n"
msgstr ""
#: src/libptouch.c:523
#, c-format
msgid "debug: called ptouch_get_tape_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:421
#: src/libptouch.c:532
#, c-format
msgid "debug: called ptouch_get_max_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:433
#: src/libptouch.c:547
#, c-format
msgid "debug: called ptouch_sendraster() with NULL ptdev\n"
msgstr ""
#: src/ptouch-print.c:143
#: src/libptouch.c:625
#, fuzzy, c-format
msgid "%s\tserial %s\t(USB bus %d, device %d)%s\n"
msgstr "%s found on USB bus %d, device %d\n"
#: src/libptouch.c:629
msgid " - in P-Lite mode, unsupported"
msgstr ""
#: src/libptouch.c:630
msgid " - unsupported"
msgstr ""
#: src/ptouch-print.c:190
#, c-format
msgid "nothing to print\n"
msgstr ""
#: src/ptouch-print.c:151
#: src/ptouch-print.c:198
#, c-format
msgid "image is too large (%ipx x %ipx)\n"
msgstr "image is too large (%ipx x %ipx)\n"
#: src/ptouch-print.c:152
#: src/ptouch-print.c:199
#, c-format
msgid "maximum printing width for this tape is %ipx\n"
msgstr "maximum printing width for this tape is %ipx\n"
#: src/ptouch-print.c:155
#: src/ptouch-print.c:202
#, fuzzy, c-format
msgid "image size (%ipx x %ipx)\n"
msgstr "image is too large (%ipx x %ipx)\n"
#: src/ptouch-print.c:165
#: src/ptouch-print.c:218
#, c-format
msgid "ptouch_rasterstart() failed\n"
msgstr "ptouch_rasterstart() failed\n"
#: src/ptouch-print.c:171
#: src/ptouch-print.c:224
#, c-format
msgid "send print information command\n"
msgstr ""
#: src/ptouch-print.c:177
#: src/ptouch-print.c:230
#, c-format
msgid "send PT-D460BT magic commands\n"
msgstr ""
#: src/ptouch-print.c:183
#: src/ptouch-print.c:237
#, c-format
msgid "send precut command\n"
msgstr ""
#: src/ptouch-print.c:191
#: src/ptouch-print.c:246
#, c-format
msgid "send PT-D460BT chain commands\n"
msgstr ""
#: src/ptouch-print.c:203
#: src/ptouch-print.c:258
#, c-format
msgid "ptouch_sendraster() failed\n"
msgstr "ptouch_sendraster() failed\n"
#: src/ptouch-print.c:252
#: src/ptouch-print.c:307
#, c-format
msgid "writing image '%s' failed\n"
msgstr "writing image '%s' failed\n"
#: src/ptouch-print.c:274
#: src/ptouch-print.c:312
#, c-format
msgid "debug: o baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:275
#, c-format
msgid "debug: text baseline offset - %d\n"
msgid "printing '%s' requires %.1f mm of tape\n"
msgstr ""
#: src/ptouch-print.c:334
#, c-format
msgid "render_text(): %i lines, font = '%s'\n"
msgid "debug: z baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:337
#: src/ptouch-print.c:335
#, c-format
msgid "debug: text baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:408
#, c-format
msgid "render_text(): %i lines, font = '%s', align = '%c'\n"
msgstr ""
#: src/ptouch-print.c:411
#, c-format
msgid "warning: font config not available\n"
msgstr "warning: font config not available\n"
#: src/ptouch-print.c:341
#: src/ptouch-print.c:415
#, c-format
msgid "setting font size=%i\n"
msgstr "setting font size=%i\n"
#: src/ptouch-print.c:345
#: src/ptouch-print.c:417
#, fuzzy, c-format
msgid "ignoring setting font margin=%i\n"
msgstr "setting font size=%i\n"
#: src/ptouch-print.c:422
#, c-format
msgid "could not estimate needed font size\n"
msgstr "could not estimate needed font size\n"
#: src/ptouch-print.c:352
#: src/ptouch-print.c:429
#, c-format
msgid "choosing font size=%i\n"
msgstr "choosing font size=%i\n"
#: src/ptouch-print.c:368 src/ptouch-print.c:396
#, c-format
msgid "error in gdImageStringFT: %s\n"
#: src/ptouch-print.c:445 src/ptouch-print.c:479
#, fuzzy, c-format
msgid "error in gdImageStringFT_180dpi: %s\n"
msgstr "error in gdImageStringFT: %s\n"
#: src/ptouch-print.c:557
#: src/ptouch-print.c:636
#, c-format
msgid "Only up to %d lines are supported"
msgstr ""
#: src/ptouch-print.c:570
#: src/ptouch-print.c:727
msgid "No arguments supported"
msgstr ""
#: src/ptouch-print.c:575
#: src/ptouch-print.c:732
msgid "Option --writepng missing"
msgstr ""
#: src/ptouch-print.c:578
#: src/ptouch-print.c:735
msgid "Options --force_tape_width and --info can't be used together"
msgstr ""
#: src/ptouch-print.c:609
#: src/ptouch-print.c:766
#, c-format
msgid "ptouch_init() failed\n"
msgstr "ptouch_init() failed\n"
#: src/ptouch-print.c:612
#: src/ptouch-print.c:775
#, c-format
msgid "ptouch_getstatus() failed\n"
msgstr "ptouch_getstatus() failed\n"
#: src/ptouch-print.c:626
#: src/ptouch-print.c:789
#, fuzzy, c-format
msgid "maximum printing width for this printer is %ldpx\n"
msgid "printer has %d dpi, maximum printing width is %ld px\n"
msgstr "maximum printing width for this tape is %ipx\n"
#: src/ptouch-print.c:627
#: src/ptouch-print.c:790
#, fuzzy, c-format
msgid "maximum printing width for this tape is %ldpx\n"
msgstr "maximum printing width for this tape is %ipx\n"
#: src/ptouch-print.c:652
#: src/ptouch-print.c:815
#, c-format
msgid "failed to load image file\n"
msgstr ""
#: src/ptouch-print.c:661
#: src/ptouch-print.c:824
#, c-format
msgid "could not render text\n"
msgstr "could not render text\n"
#: src/ptouch-print.c:700
#: src/ptouch-print.c:865
#, c-format
msgid "ptouch_finalize(%d) failed\n"
msgstr "ptouch_finalize(%d) failed\n"
#, fuzzy, c-format
#~ msgid "maximum printing width for this printer is %ldpx\n"
#~ msgstr "maximum printing width for this tape is %ipx\n"
#, c-format
#~ msgid "ptouch-print version %s by Dominic Radermacher\n"
#~ msgstr "ptouch-print version %s by Dominic Radermacher\n"
+128 -70
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ptouch-print\n"
"Report-Msgid-Bugs-To: dominic@familie-radermacher.ch\n"
"POT-Creation-Date: 2025-08-11 10:05+0200\n"
"POT-Creation-Date: 2026-09-25 09:51+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,285 +17,343 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/libptouch.c:105 src/libptouch.c:109 src/libptouch.c:113
#: src/libptouch.c:131 src/libptouch.c:135 src/libptouch.c:139
#, c-format
msgid "out of memory\n"
msgstr ""
#: src/libptouch.c:117
#: src/libptouch.c:143 src/libptouch.c:602
#, c-format
msgid "libusb_init() failed\n"
msgstr ""
#: src/libptouch.c:126
#: src/libptouch.c:152
#, c-format
msgid "failed to get device descriptor"
msgstr ""
#: src/libptouch.c:132
#, c-format
msgid "%s found on USB bus %d, device %d\n"
msgstr ""
#: src/libptouch.c:147
#: src/libptouch.c:160
#, c-format
msgid "libusb_open error :%s\n"
msgstr ""
#: src/libptouch.c:153
#: src/libptouch.c:171
#, c-format
msgid "%s found on USB bus %d, device %d, serial %s\n"
msgstr ""
#: src/libptouch.c:200
#, c-format
msgid "error while detaching kernel driver: %s\n"
msgstr ""
#: src/libptouch.c:157
#: src/libptouch.c:204
#, c-format
msgid "interface claim error: %s\n"
msgstr ""
#: src/libptouch.c:168
#: src/libptouch.c:218
#, c-format
msgid "No P-Touch printer with serial %s found\n"
msgstr ""
#: src/libptouch.c:220 src/ptouch-print.c:722
#, c-format
msgid ""
"No P-Touch printer found on USB (remember to put switch to position E)\n"
msgstr ""
#: src/libptouch.c:188
#: src/libptouch.c:241
#, c-format
msgid "debug: called ptouch_send() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:195
#: src/libptouch.c:248
#, c-format
msgid "write error: %s\n"
msgstr ""
#: src/libptouch.c:199
#: src/libptouch.c:252
#, c-format
msgid "write error: could send only %i of %ld bytes\n"
msgstr ""
#: src/libptouch.c:249
#: src/libptouch.c:302
#, c-format
msgid "debug: called ptouch_info_cmd() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:291
#: src/libptouch.c:344
#, c-format
msgid "debug: called ptouch_rasterstart() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:322
#: src/libptouch.c:384
#, c-format
msgid "debug: called ptouch_finalize() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:337
#: src/libptouch.c:399
#, c-format
msgid "debug: dumping raw status bytes\n"
msgstr ""
#: src/libptouch.c:356
#: src/libptouch.c:418
#, c-format
msgid "debug: called ptouch_getstatus() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:366 src/libptouch.c:402
#: src/libptouch.c:428 src/libptouch.c:459
#, c-format
msgid "read error: %s\n"
msgstr ""
#: src/libptouch.c:371
#: src/libptouch.c:433
#, c-format
msgid "timeout while waiting for status response\n"
msgid "timeout (%i sec) while waiting for status response\n"
msgstr ""
#: src/libptouch.c:385
#: src/libptouch.c:442
#, c-format
msgid "unknown tape width of %imm, please report this.\n"
msgstr ""
#: src/libptouch.c:391
#: src/libptouch.c:448
#, c-format
msgid "got only 16 bytes... wondering what they are:\n"
msgstr ""
#: src/libptouch.c:395
#: src/libptouch.c:452
#, c-format
msgid "read error: got %i instead of 32 bytes\n"
msgstr ""
#: src/libptouch.c:398
#: src/libptouch.c:455
#, c-format
msgid "strange status:\n"
msgstr ""
#: src/libptouch.c:400
#: src/libptouch.c:457
#, c-format
msgid "trying to flush junk\n"
msgstr ""
#: src/libptouch.c:405
#: src/libptouch.c:462
#, c-format
msgid "got another %i bytes. now try again\n"
msgstr ""
#: src/libptouch.c:412
#: src/libptouch.c:469
#, c-format
msgid "debug: called ptouch_get_dpi() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:478
#, c-format
msgid "debug: called ptouch_cal_tape_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:489
#, c-format
msgid "printer with %d dpi not supported\n"
msgstr ""
#: src/libptouch.c:509
#, c-format
msgid "debug: called ptouch_get_max_lines() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:513
#, c-format
msgid "debug: called ptouch_get_max_lines() with invalid fontsize_px\n"
msgstr ""
#: src/libptouch.c:516
#, c-format
msgid "debug: calculated max lines %d \n"
msgstr ""
#: src/libptouch.c:523
#, c-format
msgid "debug: called ptouch_get_tape_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:421
#: src/libptouch.c:532
#, c-format
msgid "debug: called ptouch_get_max_width() with NULL ptdev\n"
msgstr ""
#: src/libptouch.c:433
#: src/libptouch.c:547
#, c-format
msgid "debug: called ptouch_sendraster() with NULL ptdev\n"
msgstr ""
#: src/ptouch-print.c:143
#: src/libptouch.c:625
#, c-format
msgid "%s\tserial %s\t(USB bus %d, device %d)%s\n"
msgstr ""
#: src/libptouch.c:629
msgid " - in P-Lite mode, unsupported"
msgstr ""
#: src/libptouch.c:630
msgid " - unsupported"
msgstr ""
#: src/ptouch-print.c:190
#, c-format
msgid "nothing to print\n"
msgstr ""
#: src/ptouch-print.c:151
#: src/ptouch-print.c:198
#, c-format
msgid "image is too large (%ipx x %ipx)\n"
msgstr ""
#: src/ptouch-print.c:152
#: src/ptouch-print.c:199
#, c-format
msgid "maximum printing width for this tape is %ipx\n"
msgstr ""
#: src/ptouch-print.c:155
#: src/ptouch-print.c:202
#, c-format
msgid "image size (%ipx x %ipx)\n"
msgstr ""
#: src/ptouch-print.c:165
#: src/ptouch-print.c:218
#, c-format
msgid "ptouch_rasterstart() failed\n"
msgstr ""
#: src/ptouch-print.c:171
#: src/ptouch-print.c:224
#, c-format
msgid "send print information command\n"
msgstr ""
#: src/ptouch-print.c:177
#: src/ptouch-print.c:230
#, c-format
msgid "send PT-D460BT magic commands\n"
msgstr ""
#: src/ptouch-print.c:183
#: src/ptouch-print.c:237
#, c-format
msgid "send precut command\n"
msgstr ""
#: src/ptouch-print.c:191
#: src/ptouch-print.c:246
#, c-format
msgid "send PT-D460BT chain commands\n"
msgstr ""
#: src/ptouch-print.c:203
#: src/ptouch-print.c:258
#, c-format
msgid "ptouch_sendraster() failed\n"
msgstr ""
#: src/ptouch-print.c:252
#: src/ptouch-print.c:307
#, c-format
msgid "writing image '%s' failed\n"
msgstr ""
#: src/ptouch-print.c:274
#: src/ptouch-print.c:312
#, c-format
msgid "debug: o baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:275
#, c-format
msgid "debug: text baseline offset - %d\n"
msgid "printing '%s' requires %.1f mm of tape\n"
msgstr ""
#: src/ptouch-print.c:334
#, c-format
msgid "render_text(): %i lines, font = '%s'\n"
msgid "debug: z baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:337
#: src/ptouch-print.c:335
#, c-format
msgid "debug: text baseline offset - %d\n"
msgstr ""
#: src/ptouch-print.c:408
#, c-format
msgid "render_text(): %i lines, font = '%s', align = '%c'\n"
msgstr ""
#: src/ptouch-print.c:411
#, c-format
msgid "warning: font config not available\n"
msgstr ""
#: src/ptouch-print.c:341
#: src/ptouch-print.c:415
#, c-format
msgid "setting font size=%i\n"
msgstr ""
#: src/ptouch-print.c:345
#: src/ptouch-print.c:417
#, c-format
msgid "ignoring setting font margin=%i\n"
msgstr ""
#: src/ptouch-print.c:422
#, c-format
msgid "could not estimate needed font size\n"
msgstr ""
#: src/ptouch-print.c:352
#: src/ptouch-print.c:429
#, c-format
msgid "choosing font size=%i\n"
msgstr ""
#: src/ptouch-print.c:368 src/ptouch-print.c:396
#: src/ptouch-print.c:445 src/ptouch-print.c:479
#, c-format
msgid "error in gdImageStringFT: %s\n"
msgid "error in gdImageStringFT_180dpi: %s\n"
msgstr ""
#: src/ptouch-print.c:557
#: src/ptouch-print.c:636
#, c-format
msgid "Only up to %d lines are supported"
msgstr ""
#: src/ptouch-print.c:570
#: src/ptouch-print.c:727
msgid "No arguments supported"
msgstr ""
#: src/ptouch-print.c:575
#: src/ptouch-print.c:732
msgid "Option --writepng missing"
msgstr ""
#: src/ptouch-print.c:578
#: src/ptouch-print.c:735
msgid "Options --force_tape_width and --info can't be used together"
msgstr ""
#: src/ptouch-print.c:609
#: src/ptouch-print.c:766
#, c-format
msgid "ptouch_init() failed\n"
msgstr ""
#: src/ptouch-print.c:612
#: src/ptouch-print.c:775
#, c-format
msgid "ptouch_getstatus() failed\n"
msgstr ""
#: src/ptouch-print.c:626
#: src/ptouch-print.c:789
#, c-format
msgid "maximum printing width for this printer is %ldpx\n"
msgid "printer has %d dpi, maximum printing width is %ld px\n"
msgstr ""
#: src/ptouch-print.c:627
#: src/ptouch-print.c:790
#, c-format
msgid "maximum printing width for this tape is %ldpx\n"
msgstr ""
#: src/ptouch-print.c:652
#: src/ptouch-print.c:815
#, c-format
msgid "failed to load image file\n"
msgstr ""
#: src/ptouch-print.c:661
#: src/ptouch-print.c:824
#, c-format
msgid "could not render text\n"
msgstr ""
#: src/ptouch-print.c:700
#: src/ptouch-print.c:865
#, c-format
msgid "ptouch_finalize(%d) failed\n"
msgstr ""
+20 -2
View File
@@ -28,9 +28,22 @@ once in any order, and will be executed in the given order.
.TP
.BR \-\-debug
Enables printing of debugging information.
.TP
.BR \-\-timeout\ \fI<time>
Set the seconds ptouch-print is waiting for finishing a previous ptouch-print command.
Default is 1 second. 0 (zero) means wait forever.
Useful if ptouch-print is used in a script multiple times, and the device is waiting for the user
to use the mechanical cutter.
.TP
.BR \-\-serial\ \fI<serial>
Use the printer with this USB serial number, when more than one printer is connected.
Use \-\-list\-connected to see the serial numbers.
.SS "Font selection options"
.TP
.BR \-\-fontmargin\ \fI<size>
When auto-detecting font size account for a margin above and below the text.
.TP
.BR \-\-fontsize\ \fI<size>
Disable auto-detection of the font size and force the font size to the size
given as argument. Please note that text will be cut off if you specify a
@@ -50,7 +63,9 @@ file (which can be printed later using the --image printing command option).
.BR \-\-text\ \fItext
Print the given text at the current position. Text including spaces must be
enclosed in question marks.
To print a text in multiple lines, give multiple text arguments.
Literal '\\n' or actual newline characters in the text will be treated as
line breaks.
To print a text in multiple lines, either use '\\n' or use the -n argument.
Also see the
.BR EXAMPLES
section.
@@ -79,6 +94,9 @@ Show info about the tape detected (like printing width etc.) and exit.
.TP
.BR \-\-list-supported
List all supported printers
.TP
.BR \-\-list-connected
List all connected printers with their USB serial numbers, for use with \-\-serial
.SH DEFAULTS
The default font used is 'DejaVuSans'.
@@ -101,7 +119,7 @@ Printer device could not been opened.
\fBptouch-print\fR \fI--text\fR 'Hello World'
Print the text 'Hello World' in one line
.TP
\fBptouch-print\fR \fI--text\fR 'Hello' 'World'
\fBptouch-print\fR \fI--text\fR 'Hello' -n 'World'
Print the text 'Hello World' in two lines ('Hello' in the first line
and 'World' in the second line).
.TP
+234 -58
View File
@@ -1,7 +1,7 @@
/*
libptouch - functions to help accessing a brother ptouch
Copyright (C) 2013-2025 Dominic Radermacher <dominic@familie-radermacher.ch>
Copyright (C) 2013-2026 Dominic Radermacher <dominic@familie-radermacher.ch>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3 as
@@ -33,66 +33,92 @@
#define _(s) gettext(s)
/* Print area width in 180 DPI pixels */
/* The 360dpi print-area values (px360) are Brother's documented values for
the PT-P900 series and are NOT simply double the 180dpi ones: the 180dpi
figures for wide tapes are clamped by those printers' 128-pin printheads,
not the actual printable width. Only 36mm has been verified on hardware;
the others come from Brother's raster reference. 21mm has no P900 spec
value and keeps the doubled figure. calc_tape_px() clamps the result to
the printer's max_px, so printers with a narrower printhead stay safe. */
struct _pt_tape_info tape_info[]= {
{ 4, 24, 0.5}, /* 3.5 mm tape */
{ 6, 32, 1.0}, /* 6 mm tape */
{ 9, 52, 1.0}, /* 9 mm tape */
{12, 76, 2.0}, /* 12 mm tape */
{18, 120, 3.0}, /* 18 mm tape */
{24, 128, 3.0}, /* 24 mm tape */
{36, 192, 4.5}, /* 36 mm tape */
{ 0, 0, 0.0} /* terminating entry */
{ 4, 24, 48, 0.5}, /* 3.5 mm tape */
{ 6, 32, 64, 1.0}, /* 6 mm tape */
{ 9, 52, 106, 1.0}, /* 9 mm tape */
{12, 76, 150, 2.0}, /* 12 mm tape */
{18, 120, 234, 3.0}, /* 18 mm tape */
{21, 124, 248, 3.0}, /* 21 mm tape (360dpi value unverified) */
{24, 128, 320, 3.0}, /* 24 mm tape */
{36, 192, 454, 4.5}, /* 36 mm tape */
{ 0, 0, 0, 0.0} /* terminating entry */
};
struct _pt_dev_info ptdevs[] = {
{0x04f9, 0x2001, "PT-9200DX", 384, 360, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT}, /* 360dpi, maximum 128px, max tape width 36mm */
{0x04f9, 0x2004, "PT-2300", 112, 180, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT}, /* 180dpi, 112px printhead */
{0x04f9, 0x2007, "PT-2420PC", 128, 180, FLAG_RASTER_PACKBITS}, /* 180dpi, 128px, maximum tape width 24mm, must send TIFF compressed pixel data */
{0x04f9, 0x2011, "PT-2450PC", 128, 180, FLAG_RASTER_PACKBITS},
{0x04f9, 0x2019, "PT-1950", 112, 180, FLAG_RASTER_PACKBITS}, /* 180dpi, apparently 112px printhead ?, maximum tape width 18mm - unconfirmed if it works */
{0x04f9, 0x201f, "PT-2700", 128, 180, FLAG_HAS_PRECUT},
{0x04f9, 0x202c, "PT-1230PC", 128, 180, FLAG_NONE}, /* 180dpi, supports tapes up to 12mm - I don't know how much pixels it can print! */
{0x04f9, 0x2001, "PT-9200DX", 384, 360, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT, 0, 0}, /* 360dpi, maximum 128px, max tape width 36mm */
{0x04f9, 0x2002, "PT-9200DX", 384, 360, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT, 0, 0}, /* reported by Christian Pauls - either 0x2001 is wrong, or this printer exists with two different IDs */
{0x04f9, 0x203c, "PT-9700PC", 384, 360, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT|FLAG_P700_INIT|FLAG_USE_INFO_CMD, 0, 0}, /* 360dpi, max tape width 36mm. FLAG_P700_INIT causes printer to send a status response after rasterstart; flushed in ptouch_rasterstart(). */
{0x04f9, 0x2004, "PT-2300", 112, 180, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT, 0, 0}, /* 180dpi, 112px printhead */
{0x04f9, 0x2007, "PT-2420PC", 128, 180, FLAG_RASTER_PACKBITS, 0, 0}, /* 180dpi, 128px, maximum tape width 24mm, must send TIFF compressed pixel data */
//{0x04f9, 0x200d, "PT-3600", 384, 360, FLAG_RASTER_PACKBITS, 0, 0},
{0x04f9, 0x2011, "PT-2450PC", 128, 180, FLAG_RASTER_PACKBITS, 0, 0},
{0x04f9, 0x2019, "PT-1950", 112, 180, FLAG_RASTER_PACKBITS, 0, 0}, /* 180dpi, apparently 112px printhead ?, maximum tape width 18mm - unconfirmed if it works */
{0x04f9, 0x201f, "PT-2700", 128, 180, FLAG_HAS_PRECUT, 0, 0},
{0x04f9, 0x202c, "PT-1230PC", 128, 180, FLAG_NONE, 0, 0}, /* 180dpi, supports tapes up to 12mm - I don't know how much pixels it can print! */
/* Notes about the PT-1230PC: While it is true that this printer supports
max 12mm tapes, it apparently expects > 76px data - the first 32px
must be blank. */
{0x04f9, 0x202d, "PT-2430PC", 128, 180, FLAG_NONE}, /* 180dpi, maximum 128px */
{0x04f9, 0x2030, "PT-1230PC (PLite Mode)", 128, 180, FLAG_PLITE},
{0x04f9, 0x2031, "PT-2430PC (PLite Mode)", 128, 180, FLAG_PLITE},
{0x04f9, 0x2041, "PT-2730", 128, 180, FLAG_NONE}, /* 180dpi, maximum 128px, max tape width 24mm - reported to work with some quirks */
{0x04f9, 0x202d, "PT-2430PC", 128, 180, FLAG_HAS_PRECUT, 0, 0}, /* 180dpi, maximum 128px. Same head width/dpi as PT-2700 (which has FLAG_HAS_PRECUT); confirmed precut works on real hardware. */
{0x04f9, 0x2030, "PT-1230PC (PLite Mode)", 128, 180, FLAG_PLITE, 0, 0},
{0x04f9, 0x2031, "PT-2430PC (PLite Mode)", 128, 180, FLAG_PLITE, 0, 0},
{0x04f9, 0x2041, "PT-2730", 128, 180, FLAG_NONE, 0, 0}, /* 180dpi, maximum 128px, max tape width 24mm - reported to work with some quirks */
/* Notes about the PT-2730: was reported to need 48px whitespace
within png-images before content is actually printed - can not check this */
{0x04f9, 0x205e, "PT-H500", 128, 180, FLAG_RASTER_PACKBITS},
{0x04f9, 0x205e, "PT-H500", 128, 180, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT, 0, 0},
/* Note about the PT-H500: was reported by Eike with the remark that
it might need some trailing padding */
{0x04f9, 0x205f, "PT-E500", 128, 180, FLAG_RASTER_PACKBITS},
{0x04f9, 0x205f, "PT-E500", 128, 180, FLAG_RASTER_PACKBITS, 0, 0},
/* Note about the PT-E500: was reported by Jesse Becker with the
remark that it also needs some padding (white pixels) */
{0x04f9, 0x2060, "PT-E550W", 128, 180, FLAG_UNSUP_RASTER},
{0x04f9, 0x2060, "PT-E550W", 128, 180, FLAG_UNSUP_RASTER, 0, 0},
/* Note about the PT-E550W: was reported by Tim Biermann but does not
work yet (only prints empty tape with FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT) */
{0x04f9, 0x2061, "PT-P700", 128, 180, FLAG_RASTER_PACKBITS|FLAG_P700_INIT|FLAG_HAS_PRECUT},
{0x04f9, 0x2062, "PT-P750W", 128, 180, FLAG_RASTER_PACKBITS|FLAG_P700_INIT},
{0x04f9, 0x2064, "PT-P700 (PLite Mode)", 128, 180, FLAG_PLITE},
{0x04f9, 0x2065, "PT-P750W (PLite Mode)", 128, 180, FLAG_PLITE},
{0x04f9, 0x20df, "PT-D410", 128, 180, FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC},
{0x04f9, 0x2073, "PT-D450", 128, 180, FLAG_USE_INFO_CMD},
{0x04f9, 0x2061, "PT-P700", 128, 180, FLAG_RASTER_PACKBITS|FLAG_P700_INIT|FLAG_HAS_PRECUT, 0, 0},
{0x04f9, 0x2062, "PT-P750W", 128, 180, FLAG_RASTER_PACKBITS|FLAG_P700_INIT, 0, 0},
{0x04f9, 0x2064, "PT-P700 (PLite Mode)", 128, 180, FLAG_PLITE, 0, 0},
{0x04f9, 0x2065, "PT-P750W (PLite Mode)", 128, 180, FLAG_PLITE, 0, 0},
{0x04f9, 0x2073, "PT-D450", 128, 180, FLAG_USE_INFO_CMD, 0, 0},
/* Notes about the PT-D450: I'm unsure if print width really is 128px */
{0x04f9, 0x20e0, "PT-D460BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC},
{0x04f9, 0x2074, "PT-D600", 128, 180, FLAG_RASTER_PACKBITS},
{0x04f9, 0x2074, "PT-D600", 128, 180, FLAG_RASTER_PACKBITS, 0, 0},
/* PT-D600 was reported to work, but with some quirks (premature
cutting of tape, printing maximum of 73mm length) */
{0x04f9, 0x20e1, "PT-D610BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC},
//{0x04f9, 0x200d, "PT-3600", 384, 360, FLAG_RASTER_PACKBITS},
{0x04f9, 0x20af, "PT-P710BT", 128, 180, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT},
{0x04f9, 0x2085, "PT-P900Wc", 560, 360, FLAG_RASTER_PACKBITS|FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT, -8, 0},
/* PT-P900Wc: 360dpi, 560px printhead (70 bytes/raster line). Verified
printing on 36mm laminated tape. Narrower tape widths use Brother's
documented 360dpi print areas (see tape_info) but are untested.
pin_offset = -8: the print area is centred at pin 272, not the head
centre (pin 280) - a constant offset across all tape widths. See the
Brother "Software Developer's Manual - Raster Command Reference,
PT-P900/P900W/P950NW", section 2.3.5 "Raster line". */
{0x04f9, 0x20af, "PT-P710BT", 128, 180, FLAG_RASTER_PACKBITS|FLAG_HAS_PRECUT, 0, 0},
{0x04f9, 0x20df, "PT-D410", 128, 180, FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC, 0, 0},
{0x04f9, 0x20e0, "PT-D460BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC, 0, 0},
{0x04f9, 0x20e1, "PT-D610BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_HAS_PRECUT|FLAG_D460BT_MAGIC, 0, 0},
/* added by Christian, PT-E310BT (aka PT-E310BTVP) requires these flags, otherwise not returning from libusb_bulk_transfer-call */
/* printhead 128px, 180 dpi resolution */
/* 3,5/6/9/12/18 mm TZe Tapes, 12mm and 18mm tested */
/* 5,2/9/11,2 mm HSe heat shrink tubes not tested, probably requiring extension of struct _pt_tape_info */
{0x04f9, 0x2201, "PT-E310BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_D460BT_MAGIC},
{0,0,"",0,0,0}
{0x04f9, 0x2201, "PT-E310BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_D460BT_MAGIC, 0, 0},
{0x04f9, 0x2203, "PT-E560BT", 128, 180, FLAG_P700_INIT|FLAG_USE_INFO_CMD|FLAG_D460BT_MAGIC, 0, 10},
{0,0,"",0,0,0,0,0}
};
int ptouch_open(ptouch_dev *ptdev)
{
return ptouch_open_serial(ptdev, NULL);
}
/* Like ptouch_open(), but when serial is not NULL only a printer whose
USB serial number matches it is used. */
int ptouch_open_serial(ptouch_dev *ptdev, const char *serial)
{
libusb_device **devs;
libusb_device *dev;
@@ -129,22 +155,43 @@ int ptouch_open(ptouch_dev *ptdev)
}
for (int k=0; ptdevs[k].vid > 0; ++k) {
if ((desc.idVendor == ptdevs[k].vid) && (desc.idProduct == ptdevs[k].pid) && (ptdevs[k].flags >= 0)) {
fprintf(stderr, _("%s found on USB bus %d, device %d\n"),
unsigned char buf[64] = {0};
if ((r=libusb_open(dev, &handle)) != 0) {
fprintf(stderr, _("libusb_open error :%s\n"), libusb_error_name(r));
if (serial) {
/* can't read its serial, so it can't be the one we want */
break;
}
libusb_free_device_list(devs, 1);
return -1;
}
if (desc.iSerialNumber) {
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf));
}
fprintf(stderr, _("%s found on USB bus %d, device %d, serial %s\n"),
ptdevs[k].name,
libusb_get_bus_number(dev),
libusb_get_device_address(dev));
libusb_get_device_address(dev),
buf[0] ? (char *)buf : "-");
/* check the serial before the P-Lite/unsupported checks, so
a different printer in the wrong mode doesn't end the search */
if (serial && (strcmp((char *)buf, serial) != 0)) {
libusb_close(handle);
handle = NULL;
break; /* next device */
}
if (ptdevs[k].flags & FLAG_PLITE) {
printf("Printer is in P-Lite Mode, which is unsupported\n\n");
printf("Turn off P-Lite mode by changing switch from position EL to position E\n");
printf("or by pressing the PLite button for ~ 2 seconds (or consult the manual)\n");
libusb_close(handle);
libusb_free_device_list(devs, 1);
return -1;
}
if (ptdevs[k].flags & FLAG_UNSUP_RASTER) {
printf("Unfortunately, that printer currently is unsupported (it has a different raster data transfer)\n");
return -1;
}
if ((r=libusb_open(dev, &handle)) != 0) {
fprintf(stderr, _("libusb_open error :%s\n"), libusb_error_name(r));
libusb_close(handle);
libusb_free_device_list(devs, 1);
return -1;
}
libusb_free_device_list(devs, 1);
@@ -161,11 +208,17 @@ int ptouch_open(ptouch_dev *ptdev)
(*ptdev)->devinfo->dpi=ptdevs[k].dpi;
(*ptdev)->devinfo->max_px=ptdevs[k].max_px;
(*ptdev)->devinfo->flags=ptdevs[k].flags;
(*ptdev)->devinfo->pin_offset=ptdevs[k].pin_offset;
(*ptdev)->devinfo->min_timeout=ptdevs[k].min_timeout;
return 0;
}
}
}
if (serial) {
fprintf(stderr, _("No P-Touch printer with serial %s found\n"), serial);
} else {
fprintf(stderr, _("No P-Touch printer found on USB (remember to put switch to position E)\n"));
}
libusb_free_device_list(devs, 1);
return -1;
}
@@ -296,7 +349,16 @@ int ptouch_rasterstart(ptouch_dev ptdev)
/* 1B 69 61 01 = switch mode (0=esc/p, 1=raster mode) */
char cmd2[] = "\x1b\x69\x61\x01";
if (ptdev->devinfo->flags & FLAG_P700_INIT) {
return ptouch_send(ptdev, (uint8_t *)cmd2, strlen(cmd2));
int r = ptouch_send(ptdev, (uint8_t *)cmd2, strlen(cmd2));
if (r != 0) {
return r;
}
/* Printer sends a status response after entering raster mode;
flush it so subsequent raster writes don't block. */
uint8_t buf[32];
int tx = 0;
libusb_bulk_transfer(ptdev->h, 0x81, buf, sizeof(buf), &tx, 1000);
return 0;
} /* else */
return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
}
@@ -336,7 +398,7 @@ void ptouch_rawstatus(uint8_t raw[32])
{
fprintf(stderr, _("debug: dumping raw status bytes\n"));
for (int i=0; i<32; ++i) {
fprintf(stderr, "%02x ", raw[i]);
fprintf(stderr, "0x%02x ", raw[i]);
if (((i+1) % 16) == 0) {
fprintf(stderr, "\n");
}
@@ -345,11 +407,11 @@ void ptouch_rawstatus(uint8_t raw[32])
return;
}
int ptouch_getstatus(ptouch_dev ptdev)
int ptouch_getstatus(ptouch_dev ptdev, int timeout)
{
char cmd[]="\x1biS"; /* 1B 69 53 = ESC i S = Status info request */
uint8_t buf[32] = {};
int i, r, tx=0, tries=0;
int r, tx=0, tries=0, maxtries=timeout*10;
struct timespec w;
if (!ptdev) {
@@ -367,20 +429,15 @@ int ptouch_getstatus(ptouch_dev ptdev)
return -1;
}
++tries;
if (tries > 10) {
fprintf(stderr, _("timeout while waiting for status response\n"));
if (timeout && tries > maxtries) {
fprintf(stderr, _("timeout (%i sec) while waiting for status response\n"), timeout);
return -1;
}
}
if (tx == 32) {
if (buf[0]==0x80 && buf[1]==0x20) {
memcpy(ptdev->status, buf, 32);
ptdev->tape_width_px=0;
for (i=0; tape_info[i].mm > 0; ++i) {
if (tape_info[i].mm == buf[10]) {
ptdev->tape_width_px=tape_info[i].px;
}
}
ptdev->tape_width_px = ptouch_calc_tape_px(ptdev, buf[10]);
if (ptdev->tape_width_px == 0) {
fprintf(stderr, _("unknown tape width of %imm, please report this.\n"), buf[10]);
}
@@ -406,6 +463,60 @@ int ptouch_getstatus(ptouch_dev ptdev)
return -1;
}
int ptouch_get_dpi(ptouch_dev ptdev)
{
if (!ptdev) {
fprintf(stderr, _("debug: called ptouch_get_dpi() with NULL ptdev\n"));
return 0;
}
return ptdev->devinfo->dpi;
}
int ptouch_calc_tape_px(ptouch_dev ptdev, const uint8_t tape_width_mm)
{
if (!ptdev) {
fprintf(stderr, _("debug: called ptouch_cal_tape_width() with NULL ptdev\n"));
return 0;
}
int tape_width_px = 0;
for (int i=0; tape_info[i].mm > 0; ++i) {
if (tape_info[i].mm == tape_width_mm) {
if (ptdev->devinfo->dpi == 180) {
tape_width_px = tape_info[i].px;
} else if (ptdev->devinfo->dpi == 360) {
tape_width_px = tape_info[i].px360;
} else {
fprintf(stderr, _("printer with %d dpi not supported\n"), ptdev->devinfo->dpi);
}
}
}
/* Never print wider than the physical printhead. This also keeps 360dpi
printers with a narrower head (e.g. PT-9200DX, 384px) safe when the
tape's printable area exceeds what they can drive. */
if (tape_width_px > ptdev->devinfo->max_px) {
tape_width_px = ptdev->devinfo->max_px;
}
return tape_width_px;
}
/* TODO: The actual number of maximum lines should be calculated according to
printer resolution, tapewidth and fontsize */
/* printer resolution is planned to be taken into account when calculating
tape_width in px */
int ptouch_get_max_lines(ptouch_dev ptdev, int fontsize_px)
{
if (!ptdev) {
fprintf(stderr, _("debug: called ptouch_get_max_lines() with NULL ptdev\n"));
return 0;
}
if (fontsize_px <= 0) {
fprintf(stderr, _("debug: called ptouch_get_max_lines() with invalid fontsize_px\n"));
return 0;
}
fprintf(stderr, _("debug: calculated max lines %d \n"), ptdev->tape_width_px / fontsize_px);
return 4;
}
size_t ptouch_get_tape_width(ptouch_dev ptdev)
{
if (!ptdev) {
@@ -426,7 +537,10 @@ size_t ptouch_get_max_width(ptouch_dev ptdev)
int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, size_t len)
{
uint8_t buf[64];
/* Must hold a full raster line (max_px/8 bytes) plus up to 4 header
bytes. ptouch_send() caps a packet at 128 bytes, so this is the
largest a packet can ever be. */
uint8_t buf[128];
int rc;
if (!ptdev) {
@@ -455,15 +569,75 @@ int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, size_t len)
void ptouch_list_supported()
{
const int columns = 5;
printf("Supported printers (some might have quirks)\n");
int col=0;
for (int i=0; ptdevs[i].vid > 0; ++i) {
if ((ptdevs[i].flags & FLAG_PLITE) != FLAG_PLITE) {
printf("\t%s\n", ptdevs[i].name);
printf("%s", ptdevs[i].name);
if (strlen(ptdevs[i].name) < 8) {
printf("\t");
}
printf("%c", (col < (columns - 1))?'\t':'\n');
++col;
col = (col % columns);
}
}
printf("\n");
return;
}
/* Print every connected P-Touch printer with its USB serial number, which
can then be passed to ptouch_open_serial(). Returns the number of
printers found, or -1 on error. */
int ptouch_list_connected()
{
libusb_device **devs;
libusb_device *dev;
libusb_device_handle *handle;
struct libusb_device_descriptor desc;
int r, i=0, found=0;
if ((libusb_init(NULL)) < 0) {
fprintf(stderr, _("libusb_init() failed\n"));
return -1;
}
if (libusb_get_device_list(NULL, &devs) < 0) {
libusb_exit(NULL);
return -1;
}
while ((dev=devs[i++]) != NULL) {
if (libusb_get_device_descriptor(dev, &desc) < 0) {
continue;
}
for (int k=0; ptdevs[k].vid > 0; ++k) {
if ((desc.idVendor == ptdevs[k].vid) && (desc.idProduct == ptdevs[k].pid) && (ptdevs[k].flags >= 0)) {
unsigned char buf[64] = {0};
const char *serial = "-";
if ((r=libusb_open(dev, &handle)) != 0) {
serial = libusb_error_name(r);
} else {
if (desc.iSerialNumber && (libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf)) > 0)) {
serial = (char *)buf;
}
libusb_close(handle);
}
printf(_("%s\tserial %s\t(USB bus %d, device %d)%s\n"),
ptdevs[k].name, serial,
libusb_get_bus_number(dev),
libusb_get_device_address(dev),
(ptdevs[k].flags & FLAG_PLITE) ? _(" - in P-Lite mode, unsupported") :
(ptdevs[k].flags & FLAG_UNSUP_RASTER) ? _(" - unsupported") : "");
++found;
break;
}
}
}
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return found;
}
const char* pt_mediatype(const uint8_t media_type)
{
switch (media_type) {
@@ -471,10 +645,11 @@ const char* pt_mediatype(const uint8_t media_type)
case 0x01: return "Laminated tape"; break;
case 0x03: return "Non-laminated tape"; break;
case 0x04: return "Fabric tape"; break;
case 0x11: return "Heat-shrink tube"; break;
case 0x13: return "Fle tape"; break;
case 0x11: return "Heat-shrink tube"; break; // Seems wrong, should be 0x17
case 0x13: return "Flexi tape"; break;
case 0x14: return "Flexible ID tape"; break;
case 0x15: return "Satin tape"; break;
case 0x17: return "Heat-shrink tube"; break;
case 0xff: return "Incompatible tape"; break;
default: return "unknown";
}
@@ -508,6 +683,7 @@ const char* pt_tapecolor(const uint8_t tape_color)
case 0x61: return "Pink"; break;
case 0x62: return "Blue"; break;
case 0x70: return "Heat-shrink Tube"; break;
case 0x71: return "Heat-shrink Tube white"; break;
case 0x90: return "White(Flex. ID)"; break;
case 0x91: return "Yellow(Flex. ID)"; break;
case 0xf0: return "Cleaning"; break;
+218 -53
View File
@@ -1,7 +1,7 @@
/*
ptouch-print - Print labels with images or text on a Brother P-Touch
Copyright (C) 2015-2025 Dominic Radermacher <dominic@familie-radermacher.ch>
Copyright (C) 2015-2026 Dominic Radermacher <dominic@familie-radermacher.ch>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3 as
@@ -18,6 +18,7 @@
*/
#include <argp.h>
#include <errno.h>
#include <stdio.h> /* printf() */
#include <stdlib.h> /* exit(), malloc() */
#include <stdbool.h>
@@ -34,20 +35,37 @@
#define _(s) gettext(s)
#define MAX_LINES 4 /* maybe this should depend on tape size */
#ifdef NEED_STRCHRNUL
/* GNU extension. argp-standalone references it, so platforms that need
argp-standalone need this too. Selected by cmake/Findargp.cmake. */
char *strchrnul(const char *s, int c)
{
const char *p = strchr(s, c);
return (char *)(p ? p : s + strlen(s));
}
#endif
#define MAX_LINES 4 /* this should be calculated depending on tape size */
#define P_NAME "ptouch-print"
typedef enum { ALIGN_LEFT = 'l', ALIGN_CENTER = 'c', ALIGN_RIGHT = 'r' } align_type_t;
struct arguments {
align_type_t align;
bool chain;
bool precut;
int copies;
bool debug;
bool info;
char *font_file;
int font_size;
int font_margin;
int forced_tape_width;
char *save_png;
int verbose;
int timeout;
char *serial;
};
typedef enum { JOB_CUTMARK, JOB_IMAGE, JOB_PAD, JOB_TEXT, JOB_UNDEFINED } job_type_t;
@@ -64,47 +82,57 @@ void rasterline_setpixel(uint8_t* rasterline, size_t size, int pixel);
int get_baselineoffset(char *text, char *font, int fsz);
int find_fontsize(int want_px, char *font, char *text);
int needed_width(char *text, char *font, int fsz);
int print_img(ptouch_dev ptdev, gdImage *im, int chain);
int print_img(ptouch_dev ptdev, gdImage *im, int chain, int precut);
int write_png(gdImage *im, const char *file);
gdImage *img_append(gdImage *in_1, gdImage *in_2);
gdImage *img_cutmark(int print_width);
gdImage *render_text(char *font, char *line[], int lines, int print_width);
void unsupported_printer(ptouch_dev ptdev);
void add_job(job_type_t type, int n, char *line);
void add_text(struct argp_state *state, char *arg, bool new_job);
static error_t parse_opt(int key, char *arg, struct argp_state *state);
const char *argp_program_version = P_NAME " " VERSION;
const char *argp_program_bug_address = "Dominic Radermacher <dominic@familie-radermacher.ch>";
static char doc[] = "ptouch-print is a command line tool to print labels on Brother P-Touch printers on Linux.";
static char args_doc[] = "";
static struct argp_option options[] = {
// name, key, arg, flags, doc, group
{ 0, 0, 0, 0, "options:", 1},
{ "debug", 1, 0, 0, "Enable debug output", 1},
{ "font", 2, "<file>", 0, "Use font <file> or <name>", 1},
{ "fontsize", 3, "<size>", 0, "Manually set font size", 1},
{ "writepng", 4, "<file>", 0, "Instead of printing, write output to png <file>", 1},
{ "force-tape-width", 5, "<px>", 0, "Set tape width in pixels, use together with --writepng without a printer connected", 1},
{ "copies", 6, "<number>", 0, "Sets the number of identical prints", 1},
{ "font-size", 3, "<size>", 0, "Manually set font size, or ...", 1},
{ "fontsize", 3, "<size>", OPTION_ALIAS, "alias for font-size", 1},
{ "font-margin", 4, "<size>", 0, "Manually set font top/bottom margin (in px)", 1},
{ "fontmargin", 4, "<size>", OPTION_ALIAS, "alias for font-margin", 1},
{ "write-png", 'w', "<file>", 0, "Instead of printing, write output to png <file>", 1},
{ "writepng", 'w', "<file>", OPTION_ALIAS, "alias for write-png", 1},
{ "force-tape-width", 6, "<px>", 0, "Set tape width in pixels, use together with --writepng without a printer connected", 1},
{ "copies", 7, "<number>", 0, "Sets the number of identical prints", 1},
{ "timeout", 8, "<seconds>", 0, "Set timeout waiting for finishing previous job. Default:1, or a per-printer minimum where one is known. 0 means infinity", 1},
{ "serial", 12, "<serial>", 0, "Use the printer with this USB serial number", 1 },
{ 0, 0, 0, 0, "print commands:", 2},
{ "image", 'i', "<file>", 0, "Print the given image which must be a 2 color (black/white) png", 2},
{ "text", 't', "<text>", 0, "Print line of <text>. If the text contains spaces, use quotation marks taround it", 2},
{ "text", 't', "<text>", 0, "Print line of <text>. If the text contains spaces, use quotation marks around it. \\n will be replaced by a newline", 2},
{ "cutmark", 'c', 0, 0, "Print a mark where the tape should be cut", 2},
{ "pad", 'p', "<n>", 0, "Add n pixels padding (blank tape)", 2},
{ "chain", 10, 0, 0, "Skip final feed of label and any automatic cut", 2},
{ "newline", 'n', "<text>", 0, "Add text in a new line (up to 4 lines)", 2},
{ "precut", 11, 0, 0, "Add a cut before the label (useful in chain mode for cuts with minimal waste)", 2},
{ "newline", 'n', "<text>", 0, "Add text in a new line (up to 4 lines). \\n will be replaced by a newline", 2},
{ "align", 'a', "<l|c|r>", 0, "Align text (when printing multiple lines)", 2},
{ 0, 0, 0, 0, "other commands:", 3},
{ "info", 20, 0, 0, "Show info about detected tape", 3},
{ "list-supported", 21, 0, 0, "Show printers supported by this version", 3},
{ "list-connected", 22, 0, 0, "Show connected printers and their USB serial numbers (for --serial)", 3},
{ 0 }
};
static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };
static struct argp argp = { options, parse_opt, NULL, doc, NULL, NULL, NULL };
struct arguments arguments = {
.align = ALIGN_LEFT,
.chain = false,
.copies = 1,
.debug = false,
@@ -115,12 +143,31 @@ struct arguments arguments = {
.font_size = 0,
.forced_tape_width = 0,
.save_png = NULL,
.verbose = 0
.verbose = 0,
.timeout = -1, /* -1 = not given; 0 is already "infinity" */
.serial = NULL
};
job_t *jobs = NULL;
job_t *last_added_job = NULL;
/* --------------------------------------------------------------------
-------------------------------------------------------------------- */
char * gdImageStringFT_180dpi(gdImagePtr im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string)
{
gdFTStringExtra extra;
memset(&extra, 0, sizeof(gdFTStringExtra));
extra.flags = gdFTEX_RESOLUTION;
extra.hdpi = 180;
extra.vdpi = 180;
return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, &extra);
}
/* --------------------------------------------------------------------
-------------------------------------------------------------------- */
@@ -135,7 +182,7 @@ void rasterline_setpixel(uint8_t* rasterline, size_t size, int pixel)
return;
}
int print_img(ptouch_dev ptdev, gdImage *im, int chain)
int print_img(ptouch_dev ptdev, gdImage *im, int chain, int precut)
{
uint8_t rasterline[(ptdev->devinfo->max_px)/8];
@@ -153,7 +200,13 @@ int print_img(ptouch_dev ptdev, gdImage *im, int chain)
return -1;
}
printf(_("image size (%ipx x %ipx)\n"), gdImageSX(im), gdImageSY(im));
int offset = ((int)max_pixels / 2) - (gdImageSY(im)/2); /* always print centered */
int offset = ((int)max_pixels / 2) - (gdImageSY(im)/2); /* center within the printhead */
/* Some models do not center the print area on the printhead. pin_offset
is a fixed per-device shift (in pins/px, constant across tape widths)
that corrects for this; it is 0 where centering is already correct.
See the Brother "Software Developer's Manual - Raster Command
Reference, PT-P900/P900W/P950NW", section 2.3.5 "Raster line". */
offset += ptdev->devinfo->pin_offset;
printf("max_pixels=%ld, offset=%d\n", max_pixels, offset);
if ((ptdev->devinfo->flags & FLAG_RASTER_PACKBITS) == FLAG_RASTER_PACKBITS) {
if (arguments.debug) {
@@ -178,11 +231,13 @@ int print_img(ptouch_dev ptdev, gdImage *im, int chain)
}
}
if ((ptdev->devinfo->flags & FLAG_HAS_PRECUT) == FLAG_HAS_PRECUT) {
if (precut) {
ptouch_send_precut_cmd(ptdev, 1);
if (arguments.debug) {
printf(_("send precut command\n"));
}
}
}
/* send chain command after precut, to allow precutting before chain */
if ((ptdev->devinfo->flags & FLAG_D460BT_MAGIC) == FLAG_D460BT_MAGIC) {
if (chain) {
@@ -254,6 +309,7 @@ int write_png(gdImage *im, const char *file)
}
gdImagePng(im, f);
fclose(f);
printf(_("printing '%s' requires %.1f mm of tape\n"), file, (float)gdImageSX(im) / gdImageResolutionX(im) * 25.4);
return 0;
}
@@ -265,16 +321,20 @@ int get_baselineoffset(char *text, char *font, int fsz)
{
int brect[8];
/* NOTE: This assumes that 'o' is always on the baseline */
gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, "o");
int o_offset = brect[1];
gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text);
/* NOTE: This assumes that 'z' is on the baseline for the selected font.
'z' was choosen instead of 'o' because letters withstraight baseline
are the better choice for the majority of fonts here.
If this makes problems with non-latin fonts with lots of vertically
protruding serifs or decorations, change 'z' to 'o' */
gdImageStringFT_180dpi(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, "z");
int z_offset = brect[1];
gdImageStringFT_180dpi(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text);
int text_offset = brect[1];
if (arguments.debug) {
printf(_("debug: o baseline offset - %d\n"), o_offset);
printf(_("debug: z baseline offset - %d\n"), z_offset);
printf(_("debug: text baseline offset - %d\n"), text_offset);
}
return text_offset-o_offset;
return text_offset-z_offset;
}
/* --------------------------------------------------------------------
@@ -284,11 +344,22 @@ int get_baselineoffset(char *text, char *font, int fsz)
-------------------------------------------------------------------- */
int find_fontsize(int want_px, char *font, char *text)
{
// stabilize font size determination by always accounting for common ascenders and descenders
const char *common_chars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnoprqstuvwxyz{|}~";
char *combined_text = (char *)malloc(strlen(text) + strlen(common_chars) + 1);
if (!combined_text) {
fprintf(stderr, "Memory allocation failed\n");
return -1;
}
strcpy(combined_text, text);
strcat(combined_text, common_chars);
int save = 0;
int brect[8];
for (int i=4; ; ++i) {
if (gdImageStringFT(NULL, &brect[0], -1, font, i, 0.0, 0, 0, text) != NULL) {
if (gdImageStringFT_180dpi(NULL, &brect[0], -1, font, i, 0.0, 0, 0, combined_text) != NULL) {
break;
}
if (brect[1]-brect[5] <= want_px) {
@@ -297,6 +368,9 @@ int find_fontsize(int want_px, char *font, char *text)
break;
}
}
free(combined_text);
if (save == 0) {
return -1;
}
@@ -307,7 +381,7 @@ int needed_width(char *text, char *font, int fsz)
{
int brect[8];
if (gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text) != NULL) {
if (gdImageStringFT_180dpi(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text) != NULL) {
return -1;
}
return brect[2]-brect[0];
@@ -317,7 +391,7 @@ int offset_x(char *text, char *font, int fsz)
{
int brect[8];
if (gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text) != NULL) {
if (gdImageStringFT_180dpi(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text) != NULL) {
return -1;
}
return -brect[0];
@@ -331,7 +405,7 @@ gdImage *render_text(char *font, char *line[], int lines, int print_width)
gdImage *im = NULL;
if (arguments.debug) {
printf(_("render_text(): %i lines, font = '%s'\n"), lines, font);
printf(_("render_text(): %i lines, font = '%s', align = '%c'\n"), lines, font, arguments.align);
}
if (gdFTUseFontConfig(1) != GD_TRUE) {
printf(_("warning: font config not available\n"));
@@ -339,9 +413,12 @@ gdImage *render_text(char *font, char *line[], int lines, int print_width)
if (arguments.font_size > 0) {
fsz = arguments.font_size;
printf(_("setting font size=%i\n"), fsz);
if (arguments.font_margin > 0) {
printf(_("ignoring setting font margin=%i\n"), arguments.font_margin);
}
} else {
for (i = 0; i < lines; ++i) {
if ((tmp = find_fontsize(print_width/lines, font, line[i])) < 0) {
if ((tmp = find_fontsize((print_width-2*arguments.font_margin)/lines, font, line[i])) < 0) {
printf(_("could not estimate needed font size\n"));
return NULL;
}
@@ -360,12 +437,12 @@ gdImage *render_text(char *font, char *line[], int lines, int print_width)
im = gdImageCreatePalette(x, print_width);
gdImageColorAllocate(im, 255, 255, 255);
black = gdImageColorAllocate(im, 0, 0, 0);
/* gdImageStringFT(im,brect,fg,fontlist,size,angle,x,y,string) */
/* gdImageStringFT_180dpi(im,brect,fg,fontlist,size,angle,x,y,string) */
/* find max needed line height for ALL lines */
int max_height=0;
for (i = 0; i < lines; ++i) {
if ((p = gdImageStringFT(NULL, &brect[0], -black, font, fsz, 0.0, 0, 0, line[i])) != NULL) {
printf(_("error in gdImageStringFT: %s\n"), p);
if ((p = gdImageStringFT_180dpi(NULL, &brect[0], -black, font, fsz, 0.0, 0, 0, line[i])) != NULL) {
printf(_("error in gdImageStringFT_180dpi: %s\n"), p);
}
//int ofs = get_baselineoffset(line[i], font_file, fsz);
int lineheight = brect[1]-brect[5];
@@ -392,8 +469,14 @@ gdImage *render_text(char *font, char *line[], int lines, int print_width)
printf("debug: line %i pos=%i ofs=%i\n", i+1, pos, ofs);
}
int off_x = offset_x(line[i], arguments.font_file, fsz);
if ((p = gdImageStringFT(im, &brect[0], -black, font, fsz, 0.0, off_x, pos, line[i])) != NULL) {
printf(_("error in gdImageStringFT: %s\n"), p);
int align_ofs = 0;
if (arguments.align == ALIGN_CENTER) {
align_ofs = (x - needed_width(line[i], arguments.font_file, fsz)) / 2;
} else if (arguments.align == ALIGN_RIGHT) {
align_ofs = x - needed_width(line[i], arguments.font_file, fsz);
}
if ((p = gdImageStringFT_180dpi(im, &brect[0], -black, font, fsz, 0.0, off_x + align_ofs, pos, line[i])) != NULL) {
printf(_("error in gdImageStringFT_180dpi: %s\n"), p);
}
}
return im;
@@ -509,6 +592,58 @@ void add_job(job_type_t type, int n, char *line)
last_added_job = new_job;
}
void add_text(struct argp_state *state, char *arg, bool new_job)
{
char *p = arg;
bool first_part = true;
do {
char *next1 = strstr(p, "\\n");
char *next2 = strchr(p, '\n');
char *next = NULL;
char *p_next = NULL;
int skip = 0;
if (next1 && next2) {
if (next1 < next2) {
next = next1;
skip = 2;
} else {
next = next2;
skip = 1;
}
} else if (next1) {
next = next1;
skip = 2;
} else if (next2) {
next = next2;
skip = 1;
}
if (next) {
*next = '\0';
p_next = next + skip;
} else {
p_next = NULL;
}
if (new_job && first_part) {
add_job(JOB_TEXT, 1, p);
} else {
if (!last_added_job || last_added_job->type != JOB_TEXT) {
add_job(JOB_TEXT, 1, p);
} else {
if (last_added_job->n >= MAX_LINES) {
argp_failure(state, 1, EINVAL, _("Only up to %d lines are supported"), MAX_LINES);
return;
}
last_added_job->lines[last_added_job->n++] = p;
}
}
p = p_next;
first_part = false;
} while (p);
}
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments *arguments = (struct arguments *)state->input;
@@ -523,20 +658,27 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 3: // fontsize
arguments->font_size = strtol(arg, NULL, 10);
break;
case 4: // writepng
case 4: // fontmargin
arguments->font_margin = strtol(arg, NULL, 10);
break;
case 'w': // write-png
arguments->save_png = arg;
break;
case 5: // force-tape-width
case 6: // force-tape-width
arguments->forced_tape_width = strtol(arg, NULL, 10);
break;
case 6: // copies
case 7: // copies
arguments->copies = strtol(arg, NULL, 10);
break;
case 8: // timeout
arguments->timeout = strtol(arg, NULL, 10);
break;
case 'i': // image
add_job(JOB_IMAGE, 1, arg);
break;
case 't': // text
add_job(JOB_TEXT, 1, arg);
//printf("adding text job with alignment %i\n", arguments->align);
add_text(state, arg, true);
break;
case 'c': // cutmark
add_job(JOB_CUTMARK, 0, NULL);
@@ -547,18 +689,26 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 10: // chain
arguments->chain = true;
break;
case 11: // precut
arguments->precut = true;
break;
case 12: // serial
arguments->serial = arg;
break;
case 'a': // align
if ((strcmp(arg, "c") == 0) || (strcmp(arg, "center") == 0)) {
arguments->align = ALIGN_CENTER;
} else if ((strcmp(arg, "r") == 0) || (strcmp(arg, "right") == 0)) {
arguments->align = ALIGN_RIGHT;
} else if ((strcmp(arg, "l") == 0) || (strcmp(arg, "left") == 0)) {
arguments->align = ALIGN_LEFT;
} else {
printf("unknown alignment, defaulting to left\n");
arguments->align = ALIGN_LEFT;
}
break;
case 'n': // newline
if (!last_added_job || last_added_job->type != JOB_TEXT) {
add_job(JOB_TEXT, 1, arg);
break;
}
if (last_added_job->n >= MAX_LINES) { // max number of lines reached
argp_failure(state, 1, EINVAL, _("Only up to %d lines are supported"), MAX_LINES);
break;
}
last_added_job->lines[last_added_job->n++] = arg;
add_text(state, arg, false);
break;
case 20: // info
arguments->info = true;
@@ -566,6 +716,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 21: // list-supported
ptouch_list_supported();
exit(0);
case 22: { // list-connected
int n = ptouch_list_connected();
if (n == 0) {
fprintf(stderr, _("No P-Touch printer found on USB (remember to put switch to position E)\n"));
}
exit(n > 0 ? 0 : 5);
}
case ARGP_KEY_ARG:
argp_failure(state, 1, E2BIG, _("No arguments supported"));
break;
@@ -602,13 +759,19 @@ int main(int argc, char *argv[])
argp_parse(&argp, argc, argv, 0, 0, &arguments);
if (!arguments.forced_tape_width) {
if ((ptouch_open(&ptdev)) < 0) {
if ((ptouch_open_serial(&ptdev, arguments.serial)) < 0) {
return 5;
}
if (ptouch_init(ptdev) != 0) {
printf(_("ptouch_init() failed\n"));
}
if (ptouch_getstatus(ptdev) != 0) {
/* Resolve the timeout only now, because it can depend on which
printer answered. An explicit --timeout always wins. */
if (arguments.timeout < 0) {
arguments.timeout = ptdev->devinfo->min_timeout > 0
? ptdev->devinfo->min_timeout : 1;
}
if (ptouch_getstatus(ptdev, arguments.timeout) != 0) {
printf(_("ptouch_getstatus() failed\n"));
return 1;
}
@@ -623,13 +786,13 @@ int main(int argc, char *argv[])
}
if (arguments.info) {
printf(_("maximum printing width for this printer is %ldpx\n"), ptouch_get_max_width(ptdev));
printf(_("printer has %d dpi, maximum printing width is %ld px\n"), ptouch_get_dpi(ptdev), ptouch_get_max_width(ptdev));
printf(_("maximum printing width for this tape is %ldpx\n"), ptouch_get_tape_width(ptdev));
printf("media type = %02x (%s)\n", ptdev->status->media_type, pt_mediatype(ptdev->status->media_type));
printf("media type = 0x%02x (%s)\n", ptdev->status->media_type, pt_mediatype(ptdev->status->media_type));
printf("media width = %d mm\n", ptdev->status->media_width);
printf("tape color = %02x (%s)\n", ptdev->status->tape_color, pt_tapecolor(ptdev->status->tape_color));
printf("text color = %02x (%s)\n", ptdev->status->text_color, pt_textcolor(ptdev->status->text_color));
printf("error = %04x\n", ptdev->status->error);
printf("tape color = 0x%02x (%s)\n", ptdev->status->tape_color, pt_tapecolor(ptdev->status->tape_color));
printf("text color = 0x%02x (%s)\n", ptdev->status->text_color, pt_textcolor(ptdev->status->text_color));
printf("error = 0x%04x\n", ptdev->status->error);
if (arguments.debug) {
ptouch_rawstatus((uint8_t *)ptdev->status);
}
@@ -692,10 +855,12 @@ int main(int argc, char *argv[])
if (out) {
if (arguments.save_png) {
int dpi = ptouch_get_dpi(ptdev);
gdImageSetResolution(out, dpi, dpi);
write_png(out, arguments.save_png);
} else {
for (int i = 0; i < arguments.copies; ++i) {
print_img(ptdev, out, arguments.chain);
print_img(ptdev, out, arguments.chain, arguments.precut);
if (ptouch_finalize(ptdev, ( arguments.chain || (i < arguments.copies-1) ) ) != 0) {
printf(_("ptouch_finalize(%d) failed\n"), arguments.chain);
return 2;
+9
View File
@@ -1,4 +1,6 @@
# Enable non-root access for known ptouch printers
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2001", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2002", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2004", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2007", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2011", MODE="0660", TAG+="uaccess"
@@ -6,15 +8,22 @@ SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2019", MODE=
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "201f", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "202c", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "202d", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2030", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2031", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2041", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "205e", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "205f", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2060", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2061", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2062", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2064", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2065", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2073", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2074", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2085", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "20af", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "20df", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "20e0", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "20e1", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2201", MODE="0660", TAG+="uaccess"
SUBSYSTEM == "usb", ATTRS{idVendor} == "04f9", ATTRS{idProduct} == "2203", MODE="0660", TAG+="uaccess"