Module: ZplRender
- Defined in:
- lib/zpl_render.rb,
lib/zpl_render/font.rb,
lib/zpl_render/canvas.rb,
lib/zpl_render/parser.rb,
lib/zpl_render/version.rb,
lib/zpl_render/renderer.rb,
lib/zpl_render/truetype.rb,
lib/zpl_render/font_data.rb,
lib/zpl_render/barcode/qr.rb,
lib/zpl_render/output/pdf.rb,
lib/zpl_render/output/png.rb,
lib/zpl_render/graphic_field.rb,
lib/zpl_render/barcode/code39.rb,
lib/zpl_render/barcode/pdf417.rb,
lib/zpl_render/barcode/code128.rb,
lib/zpl_render/helvetica_metrics.rb,
lib/zpl_render/barcode/pdf417_tables.rb,
lib/zpl_render/barcode/interleaved2of5.rb
Overview
Render ZPL II label programs to PNG or PDF.
png = ZplRender.to_png(zpl, dpmm: 8, width_in: 4, height_in: 6)
pdf = ZplRender.to_pdf(zpl, dpmm: 8, width_in: 4, height_in: 6)
dpmm is the printer density in dots per millimeter:
6 = 152 dpi, 8 = 203 dpi (most common), 12 = 300 dpi, 24 = 600 dpi
Error handling: every failure the library raises intentionally is a
ZplRender::Error. By default rendering is lenient: recoverable problems
(a field that fails to render, an unsupported command) are recorded in
the optional warnings array and rendering continues, like a printer.
Pass strict: true to raise ZplRender::Error on the first problem
instead, for pipelines that must not silently drop label content.
Defined Under Namespace
Modules: Barcode, Font, GraphicField, Output Classes: Canvas, Error, Parser, Renderer, TrueType
Constant Summary collapse
- VERSION =
"0.2.0"- FONT8X8 =
one per row, LSB = leftmost pixel.
[ [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # ^ 0x00-0x0f [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # ^ 0x10-0x1f [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00], [0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00], [0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00], [0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00], [0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00], [0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00], [0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00], [0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00], [0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00], [0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06], [0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00], [0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00], # ^ 0x20-0x2f [0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00], [0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00], [0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00], [0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00], [0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00], [0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00], [0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00], [0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00], [0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00], [0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00], [0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00], [0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06], [0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00], [0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00], [0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00], [0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00], # ^ 0x30-0x3f [0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00], [0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00], [0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00], [0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00], [0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00], [0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00], [0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00], [0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00], [0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00], [0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], [0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00], [0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00], [0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00], [0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00], [0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00], [0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00], # ^ 0x40-0x4f [0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00], [0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00], [0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00], [0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00], [0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], [0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00], [0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00], [0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00], [0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00], [0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00], [0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00], [0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00], [0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00], [0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00], [0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF], # ^ 0x50-0x5f [0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00], [0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00], [0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00], [0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00], [0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00], [0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00], [0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F], [0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00], [0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], [0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E], [0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00], [0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], [0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00], [0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00], [0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00], # ^ 0x60-0x6f [0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F], [0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78], [0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00], [0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00], [0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00], [0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00], [0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00], [0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00], [0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00], [0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F], [0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00], [0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00], [0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00], [0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00], [0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # ^ 0x70-0x7f ].each(&:freeze).freeze
- HELVETICA_WIDTHS =
Helvetica advance widths (1/1000 em) for ASCII 32-126, from the Adobe Core 14 AFM metrics. Used to approximate Zebra's scalable CG Triumvirate (font 0), which shares Helvetica's metrics closely.
[ 278, 278, 355, 556, 556, 889, 667, 222, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 222, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584 ].freeze
Class Method Summary collapse
-
.decode_base64(data) ⇒ Object
Decode a Base64-encoded ZPL payload into the ZPL string.
-
.render(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) ⇒ Object
Render every ^XA..^XZ format to a Canvas (dot matrix).
-
.to_pdf(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) ⇒ Object
PDF bytes, one page per label, at exact physical size.
-
.to_png(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) ⇒ Object
PNG bytes for the first label.
-
.to_pngs(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) ⇒ Object
PNG bytes for every label.
Class Method Details
.decode_base64(data) ⇒ Object
Decode a Base64-encoded ZPL payload into the ZPL string. Accepts the standard and URL-safe alphabets, tolerates whitespace/newlines and missing padding, and raises ZplRender::Error when the input is not base64 or does not decode to ZPL. Useful when labels are stored base64-encoded (WMS exports, database columns, API payloads).
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/zpl_render.rb', line 42 def decode_base64(data) raise Error, "base64 input must be a String (got #{data.class})" unless data.respond_to?(:to_str) compact = data.to_str.gsub(/\s+/, "").tr("-_", "+/") compact += "=" * ((4 - compact.length % 4) % 4) unless !compact.empty? && compact.match?(%r{\A[A-Za-z0-9+/]+={0,2}\z}) && (compact.length % 4).zero? raise Error, "input is not valid base64" end zpl = begin compact.unpack1("m0") rescue ArgumentError => e raise Error, "input is not valid base64: #{e.}" end zpl.force_encoding(Encoding::UTF_8) zpl.force_encoding(Encoding::BINARY) unless zpl.valid_encoding? raise Error, "decoded base64 does not contain any ZPL commands" unless zpl.match?(/[\^~]/) zpl end |
.render(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) ⇒ Object
Render every ^XA..^XZ format to a Canvas (dot matrix).
Pass base64: true when zpl is a Base64-encoded ZPL payload.
65 66 67 68 69 70 71 72 73 |
# File 'lib/zpl_render.rb', line 65 def render(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) raise Error, "zpl must be a String (got #{zpl.class})" unless zpl.respond_to?(:to_str) zpl = base64 ? decode_base64(zpl) : zpl.to_str renderer = Renderer.new(dpmm: dpmm, width_in: width_in, height_in: height_in, strict: strict) labels = renderer.render(zpl) warnings.concat(renderer.warnings) if warnings labels end |
.to_pdf(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) ⇒ Object
PDF bytes, one page per label, at exact physical size.
92 93 94 95 96 97 98 |
# File 'lib/zpl_render.rb', line 92 def to_pdf(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, strict: false, base64: false, warnings: nil) labels = render(zpl, dpmm: dpmm, width_in: width_in, height_in: height_in, strict: strict, base64: base64, warnings: warnings) raise Error, "no ^XA..^XZ label formats found" if labels.empty? Output::Pdf.encode(labels, dpmm: dpmm) end |
.to_png(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) ⇒ Object
PNG bytes for the first label.
76 77 78 79 80 81 82 |
# File 'lib/zpl_render.rb', line 76 def to_png(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) labels = render(zpl, dpmm: dpmm, width_in: width_in, height_in: height_in, strict: strict, base64: base64, warnings: warnings) raise Error, "no ^XA..^XZ label formats found" if labels.empty? Output::Png.encode(labels.first, scale: scale) end |
.to_pngs(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) ⇒ Object
PNG bytes for every label.
85 86 87 88 89 |
# File 'lib/zpl_render.rb', line 85 def to_pngs(zpl, dpmm: 8, width_in: 4.0, height_in: 6.0, scale: 1, strict: false, base64: false, warnings: nil) render(zpl, dpmm: dpmm, width_in: width_in, height_in: height_in, strict: strict, base64: base64, warnings: warnings) .map { |canvas| Output::Png.encode(canvas, scale: scale) } end |