ptouch-label CLIを追加して差込印刷を拡張

コマンド名を機能に合わせて整理し、SVGテンプレート+JSON/YAMLの差込印刷とメディア情報取得を使いやすくする。

Made-with: Cursor
This commit is contained in:
knb
2026-04-16 14:49:08 +09:00
parent 33465c7299
commit 32ab12f661
12 changed files with 412 additions and 260 deletions

0
reference/note.adoc Normal file
View File

View File

@@ -31,21 +31,25 @@ export LIBPTOUCH_LIB=/usr/local/lib/libptouch.so
`cmake --install` で共有ライブラリをインストールした場合は、通常は `libptouch` 名でローダが解決します。) `cmake --install` で共有ライブラリをインストールした場合は、通常は `libptouch` 名でローダが解決します。)
## コマンド `ptouch-print-png`PNG/SVG ## コマンド `ptouch-label`PNG/SVG
C の `ptouch-print` と同様の流れで、**PNG/SVG 入力**`-w`/`-H` や 1bit ラスターは扱いません)を扱います。`gem install` 後は PATH に `ptouch-print-png` が入ります。 C の `ptouch-print` と同様の流れで、**PNG/SVG 入力**`-w`/`-H` や 1bit ラスターは扱いません)を扱います。`gem install` 後は PATH に `ptouch-label` が入ります。
SVG は現在装着テープの印字可能幅に合わせて自動拡大・縮小しますUSB 接続が必要)。 SVG は現在装着テープの印字可能幅に合わせて自動拡大・縮小しますUSB 接続が必要)。
後方互換のため `ptouch-print-png` も引き続き使えます。
オプションは C 側に合わせ、**`-p` / `--pid`** で USB 製品 ID16 進可)を指定できます。省略時は PT-P900W`Libptouch::USB_PID_PTP900W` = `0x2085`)。例: PT-P750W `0x2062`、PT-P710BT `0x20af``libptouch.h` / `Libptouch` 定数と同じ)。 オプションは C 側に合わせ、**`-p` / `--pid`** で USB 製品 ID16 進可)を指定できます。省略時は PT-P900W`Libptouch::USB_PID_PTP900W` = `0x2085`)。例: PT-P750W `0x2062`、PT-P710BT `0x20af``libptouch.h` / `Libptouch` 定数と同じ)。
また、`--template`SVGと `--data`JSON/YAMLを使うと `data-field` 属性をキーにした差込印刷が可能です。
開発ツリーからそのまま試す例: 開発ツリーからそのまま試す例:
```bash ```bash
bundle exec ruby -I lib exe/ptouch-print-png --help bundle exec ruby -I lib exe/ptouch-label --help
bundle exec ruby -I lib exe/ptouch-print-png -n -f ../samples/your.png bundle exec ruby -I lib exe/ptouch-label -n -f ../samples/your.png
bundle exec ruby -I lib exe/ptouch-print-png -n -f ../samples/your.svg bundle exec ruby -I lib exe/ptouch-label -n -f ../samples/your.svg
bundle exec ruby -I lib exe/ptouch-print-png --status -p 0x2062 bundle exec ruby -I lib exe/ptouch-label -n --template ../samples/your_template.svg --data ../samples/your_data.yml
bundle exec ruby -I lib exe/ptouch-print-png -f ../samples/your.png -p 0x20af bundle exec ruby -I lib exe/ptouch-label --media-info
bundle exec ruby -I lib exe/ptouch-label --status -p 0x2062
bundle exec ruby -I lib exe/ptouch-label -f ../samples/your.png -p 0x20af
``` ```
## 使用例 ## 使用例
@@ -92,9 +96,9 @@ ctx.dispose
## API の範囲 ## API の範囲
- 実行ファイル `ptouch-print-png` … PNG/SVG`-f`, `-t`, `-p`, `-n`, `-S`, `-V`, `-h`)。ステータスは JSON`status_bytes` を `parse_status` したもの、`raw_bytes` 除く) - 実行ファイル `ptouch-label`(互換: `ptouch-print-png`… PNG/SVG`-f`, `-t`, `-p`, `-n`, `-M`, `-S`, `-V`, `-h`, `--template`, `--data`)。`-M` は現在テープ情報(幅 mm・DPI 等)を JSON 出力、`-S` はステータス JSON 出力
- `Libptouch::Context` … `open_usb` / `open_usb_vid_pid` / `close` / `dispose` - `Libptouch::Context` … `open_usb` / `open_usb_vid_pid` / `close` / `dispose`
- `check_raster` / `print_raster` / `png_file_to_raster` / `svg_file_to_raster_fit_current_tape` / `status_bytes` / `status_hash` / `current_media_info` - `check_raster` / `print_raster` / `png_file_to_raster` / `svg_file_to_raster_fit_current_tape` / `status_bytes` / `status_hash` / `current_media_info`
- `current_media_info` には `print_dpi` / `feed_dpi` / `tape_width_mm` / `min_feed_mm` などを含む - `current_media_info` には `print_dpi` / `feed_dpi` / `tape_width_mm` / `printable_height_dots` / `min_feed_mm` などを含む(テープ幅方向は `printable_height_dots`
- `Libptouch.parse_status(raw)` … 32 バイトを Hash に展開(機種・テープ幅・**テープ種類**・色・**状態status_kind**・エラービット・`raw_hex` など) - `Libptouch.parse_status(raw)` … 32 バイトを Hash に展開(機種・テープ幅・**テープ種類**・色・**状態status_kind**・エラービット・`raw_hex` など)
- C の `libptouch_status_fprint``FILE *`)は FFI からはバインドしていません。テキスト出力の代わりに `parse_status` / `status_hash` を使ってください。 - C の `libptouch_status_fprint``FILE *`)は FFI からはバインドしていません。テキスト出力の代わりに `parse_status` / `status_hash` を使ってください。

