libptouch を複数ソースに分割し src/lib に配置

- core / usb / print / status / png と libptouch_internal.h に分割
- 旧単一ファイル src/libptouch.c を削除
- CMake のソース一覧と include パスを更新
- README・libptouch.h の参照パスを追随

Made-with: Cursor
This commit is contained in:
knb
2026-04-13 09:43:33 +09:00
parent fdcb4d97fa
commit add08ba9b2
10 changed files with 1244 additions and 1169 deletions

296
src/lib/libptouch_print.c Normal file
View File

@@ -0,0 +1,296 @@
/*
* libptouch — raster layout, transpose, P-touch print job (ESC/P bulk)
*
* Author: knb
* Email: knb@artif.org
*/
#include "libptouch_internal.h"
#include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* cv_ptp900_jpn_raster_102.pdf: テープ幅から印刷可能ドット */
static libptouch_err_t layout_from_status(uint8_t media_kind, uint8_t media_wbyte,
uint16_t *left, uint16_t *print_dots,
uint16_t *right)
{
if (media_kind == 0x11u || media_kind == 0x17u) {
switch (media_wbyte) {
case 0x06:
*left = 244;
*print_dots = 56;
*right = 260;
return LIBPTOUCH_OK;
case 0x09:
*left = 224;
*print_dots = 96;
*right = 240;
return LIBPTOUCH_OK;
case 0x0C:
*left = 206;
*print_dots = 132;
*right = 222;
return LIBPTOUCH_OK;
case 0x12:
*left = 166;
*print_dots = 212;
*right = 182;
return LIBPTOUCH_OK;
case 0x18:
*left = 144;
*print_dots = 256;
*right = 160;
return LIBPTOUCH_OK;
default:
break;
}
}
switch (media_wbyte) {
case 0x04:
*left = 248;
*print_dots = 48;
*right = 264;
return LIBPTOUCH_OK;
case 0x06:
*left = 240;
*print_dots = 64;
*right = 256;
return LIBPTOUCH_OK;
case 0x09:
*left = 219;
*print_dots = 106;
*right = 235;
return LIBPTOUCH_OK;
case 0x0C:
*left = 197;
*print_dots = 150;
*right = 213;
return LIBPTOUCH_OK;
case 0x12:
*left = 155;
*print_dots = 234;
*right = 171;
return LIBPTOUCH_OK;
case 0x18:
*left = 112;
*print_dots = 320;
*right = 128;
return LIBPTOUCH_OK;
case 0x24:
*left = 45;
*print_dots = 454;
*right = 61;
return LIBPTOUCH_OK;
default:
break;
}
(void)media_kind;
return LIBPTOUCH_ERR_UNSUPPORTED;
}
/* cv_ptp900_jpn_raster_102.pdf: 2.3.5 ラスターライン(全 560 ドット = 70 バイト) */
static void pack_line_560(uint8_t line[70], const uint8_t *row, uint32_t width_dots,
uint16_t left_dots, uint16_t print_dots)
{
memset(line, 0, 70u);
if (width_dots > (uint32_t)print_dots)
return;
uint32_t start = (uint32_t)left_dots +
((uint32_t)print_dots - width_dots) / 2u;
for (uint32_t x = 0; x < width_dots; x++) {
uint32_t ubyte = x / 8u;
uint32_t ubit = 7u - (x % 8u);
if (((row[ubyte] >> ubit) & 1u) == 0)
continue;
uint32_t dot = start + x;
if (dot >= 560u)
break;
uint32_t b = dot / 8u;
uint32_t bi = 7u - (dot % 8u);
line[b] |= (uint8_t)(1u << bi);
}
}
static uint8_t *transpose_raster_alloc(const uint8_t *in, uint32_t W, uint32_t H,
uint32_t *outW, uint32_t *outH)
{
*outW = H;
*outH = W;
size_t old_rb = (W + 7u) / 8u;
size_t new_rb = (H + 7u) / 8u;
uint8_t *out = (uint8_t *)calloc(new_rb * W, 1);
if (!out)
return NULL;
for (uint32_t y = 0; y < H; y++) {
for (uint32_t x = 0; x < W; x++) {
size_t ob = (size_t)y * old_rb + x / 8u;
int bit = (int)((in[ob] >> (7u - x % 8u)) & 1u);
if (!bit)
continue;
uint32_t nx = y;
uint32_t ny = x;
size_t nb = (size_t)ny * new_rb + nx / 8u;
out[nb] |= (uint8_t)(1u << (7u - nx % 8u));
}
}
return out;
}
libptouch_err_t libptouch_print_raster(libptouch_ctx *ctx,
const uint8_t *data, size_t data_len,
const libptouch_raster_params_t *params)
{
libptouch_err_t v =
libptouch_check_raster(ctx, data, data_len, params);
if (v != LIBPTOUCH_OK)
return v;
if (!ctx->usb_open || !ctx->bulk_out_ep) {
ptouch_set_error(ctx, LIBPTOUCH_ERR_IO, "not connected");
return LIBPTOUCH_ERR_IO;
}
uint8_t st[LIBPTOUCH_STATUS_LENGTH];
v = libptouch_get_status(ctx, st);
if (v != LIBPTOUCH_OK)
return v;
uint8_t media_kind = st[11];
uint8_t media_w = st[10];
uint16_t left_dots, print_dots, right_dots;
v = layout_from_status(media_kind, media_w, &left_dots, &print_dots,
&right_dots);
if (v != LIBPTOUCH_OK) {
ptouch_set_error(ctx, LIBPTOUCH_ERR_UNSUPPORTED,
"tape width/layout not supported for this media "
"(check status media bytes)");
return LIBPTOUCH_ERR_UNSUPPORTED;
}
(void)right_dots;
uint32_t wd = params->width_dots;
uint32_t ht = params->height_dots;
uint8_t *transposed = transpose_raster_alloc(data, wd, ht, &wd, &ht);
if (!transposed) {
ptouch_set_error(ctx, LIBPTOUCH_ERR_NOMEM,
"transpose raster: out of memory");
return LIBPTOUCH_ERR_NOMEM;
}
const uint8_t *src = transposed;
if (wd > (uint32_t)print_dots) {
char buf[160];
snprintf(buf, sizeof(buf),
"image width %u dots > printable %u for loaded tape",
(unsigned)wd, (unsigned)print_dots);
ptouch_set_error(ctx, LIBPTOUCH_ERR_ARG, buf);
free(transposed);
return LIBPTOUCH_ERR_ARG;
}
unsigned margin_dots = 14u;
if (params->margin_mm > 0) {
margin_dots = (unsigned)((double)params->margin_mm * 360.0 /
25.4 +
0.5);
if (margin_dots < 14u)
margin_dots = 14u;
if (margin_dots > 1800u)
margin_dots = 1800u;
}
uint32_t lines = ht;
uint8_t n5 = (uint8_t)(lines & 0xFFu);
uint8_t n6 = (uint8_t)((lines >> 8) & 0xFFu);
uint8_t n7 = (uint8_t)((lines >> 16) & 0xFFu);
uint8_t n8 = (uint8_t)((lines >> 24) & 0xFFu);
uint8_t n2_paper = 0x09u;
if (media_kind == 0x03u)
n2_paper = 0x00u;
else if (media_kind == 0x11u)
n2_paper = 0x11u;
else if (media_kind == 0x17u)
n2_paper = 0x17u;
else if (media_kind == 0x13u)
n2_paper = 0x13u;
uint8_t head[256];
size_t pos = 0;
memset(head + pos, 0, 200);
pos += 200u;
static const uint8_t esc_at[] = { 0x1B, 0x40 };
memcpy(head + pos, esc_at, sizeof(esc_at));
pos += sizeof(esc_at);
static const uint8_t raster_mode[] = { 0x1B, 0x69, 0x61, 0x01 };
memcpy(head + pos, raster_mode, sizeof(raster_mode));
pos += sizeof(raster_mode);
uint8_t esc_iz[] = { 0x1B, 0x69, 0x7A, 0x0Eu, n2_paper, media_w,
0x00u, n5, n6, n7, n8, 0x02u, 0x00u };
memcpy(head + pos, esc_iz, sizeof(esc_iz));
pos += sizeof(esc_iz);
static const uint8_t esc_im[] = { 0x1B, 0x69, 0x4D, 0x40 };
memcpy(head + pos, esc_im, sizeof(esc_im));
pos += sizeof(esc_im);
static const uint8_t esc_ia[] = { 0x1B, 0x69, 0x41, 0x01 };
memcpy(head + pos, esc_ia, sizeof(esc_ia));
pos += sizeof(esc_ia);
static const uint8_t esc_ik[] = { 0x1B, 0x69, 0x4B, 0x0C };
memcpy(head + pos, esc_ik, sizeof(esc_ik));
pos += sizeof(esc_ik);
uint8_t esc_id[] = {
0x1B, 0x69, 0x64,
(uint8_t)(margin_dots & 0xFFu),
(uint8_t)((margin_dots >> 8) & 0xFFu)
};
memcpy(head + pos, esc_id, sizeof(esc_id));
pos += sizeof(esc_id);
static const uint8_t mode_m[] = { 0x4D, 0x00 };
memcpy(head + pos, mode_m, sizeof(mode_m));
pos += sizeof(mode_m);
v = ptouch_bulk_send_job(ctx, head, pos, "print preamble");
if (v != LIBPTOUCH_OK) {
free(transposed);
return v;
}
size_t row_b = ((size_t)wd + 7u) / 8u;
uint8_t gbuf[73];
static const uint8_t g_hdr[] = { 0x47, 0x46, 0x00 };
for (uint32_t y = 0; y < lines; y++) {
const uint8_t *row = src + (size_t)y * row_b;
pack_line_560(gbuf + 3, row, wd, left_dots, print_dots);
memcpy(gbuf, g_hdr, sizeof(g_hdr));
v = ptouch_bulk_send_job(ctx, gbuf, sizeof(gbuf), "raster line");
if (v != LIBPTOUCH_OK) {
free(transposed);
return v;
}
}
static const uint8_t print_end[] = { 0x1A };
v = ptouch_bulk_send_job(ctx, print_end, sizeof(print_end), "print end");
if (v != LIBPTOUCH_OK) {
free(transposed);
return v;
}
uint8_t sink[64];
int tr = 0;
(void)libusb_bulk_transfer(ctx->usb_handle, ctx->bulk_in_ep, sink,
(int)sizeof(sink), &tr, 3000);
(void)tr;
free(transposed);
ptouch_set_error(ctx, LIBPTOUCH_OK, "");
return LIBPTOUCH_OK;
}