SVG印刷対応とメディア情報APIを追加

SVG入力を現在テープ幅に自動フィットして印刷できるようにし、アプリ側が余白計算できるようにテープ幅・DPI・最小送り量を取得するAPIを追加する。

Made-with: Cursor
This commit is contained in:
knb
2026-04-14 18:29:24 +09:00
parent f26a1186a3
commit 2ed0bfc0be
10 changed files with 539 additions and 43 deletions

View File

@@ -21,14 +21,15 @@ static void usage(const char *argv0)
" -f, --file PATH 入力ファイル\n"
" -w, --width DOTS 1bit ラスター時: 幅(ドット)\n"
" -H, --height DOTS 1bit ラスター時: 高さ(ドット)\n"
" -t, --threshold N PNG 二値化しきい値 0255既定 %u、PNG のみ\n"
" -t, --threshold N 二値化しきい値 0255既定 %u、PNG/SVG\n"
" -n, --dry-run 読み込みと check_raster のみUSB なし)\n"
" -p, --pid HEX USB 製品 ID既定: P900W の 0x2085。例: P750W 0x2062、P710BT 0x20af\n"
" -S, --status USB 接続プリンタのステータス(テープ種・幅・色等)を表示して終了\n"
" -V, --version バージョンを表示して終了\n"
" -h, --help このヘルプ\n"
"\n"
"PNG の場合は幅・高さはファイルから取得(-w/-H 不要)。\n"
"PNG は幅・高さを画像から取得(-w/-H 不要)。\n"
"SVG は現在テープの印字可能幅に合わせて自動拡大・縮小USB 必須)。\n"
"1bit packed ラスター(行優先)の場合は -f -w -H が必須。\n"
"--status のときは -f は不要(他オプションは無視されます)。\n",
argv0, (unsigned)LIBPTOUCH_PNG_DEFAULT_THRESHOLD);
@@ -54,6 +55,14 @@ static int input_is_png(const char *path)
return memcmp(sig, png_magic, sizeof(png_magic)) == 0;
}
static int input_is_svg(const char *path)
{
const char *dot = strrchr(path, '.');
if (dot && strcasecmp(dot, ".svg") == 0)
return 1;
return 0;
}
static int read_file(const char *path, uint8_t **out, size_t *out_len)
{
FILE *fp = fopen(path, "rb");
@@ -201,20 +210,21 @@ int main(int argc, char **argv)
}
int png = input_is_png(file);
if (png) {
int svg = input_is_svg(file);
if (png || svg) {
if (width != 0 || height != 0)
fprintf(stderr,
"warning: -w/-H ignored for PNG (using image size)\n");
"warning: -w/-H ignored for image inputs\n");
} else {
if (width == 0 || height == 0) {
fprintf(stderr,
"1bit raster requires -w and -H (or use a PNG file)\n");
"1bit raster requires -w and -H (or use a PNG/SVG file)\n");
usage(argv[0]);
return 2;
}
if (has_threshold)
fprintf(stderr,
"warning: -t applies to PNG only (ignored)\n");
"warning: -t applies to PNG/SVG only (ignored)\n");
}
libptouch_ctx *ctx = libptouch_create();
@@ -227,6 +237,7 @@ int main(int argc, char **argv)
size_t data_len = 0;
libptouch_raster_params_t params = { 0, 0, 0 };
libptouch_err_t e;
int usb_opened = 0;
if (png) {
libptouch_png_options_t opt = { .threshold = (uint8_t)threshold };
@@ -239,6 +250,28 @@ int main(int argc, char **argv)
libptouch_destroy(ctx);
return 1;
}
} else if (svg) {
e = usb_pid_arg != 0
? libptouch_open_usb_vid_pid(ctx, LIBPTOUCH_USB_VID_BROTHER,
(uint16_t)usb_pid_arg)
: libptouch_open_usb(ctx);
if (e != LIBPTOUCH_OK) {
fprintf(stderr, "open_usb: %s\n", libptouch_strerror(ctx));
libptouch_destroy(ctx);
return 1;
}
usb_opened = 1;
libptouch_svg_options_t opt = { .threshold = (uint8_t)threshold };
e = libptouch_svg_file_to_raster_fit_current_tape(
ctx, file, has_threshold ? &opt : NULL, &data, &data_len,
&params);
if (e != LIBPTOUCH_OK) {
fprintf(stderr, "svg_file_to_raster_fit_current_tape: %s\n",
libptouch_strerror(ctx));
libptouch_close(ctx);
libptouch_destroy(ctx);
return 1;
}
} else {
if (read_file(file, &data, &data_len) != 0) {
libptouch_destroy(ctx);
@@ -254,7 +287,7 @@ int main(int argc, char **argv)
fprintf(stderr, "check_raster: %s\n",
libptouch_strerror(ctx));
libptouch_destroy(ctx);
if (png)
if (png || svg)
libptouch_free_raster(data);
else
free(data);
@@ -262,29 +295,36 @@ int main(int argc, char **argv)
}
if (dry_run) {
printf("dry-run OK: %zu bytes, %ux%u dots\n", data_len,
printf("dry-run OK: %zu bytes, src %ux%u dots (print lengthxwidth %ux%u)\n",
data_len,
(unsigned)params.width_dots,
(unsigned)params.height_dots,
(unsigned)params.width_dots,
(unsigned)params.height_dots);
if (usb_opened)
libptouch_close(ctx);
libptouch_destroy(ctx);
if (png)
if (png || svg)
libptouch_free_raster(data);
else
free(data);
return 0;
}
e = usb_pid_arg != 0
? libptouch_open_usb_vid_pid(ctx, LIBPTOUCH_USB_VID_BROTHER,
(uint16_t)usb_pid_arg)
: libptouch_open_usb(ctx);
if (e != LIBPTOUCH_OK) {
fprintf(stderr, "open_usb: %s\n", libptouch_strerror(ctx));
libptouch_destroy(ctx);
if (png)
libptouch_free_raster(data);
else
free(data);
return 1;
if (!usb_opened) {
e = usb_pid_arg != 0
? libptouch_open_usb_vid_pid(ctx, LIBPTOUCH_USB_VID_BROTHER,
(uint16_t)usb_pid_arg)
: libptouch_open_usb(ctx);
if (e != LIBPTOUCH_OK) {
fprintf(stderr, "open_usb: %s\n", libptouch_strerror(ctx));
libptouch_destroy(ctx);
if (png || svg)
libptouch_free_raster(data);
else
free(data);
return 1;
}
}
e = libptouch_print_raster(ctx, data, data_len, &params);
@@ -293,7 +333,7 @@ int main(int argc, char **argv)
libptouch_strerror(ctx));
libptouch_close(ctx);
libptouch_destroy(ctx);
if (png)
if (png || svg)
libptouch_free_raster(data);
else
free(data);
@@ -302,7 +342,7 @@ int main(int argc, char **argv)
libptouch_close(ctx);
libptouch_destroy(ctx);
if (png)
if (png || svg)
libptouch_free_raster(data);
else
free(data);