6
ruby/exe/ptouch-label Normal file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require "libptouch/cli/label_print"
exit Libptouch::Cli::LabelPrint.run(ARGV)

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# frozen_string_literal: true # frozen_string_literal: true
require "libptouch/cli/png_print" require "libptouch/cli/label_print"
exit Libptouch::Cli::PngPrint.run(ARGV) exit Libptouch::Cli::LabelPrint.run(ARGV)

View File

@@ -0,0 +1,361 @@
# frozen_string_literal: true
require "json"
require "optparse"
require "rexml/document"
require "tempfile"
require "yaml"
require "libptouch"
module Libptouch
module Cli
# PNG/SVG を扱う ptouch-print 相当の CLI1bit ラスター経路なし)。
module LabelPrint
module_function
def run(argv)
opts = parse(argv)
return 2 if opts.nil?
return run_version if opts[:version]
return run_help if opts[:help]
return run_media_info(opts) if opts[:media_info]
if opts[:status]
warn_unused_file_options(opts)
return run_status(opts)
end
if opts[:template] || opts[:data]
return usage_error("--template and --data must be used together") if opts[:template].to_s.empty? || opts[:data].to_s.empty?
return usage_error("-f and --template/--data cannot be used together") unless opts[:file].to_s.empty?
return run_template_print(opts)
end
return usage_error("-f is required (or use --template/--data, or --status)") if opts[:file].to_s.empty?
path = opts[:file]
kind = image_kind(path)
return usage_error("not a PNG/SVG file: #{path}") if kind.nil?
run_print(path, opts, kind)
end
def png_file?(path)
return true if path.downcase.end_with?(".png")
File.open(path, "rb") do |f|
sig = f.read(8)
sig == "\x89PNG\r\n\x1a\n".b
end
rescue Errno::ENOENT, Errno::EACCES => e
warn "open #{path}: #{e.message}"
false
end
def svg_file?(path)
path.downcase.end_with?(".svg")
end
def image_kind(path)
return :png if png_file?(path)
return :svg if svg_file?(path)
nil
end
def parse(argv)
opts_hash = default_cli_opts
build_cli_parser(opts_hash).parse!(argv)
return nil unless threshold_option_ok?(opts_hash)
return nil unless usb_pid_option_ok?(opts_hash)
opts_hash.delete(:usb_pid_invalid)
opts_hash
end
def default_cli_opts
{
file: nil,
template: nil,
data: nil,
threshold: nil,
usb_pid: nil,
usb_pid_invalid: false,
dry_run: false,
media_info: false,
status: false,
version: false,
help: false
}
end
def pid_option_description
p900 = Libptouch::USB_PID_PTP900W
p750 = Libptouch::USB_PID_PTP750W
p710 = Libptouch::USB_PID_PTP710BT
"USB 製品 ID16 進可)。既定 P900W 0x#{p900.to_s(16)}; " \
"P750W 0x#{p750.to_s(16)}; P710BT 0x#{p710.to_s(16)}"
end
def apply_usb_pid_option(opts_hash, pid_str)
opts_hash[:usb_pid] = Integer(pid_str, 0)
rescue ArgumentError
warn "invalid --pid: #{pid_str.inspect}"
opts_hash[:usb_pid_invalid] = true
end
def threshold_option_ok?(opts_hash)
return true if opts_hash[:threshold].nil? || (0..255).cover?(opts_hash[:threshold])
warn "-t must be 0..255"
false
end
def usb_pid_option_ok?(opts_hash)
return false if opts_hash[:usb_pid_invalid]
return true if opts_hash[:usb_pid].nil?
return true if opts_hash[:usb_pid].between?(1, 0xFFFF)
warn "-p/--pid must be 1..0xFFFF"
false
end
def build_cli_parser(opts_hash)
OptionParser.new do |p|
p.banner = usage_banner
p.separator ""
p.on("-f", "--file PATH", "入力 PNG/SVG ファイル") { |v| opts_hash[:file] = v }
p.on("--template PATH", "差込用 SVG テンプレート") { |v| opts_hash[:template] = v }
p.on("--data PATH", "差込データ JSON/YAML ファイル") { |v| opts_hash[:data] = v }
p.on("-t", "--threshold N", Integer,
"二値化しきい値 0255既定 #{Libptouch::PNG_DEFAULT_THRESHOLD}、PNG/SVG") do |v|
opts_hash[:threshold] = v
end
p.on("-p", "--pid PID", pid_option_description) do |v|
apply_usb_pid_option(opts_hash, v)
end
p.on("-n", "--dry-run", "読み込みと検証のみUSB なし)") { opts_hash[:dry_run] = true }
p.on("-M", "--media-info", "現在テープの幅(mm)・DPI・最小余白(mm)を JSON で表示して終了") do
opts_hash[:media_info] = true
end
p.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") do
opts_hash[:status] = true
end
p.on("-V", "--version", "バージョンを表示して終了") { opts_hash[:version] = true }
p.on("-h", "--help", "このヘルプ") { opts_hash[:help] = true }
end
end
def usage_banner
<<~BANNER
Usage: ptouch-label [options]
PNG/SVG -w/-H
--template/--data SVG
SVG USB
--status / --media-info -f
BANNER
end
def warn_unused_file_options(opts)
return unless opts[:file] || opts[:template] || opts[:data] || opts[:dry_run] || !opts[:threshold].nil?
warn "warning: options other than --status are ignored"
end
def run_version
puts "ptouch-label #{Libptouch::VERSION}"
0
end
def run_help
puts usage_banner
puts ""
puts parser_help_text
0
end
def parser_help_text
opts_hash = default_cli_opts
p = OptionParser.new do |parser|
parser.banner = "ptouch-label [options]"
parser.on("-f", "--file PATH", "入力 PNG/SVG ファイル") { |v| opts_hash[:file] = v }
parser.on("--template PATH", "差込用 SVG テンプレート") { |v| opts_hash[:template] = v }
parser.on("--data PATH", "差込データ JSON/YAML ファイル") { |v| opts_hash[:data] = v }
parser.on("-t", "--threshold N", Integer,
"二値化しきい値 0255既定 #{Libptouch::PNG_DEFAULT_THRESHOLD}、PNG/SVG") do |v|
opts_hash[:threshold] = v
end
parser.on("-p", "--pid PID", pid_option_description) do |v|
apply_usb_pid_option(opts_hash, v)
end
parser.on("-n", "--dry-run", "読み込みと検証のみUSB なし)") { opts_hash[:dry_run] = true }
parser.on("-M", "--media-info", "現在テープの幅(mm)・DPI・最小余白(mm)を JSON で表示して終了") do
opts_hash[:media_info] = true
end
parser.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") do
opts_hash[:status] = true
end
parser.on("-V", "--version", "バージョンを表示して終了") { opts_hash[:version] = true }
parser.on("-h", "--help", "このヘルプ") { opts_hash[:help] = true }
end
p.help
end
def open_usb_for_opts(ctx, opts)
if opts[:usb_pid]
ctx.open_usb_vid_pid(Libptouch::USB_VID_BROTHER, opts[:usb_pid])
else
ctx.open_usb
end
end
def run_template_print(opts)
svg_text = render_svg_template(opts[:template], load_merge_data(opts[:data]))
Tempfile.create(["ptouch-merge-", ".svg"]) do |tmp|
tmp.binmode
tmp.write(svg_text)
tmp.flush
run_print(tmp.path, opts, :svg)
end
rescue REXML::ParseException => e
warn "template parse error: #{e.message}"
1
rescue Errno::ENOENT, Errno::EACCES => e
warn e.message
1
rescue JSON::ParserError, Psych::SyntaxError => e
warn "data parse error: #{e.message}"
1
rescue ArgumentError => e
warn "data error: #{e.message}"
1
end
def load_merge_data(path)
text = File.read(path, encoding: "UTF-8")
ext = File.extname(path).downcase
parsed = if ext == ".json"
JSON.parse(text)
else
YAML.safe_load(text, permitted_classes: [], aliases: false)
end
unless parsed.is_a?(Hash)
raise ArgumentError, "data must be a key-value object/hash"
end
parsed.transform_keys(&:to_s)
end
def render_svg_template(path, data)
xml = File.read(path, encoding: "UTF-8")
doc = REXML::Document.new(xml)
doc.elements.each("//text[@data-field]") do |el|
# If descendants also have data-field (e.g. tspan placeholders),
# keep node structure and let element-level replacements handle them.
next if el.elements[".//*[@data-field]"]
key = el.attributes["data-field"].to_s
next unless data.key?(key)
replace_text_element_content(el, data[key].to_s)
end
doc.elements.each("//tspan[@data-field]") do |el|
key = el.attributes["data-field"].to_s
next unless data.key?(key)
replace_text_element_content(el, data[key].to_s)
end
out = +""
formatter = REXML::Formatters::Default.new
formatter.write(doc, out)
out
end
def replace_text_element_content(text_element, value)
# Remove all child nodes first so mixed content (<tspan>, text nodes, etc.)
# gets replaced consistently by merge data.
text_element.children.to_a.each { |child| text_element.delete(child) }
text_element.add(REXML::Text.new(value, true))
end
def run_status(opts)
ctx = nil
begin
ctx = Libptouch::Context.new
open_usb_for_opts(ctx, opts)
h = Libptouch.parse_status(ctx.status_bytes)
h.delete(:raw_bytes)
puts JSON.pretty_generate(h)
0
rescue Libptouch::Error => e
warn "get_status: #{e.message}"
1
ensure
ctx&.dispose
end
end
def run_media_info(opts)
warn_unused_file_options(opts)
ctx = nil
begin
ctx = Libptouch::Context.new
open_usb_for_opts(ctx, opts)
puts JSON.pretty_generate(ctx.current_media_info)
0
rescue Libptouch::Error => e
warn "media_info: #{e.message}"
1
ensure
ctx&.dispose
end
end
def run_print(path, opts, kind)
ctx = nil
begin
ctx = Libptouch::Context.new
threshold = opts[:threshold]
data, width, height = if kind == :svg
open_usb_for_opts(ctx, opts)
if threshold.nil?
ctx.svg_file_to_raster_fit_current_tape(path)
else
ctx.svg_file_to_raster_fit_current_tape(path, threshold: threshold)
end
elsif threshold.nil?
ctx.png_file_to_raster(path)
else
ctx.png_file_to_raster(path, threshold: threshold)
end
ctx.check_raster(data, width_dots: width, height_dots: height)
if opts[:dry_run]
puts "dry-run OK: #{data.bytesize} bytes, src #{width}x#{height} dots (print lengthxwidth #{width}x#{height})"
return 0
end
open_usb_for_opts(ctx, opts) if kind == :png
ctx.print_raster(data, width_dots: width, height_dots: height)
0
rescue Libptouch::Error => e
warn e.message
1
ensure
ctx&.dispose
end
end
def usage_error(msg)
warn msg
warn "(try ptouch-label --help)"
2
end
end
end
end

View File

@@ -1,251 +1,8 @@
# frozen_string_literal: true # Backward-compatibility shim.
require "libptouch/cli/label_print"
require "json"
require "optparse"
require "libptouch"
module Libptouch module Libptouch
module Cli module Cli
# PNG/SVG を扱う ptouch-print 相当の CLI1bit ラスター経路なし)。 PngPrint = LabelPrint
module PngPrint
module_function
def run(argv)
opts = parse(argv)
return 2 if opts.nil?
return run_version if opts[:version]
return run_help if opts[:help]
if opts[:status]
warn_unused_file_options(opts)
return run_status(opts)
end
return usage_error("-f is required (or use --status)") if opts[:file].to_s.empty?
path = opts[:file]
kind = image_kind(path)
return usage_error("not a PNG/SVG file: #{path}") if kind.nil?
run_print(path, opts, kind)
end
def png_file?(path)
return true if path.downcase.end_with?(".png")
File.open(path, "rb") do |f|
sig = f.read(8)
sig == "\x89PNG\r\n\x1a\n".b
end
rescue Errno::ENOENT, Errno::EACCES => e
warn "open #{path}: #{e.message}"
false
end
def svg_file?(path)
path.downcase.end_with?(".svg")
end
def image_kind(path)
return :png if png_file?(path)
return :svg if svg_file?(path)
nil
end
def parse(argv)
opts_hash = default_cli_opts
build_cli_parser(opts_hash).parse!(argv)
return nil unless threshold_option_ok?(opts_hash)
return nil unless usb_pid_option_ok?(opts_hash)
opts_hash.delete(:usb_pid_invalid)
opts_hash
end
def default_cli_opts
{
file: nil,
threshold: nil,
usb_pid: nil,
usb_pid_invalid: false,
dry_run: false,
status: false,
version: false,
help: false
}
end
def pid_option_description
p900 = Libptouch::USB_PID_PTP900W
p750 = Libptouch::USB_PID_PTP750W
p710 = Libptouch::USB_PID_PTP710BT
"USB 製品 ID16 進可)。既定 P900W 0x#{p900.to_s(16)}; " \
"P750W 0x#{p750.to_s(16)}; P710BT 0x#{p710.to_s(16)}"
end
def apply_usb_pid_option(opts_hash, pid_str)
opts_hash[:usb_pid] = Integer(pid_str, 0)
rescue ArgumentError
warn "invalid --pid: #{pid_str.inspect}"
opts_hash[:usb_pid_invalid] = true
end
def threshold_option_ok?(opts_hash)
return true if opts_hash[:threshold].nil? || (0..255).cover?(opts_hash[:threshold])
warn "-t must be 0..255"
false
end
def usb_pid_option_ok?(opts_hash)
return false if opts_hash[:usb_pid_invalid]
return true if opts_hash[:usb_pid].nil?
return true if opts_hash[:usb_pid].between?(1, 0xFFFF)
warn "-p/--pid must be 1..0xFFFF"
false
end
def build_cli_parser(opts_hash)
OptionParser.new do |p|
p.banner = usage_banner
p.separator ""
p.on("-f", "--file PATH", "入力 PNG/SVG ファイル") { |v| opts_hash[:file] = v }
p.on("-t", "--threshold N", Integer,
"二値化しきい値 0255既定 #{Libptouch::PNG_DEFAULT_THRESHOLD}、PNG/SVG") do |v|
opts_hash[:threshold] = v
end
p.on("-p", "--pid PID", pid_option_description) do |v|
apply_usb_pid_option(opts_hash, v)
end
p.on("-n", "--dry-run", "読み込みと検証のみUSB なし)") { opts_hash[:dry_run] = true }
p.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") do
opts_hash[:status] = true
end
p.on("-V", "--version", "バージョンを表示して終了") { opts_hash[:version] = true }
p.on("-h", "--help", "このヘルプ") { opts_hash[:help] = true }
end
end
def usage_banner
<<~BANNER
Usage: ptouch-print-png [options]
PNG/SVG -w/-H
SVG USB
--status -f
BANNER
end
def warn_unused_file_options(opts)
return unless opts[:file] || opts[:dry_run] || !opts[:threshold].nil?
warn "warning: options other than --status are ignored"
end
def run_version
puts "ptouch-print-png #{Libptouch::VERSION}"
0
end
def run_help
puts usage_banner
puts ""
puts parser_help_text
0
end
def parser_help_text
opts_hash = default_cli_opts
p = OptionParser.new do |parser|
parser.banner = "ptouch-print-png [options]"
parser.on("-f", "--file PATH", "入力 PNG/SVG ファイル") { |v| opts_hash[:file] = v }
parser.on("-t", "--threshold N", Integer,
"二値化しきい値 0255既定 #{Libptouch::PNG_DEFAULT_THRESHOLD}、PNG/SVG") do |v|
opts_hash[:threshold] = v
end
parser.on("-p", "--pid PID", pid_option_description) do |v|
apply_usb_pid_option(opts_hash, v)
end
parser.on("-n", "--dry-run", "読み込みと検証のみUSB なし)") { opts_hash[:dry_run] = true }
parser.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") do
opts_hash[:status] = true
end
parser.on("-V", "--version", "バージョンを表示して終了") { opts_hash[:version] = true }
parser.on("-h", "--help", "このヘルプ") { opts_hash[:help] = true }
end
p.help
end
def open_usb_for_opts(ctx, opts)
if opts[:usb_pid]
ctx.open_usb_vid_pid(Libptouch::USB_VID_BROTHER, opts[:usb_pid])
else
ctx.open_usb
end
end
def run_status(opts)
ctx = nil
begin
ctx = Libptouch::Context.new
open_usb_for_opts(ctx, opts)
h = Libptouch.parse_status(ctx.status_bytes)
h.delete(:raw_bytes)
puts JSON.pretty_generate(h)
0
rescue Libptouch::Error => e
warn "get_status: #{e.message}"
1
ensure
ctx&.dispose
end
end
def run_print(path, opts, kind)
ctx = nil
begin
ctx = Libptouch::Context.new
threshold = opts[:threshold]
data, width, height = if kind == :svg
open_usb_for_opts(ctx, opts)
if threshold.nil?
ctx.svg_file_to_raster_fit_current_tape(path)
else
ctx.svg_file_to_raster_fit_current_tape(path, threshold: threshold)
end
elsif threshold.nil?
ctx.png_file_to_raster(path)
else
ctx.png_file_to_raster(path, threshold: threshold)
end
ctx.check_raster(data, width_dots: width, height_dots: height)
if opts[:dry_run]
puts "dry-run OK: #{data.bytesize} bytes, src #{width}x#{height} dots (print lengthxwidth #{width}x#{height})"
return 0
end
open_usb_for_opts(ctx, opts) if kind == :png
ctx.print_raster(data, width_dots: width, height_dots: height)
0
rescue Libptouch::Error => e
warn e.message
1
ensure
ctx&.dispose
end
end
def usage_error(msg)
warn msg
warn "(try ptouch-print-png --help)"
2
end
end
end end
end end

View File

@@ -134,7 +134,7 @@ module Libptouch
print_dpi: info[:print_dpi], print_dpi: info[:print_dpi],
feed_dpi: info[:feed_dpi], feed_dpi: info[:feed_dpi],
tape_width_mm: info[:tape_width_mm], tape_width_mm: info[:tape_width_mm],
printable_dots: info[:printable_dots], printable_height_dots: info[:printable_dots],
left_margin_dots: info[:left_margin_dots], left_margin_dots: info[:left_margin_dots],
right_margin_dots: info[:right_margin_dots], right_margin_dots: info[:right_margin_dots],
min_feed_dots: info[:min_feed_dots], min_feed_dots: info[:min_feed_dots],

View File

@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(__dir__) { Dir["lib/**/*.rb", "exe/*", "README.md"] } spec.files = Dir.chdir(__dir__) { Dir["lib/**/*.rb", "exe/*", "README.md"] }
spec.bindir = "exe" spec.bindir = "exe"
spec.executables = ["ptouch-print-png"] spec.executables = ["ptouch-label", "ptouch-print-png"]
spec.require_paths = ["lib"] spec.require_paths = ["lib"]
spec.add_dependency "ffi", "~> 1.15" spec.add_dependency "ffi", "~> 1.15"

View File

@@ -1,9 +1,16 @@
# samples # samples
試験・デモ用のサンプル画像PNG など)を置くディレクトリです。リポジトリに含める場合はライセンス・著作権に注意してください。 試験・デモ用のサンプル画像PNG/SVGや差込印刷データJSON/YAML)を置くディレクトリです。リポジトリに含める場合はライセンス・著作権に注意してください。
例(ドライラン): 例(ドライラン):
```bash ```bash
./build/ptouch-print -n -f samples/your.png ./build/ptouch-print -n -f samples/your.png
``` ```
差込印刷の例Ruby CLI:
```bash
ruby -I ruby/lib ruby/exe/ptouch-label -n --template samples/merge_template.svg --data samples/merge_data.yml
ruby -I ruby/lib ruby/exe/ptouch-label -n --template samples/merge_template.svg --data samples/merge_data.json
```

5
samples/merge_data.json Normal file
View File

@@ -0,0 +1,5 @@
{
"title": "出荷ラベル",
"left": "品番 ABC-123",
"right": "数量 24"
}

3
samples/merge_data.yml Normal file
View File

@@ -0,0 +1,3 @@
title: "出荷ラベル"
left: "品番 ABC-123"
right: "数量 24"

View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="220" viewBox="0 0 720 220">
<rect width="720" height="220" fill="#FFFFFF" />
<text x="24" y="86" data-field="title" font-size="56" fill="#000000">TITLE</text>
<text x="24" y="160" font-size="36" fill="#000000">
<tspan data-field="left">LEFT</tspan>
<tspan dx="20">/</tspan>
<tspan dx="20" data-field="right">RIGHT</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 417 B