Skip to content
109 changes: 109 additions & 0 deletions .github/skills/tspl-reference/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
name: tspl-reference
description: "Look up TSPL/TSPL2 command specifications from official TSC programming manuals. Use when: implementing TSPL commands, debugging TSPL parsing, verifying parameter syntax, checking defaults, coordinate units, text or bitmap font behavior, graphics, bitmap modes, barcode/QR/PDF417/DataMatrix/Aztec/MaxiCode semantics, or fixing TSPL rendering differences."
argument-hint: "TSPL command name or rendering question (e.g. 'SIZE units', 'TEXT alignment', 'BARCODE parameters')"
---

# TSPL Official Reference Lookup

## Purpose

Fetch and interpret TSPL/TSPL2 command specifications from the official TSC programming manual to resolve ambiguities in labelize's TSPL parser and renderer.

## When to Use

- Implementing or fixing a TSPL command parser
- A `.tspl` label renders incorrectly
- Unsure about command syntax, optional parameters, defaults, ranges, or units
- Text, graphics, bitmap, or barcode behavior is unclear
- Comparing labelize output with a real TSC printer, TSC docs, or Zebra TSPL compatibility docs

## Official Documentation

Primary source:

```
https://fs.tscprinters.com/en/dl/4/2541
```

Known direct PDF URL:

```
https://fs.tscprinters.com/system/files/31-0000001-00_tspl_tspl2_programming_3_0.pdf
```

If the direct PDF stops working, start from the TSC downloads page and search for `TSPL/ TSPL2 Programming Manual (English)`:

```
https://usca.tscprinters.com/en/downloads
```

Supplementary compatibility reference:

```
https://www.zebra.com/content/dam/support-dam/en/documentation/unrestricted/guide/software/zd100series-zd230series-zd888series-proman-en.pdf
```

## Common TSPL Command Areas

| Area | Commands |
|------|----------|
| Setup and media | `SIZE`, `GAP`, `BLINE`, `OFFSET`, `SPEED`, `DENSITY`, `DIRECTION`, `REFERENCE`, `SHIFT`, `CODEPAGE`, `CLS`, `PRINT` |
| Text | `TEXT`, `BLOCK`, resident bitmap fonts, downloaded fonts, code pages |
| Graphics | `BAR`, `BOX`, `CIRCLE`, `ELLIPSE`, `ERASE`, `REVERSE`, `BITMAP`, `PUTBMP`, `PUTPCX`, `PUTPNG` |
| 1D barcodes | `BARCODE`, `TLC39`, `RSS` |
| 2D barcodes | `QRCODE`, `PDF417`, `MPDF417`, `DMATRIX`, `MAXICODE`, `AZTEC` |
| Memory/files | `DOWNLOAD`, `EOP`, `FILES`, `KILL`, `MOVE`, `RUN` |
| Device control | `FEED`, `BACKFEED`, `FORMFEED`, `HOME`, `CUT`, `SELFTEST`, `SOUND` |

## Procedure

1. **Identify the command** — Extract the TSPL command name from the user's question, fixture, or parser code. TSPL command names are case-insensitive in practice; normalize to uppercase when searching.

2. **Fetch the official manual** — Use the web or fetch tool to load the TSC manual PDF. Search within the PDF for the command heading, then read the full command section.

3. **Extract key details:**
- Syntax line and exact parameter order
- Parameter types, required vs optional fields, defaults, ranges, and units
- Coordinate behavior, especially dot units and effects of `REFERENCE`, `SHIFT`, and `DIRECTION`
- Bitmap and barcode mode semantics
- Printer-model or TSPL-vs-TSPL2 compatibility notes

4. **Compare with labelize implementation:**
- Parser: `src/parsers/tspl_parser.rs`
- Rendered elements: `src/elements/`
- Renderer: `src/drawers/renderer.rs`
- Barcode encoders: `src/barcodes/`
- TSPL parser tests: `tests/unit_tspl_parser.rs`
- Fixture labels: `testdata/tspl/`

5. **Report discrepancies** between the official spec and labelize's behavior before editing code. Include parameter position, official default, current implementation, and the expected rendering effect.

6. **Verify focused changes** with TSPL-specific tests first:
```bash
cargo test --test unit_tspl_parser
cargo test --test unit_renderer
```

For parser or rendering changes with wider impact, also run:
```bash
cargo test
```

## Labelize TSPL Notes

- `SIZE` may update per-label `DrawerOptions`; explicit CLI/API dimensions can override it per axis.
- Coordinates are interpreted in dots after applying `REFERENCE` and `SHIFT`.
- Supported render-focused commands currently include `SIZE`, `DIRECTION`, `REFERENCE`, `SHIFT`, `CLS`, `PRINT`, `TEXT`, `BAR`, `BOX`, `CIRCLE`, `ELLIPSE`, `ERASE`, `REVERSE`, `BITMAP`, `BARCODE`, `QRCODE`, and `PDF417`.
- Some TSPL commands may be accepted as device no-ops because they affect printer hardware rather than rendered output.
- Do not add command behavior from secondary references without checking the official TSC manual first.

## Example

User asks: "Why is TSPL TEXT too large?"

1. Fetch the TSC TSPL/TSPL2 Programming Manual.
2. Search for the `TEXT` command and resident font table.
3. Check font width/height, x/y multiplication, rotation, and alignment parameters.
4. Compare with `parse_text`, `tspl_font_info`, and TSPL font metrics in `src/elements/font.rs`.
5. Add or adjust focused tests in `tests/unit_tspl_parser.rs`, then run `cargo test --test unit_tspl_parser`.
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Labelize — ZPL / EPL Label Renderer
# Labelize — ZPL / EPL / TSPL Label Renderer

[![Crates.io](https://img.shields.io/crates/v/labelize)](https://crates.io/crates/labelize)
[![License](https://img.shields.io/github/license/GOODBOY008/labelize)](LICENSE)
[![Build](https://img.shields.io/github/actions/workflow/status/GOODBOY008/labelize/ci.yml?branch=main)](https://github.com/GOODBOY008/labelize/actions)

> **Turn ZPL/EPL into pixels — label rendering, simplified.**
> **Turn ZPL/EPL/TSPL into pixels — label rendering, simplified.**

Labelize is a fast, open-source Rust engine that parses **ZPL** (Zebra Programming Language) and **EPL** (Eltron Programming Language) label data and renders it to **PNG** or **PDF**. Use it as a **CLI tool**, an **HTTP microservice**, or embed it as a **Rust library** — no printer hardware required.
Labelize is a fast, open-source Rust engine that parses **ZPL** (Zebra Programming Language), **EPL** (Eltron Programming Language), and **TSPL** label data and renders it to **PNG** or **PDF**. Use it as a **CLI tool**, an **HTTP microservice**, or embed it as a **Rust library** — no printer hardware required.

If you need a self-hosted, offline alternative to [Labelary](http://labelary.com/) for previewing and converting thermal label formats, Labelize has you covered.

Expand Down Expand Up @@ -39,11 +39,12 @@ Benchmarked against the Labelary API on the same set of labels:

- **ZPL Parser** — 30+ ZPL commands: text, barcodes, graphics, stored formats, graphic fields, field blocks, and more
- **EPL Parser** — EPL command support for text, barcodes, line draw, and reference points
- **TSPL Parser** — render-focused support for `SIZE`, text, graphics, bitmaps, QR/PDF417, and common 1D barcodes
- **10 Barcode Symbologies** — Code 128, Code 39, EAN-13, Interleaved 2-of-5, PDF417, Aztec, DataMatrix, QR Code, MaxiCode
- **PNG & PDF Output** — Monochrome 1-bit PNG or single-page embedded PDF output
- **CLI Tool** — Convert ZPL/EPL files from the command line with format auto-detection, multi-label support, and customizable label dimensions
- **CLI Tool** — Convert ZPL/EPL/TSPL files from the command line with format auto-detection, multi-label support, and customizable label dimensions
- **HTTP Microservice** — RESTful API for label conversion with format detection via `Content-Type` header; deploy anywhere with Docker or bare metal
- **Web Playground** — Built-in browser UI at `GET /` — paste or open a `.zpl`/`.epl` file, choose a label size (4×6, 4×4, etc.), render PNG inline, and download PNG or PDF with one click
- **Web Playground** — Built-in browser UI at `GET /` — paste or open a `.zpl`/`.epl`/`.tspl` file, choose a label size (4×6, 4×4, etc.), render PNG inline, and download PNG or PDF with one click
- **Embedded Fonts** — Zero runtime font dependencies; bundles Helvetica Bold Condensed, DejaVu Sans Mono, and ZPL GS fonts
- **Rust Library** — Integrate label rendering directly into your Rust application via the public API

Expand All @@ -64,6 +65,7 @@ cargo install --path .
```bash
labelize convert label.zpl # → label.png (format auto-detected)
labelize convert label.epl # EPL works too
labelize convert label.tspl # TSPL SIZE controls dimensions unless overridden
labelize convert label.zpl -t pdf # output as PDF
labelize convert label.zpl --width 100 --height 62 --dpmm 12 # custom dimensions
```
Expand All @@ -74,7 +76,7 @@ labelize convert label.zpl --width 100 --height 62 --dpmm 12 # custom dimension
labelize serve --port 8080
```

Open **http://localhost:8080/** in your browser to use the built-in **interactive playground** — paste ZPL/EPL, pick a label size, and render PNG instantly. Download PNG or PDF directly from the page.
Open **http://localhost:8080/** in your browser to use the built-in **interactive playground** — paste ZPL/EPL/TSPL, pick a label size, and render PNG instantly. Download PNG or PDF directly from the page.

```bash
# Convert via REST API
Expand All @@ -90,16 +92,16 @@ curl -X POST http://localhost:8080/convert \
Usage: labelize <COMMAND>

Commands:
convert Convert a ZPL/EPL file to PNG or PDF
convert Convert a ZPL/EPL/TSPL file to PNG or PDF
serve Start HTTP server for label conversion

Convert Options:
<INPUT> Input file path (.zpl or .epl)
<INPUT> Input file path (.zpl, .epl, or .tspl)
-o, --output <PATH> Output file path (default: input stem + .png/.pdf)
-f, --format <FMT> Input format override: zpl | epl
-f, --format <FMT> Input format override: zpl | epl | tspl
-t, --type <TYPE> Output type: png | pdf [default: png]
--width <MM> Label width in mm [default: 102]
--height <MM> Label height in mm [default: 152]
--width <MM> Label width override in mm
--height <MM> Label height override in mm
--dpmm <N> Dots per mm [default: 8]

Serve Options:
Expand All @@ -124,7 +126,7 @@ Serve Options:
| `dpmm` | 8 | Dots per mm |
| `output` | png | Output format: png/pdf |

Set `Content-Type: application/zpl` or `Content-Type: application/epl` to select the parser.
Set `Content-Type: application/zpl`, `application/epl`, or `application/tspl` to select the parser. For TSPL, `SIZE` supplies render dimensions unless `width` or `height` is provided explicitly.

## Library Usage

Expand All @@ -143,7 +145,7 @@ renderer.draw_label_as_png(&labels[0], &mut buf, DrawerOptions::default()).unwra
std::fs::write("output.png", buf.into_inner()).unwrap();
```

## Supported ZPL & EPL Commands
## Supported ZPL, EPL & TSPL Commands

### ZPL Commands

Expand All @@ -159,10 +161,14 @@ std::fs::write("output.png", buf.into_inner()).unwrap();

`N` (new label) · `A` (text) · `B` (barcode) · `LO` (line draw) · `R` (reference point) · `P` (print)

### TSPL Commands

`SIZE` · `DIRECTION` · `REFERENCE` · `SHIFT` · `CLS` · `PRINT` · `TEXT` · `BAR` · `BOX` · `CIRCLE` · `ELLIPSE` · `ERASE` · `REVERSE` · `BITMAP` · `BARCODE` · `QRCODE` · `PDF417`

## Architecture

```
ZPL/EPL input
ZPL/EPL/TSPL input
┌─────────┐ ┌──────────┐ ┌─────────┐
Expand Down Expand Up @@ -226,7 +232,7 @@ cargo build --release

## Related Projects & Keywords

Looking for a **ZPL renderer**, **ZPL to PNG converter**, **ZPL to PDF**, **EPL parser**, **Zebra label preview**, **thermal label rendering**, or **Labelary alternative**? Labelize covers all of these.
Looking for a **ZPL renderer**, **ZPL to PNG converter**, **ZPL to PDF**, **EPL parser**, **TSPL parser**, **Zebra label preview**, **thermal label rendering**, or **Labelary alternative**? Labelize covers all of these.

## Contributing

Expand Down
5 changes: 5 additions & 0 deletions docs/TSPL_COMMANDS_REFERENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TSPL Commands Reference

Source: [TSPL/ TSPL2 Programming Manual 3.0 (2026)](https://fs.tscprinters.com/en/dl/4/2541)
Source: [TSPL/ TSPL2 Programming Manual (2009)](https://cleversoftsolutions.com/descargas/utilidades/Impresoras/Tsc/TSPL_TSPL2_Programming2.pdf)
Source: [Zebra TSPL Programming Guide](https://www.zebra.com/content/dam/support-dam/en/documentation/unrestricted/guide/software/zd100series-zd230series-zd888series-proman-en.pdf)
38 changes: 33 additions & 5 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ labelize convert label.epl
# → label.png (auto-detected from extension)
```

### Convert a TSPL file to PNG

```bash
labelize convert label.tspl
# → label.png (TSPL SIZE controls dimensions unless overridden)
```

### Specify output path

```bash
Expand All @@ -55,6 +62,7 @@ labelize convert label.zpl -t pdf

```bash
labelize convert data.txt --format zpl
labelize convert data.txt --format tspl
```

### Custom label dimensions
Expand All @@ -65,10 +73,10 @@ labelize convert label.zpl --width 100 --height 150 --dpmm 12

| Option | Default | Description |
|-------------|---------|------------------------------------------|
| `--width` | 102 | Label width in mm |
| `--height` | 152 | Label height in mm |
| `--width` | 102 or TSPL `SIZE` | Label width override in mm |
| `--height` | 152 or TSPL `SIZE` | Label height override in mm |
| `--dpmm` | 8 | Dots per mm (6, 8, 12, or 24) |
| `-f, --format` | auto | Input format: `zpl` or `epl` |
| `-f, --format` | auto | Input format: `zpl`, `epl`, or `tspl` |
| `-t, --type` | png | Output type: `png` or `pdf` |
| `-o, --output` | auto | Output file path |

Expand Down Expand Up @@ -123,6 +131,15 @@ curl -X POST http://localhost:8080/convert \
-o label.png
```

### Convert TSPL to PNG via HTTP

```bash
curl -X POST http://localhost:8080/convert \
-H "Content-Type: application/tspl" \
--data-binary @label.tspl \
-o label.png
```

### Convert to PDF via HTTP

Add `?output=pdf` to the URL:
Expand All @@ -145,8 +162,8 @@ curl -X POST "http://localhost:8080/convert?width=100&height=62&dpmm=12" \

| Parameter | Default | Description |
|-----------|---------|-------------------------|
| `width` | 102 | Label width in mm |
| `height` | 152 | Label height in mm |
| `width` | 102 or TSPL `SIZE` | Label width override in mm |
| `height` | 152 or TSPL `SIZE` | Label height override in mm |
| `dpmm` | 8 | Dots per mm |
| `output` | png | Output format: png/pdf |

Expand Down Expand Up @@ -262,3 +279,14 @@ fn main() {
| `LO` | Line draw (graphic box) |
| `R` | Reference point |
| `P` | Print label |

## Supported TSPL Commands

| Category | Commands |
|----------|----------|
| **Layout** | `SIZE` `DIRECTION` `REFERENCE` `SHIFT` `CLS` `PRINT` |
| **Text** | `TEXT` |
| **Graphics** | `BAR` `BOX` `CIRCLE` `ELLIPSE` `ERASE` `REVERSE` `BITMAP` |
| **Barcodes** | `BARCODE` (`128`, `EAN128`, `39`, `39C`, `EAN13`) `QRCODE` `PDF417` |

Printer-control commands such as `GAP`, `SPEED`, `DENSITY`, and `SET` are parsed as no-ops because they do not affect rendered output.
Binary file added src/assets/fonts/TSS16.BF2
Binary file not shown.
Binary file added src/assets/fonts/TSS24.BF2
Binary file not shown.
Binary file added src/assets/fonts/WenQuanYiBitmapSong12px.ttf
Binary file not shown.
Binary file added src/assets/fonts/WenQuanYiBitmapSong16px.ttf
Binary file not shown.
2 changes: 2 additions & 0 deletions src/assets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ pub static FONT_HELVETICA_BOLD: &[u8] = include_bytes!("fonts/HelveticaBoldConde
pub static FONT_DEJAVU_SANS_MONO: &[u8] = include_bytes!("fonts/DejaVuSansMono.ttf");
pub static FONT_DEJAVU_SANS_MONO_BOLD: &[u8] = include_bytes!("fonts/DejaVuSansMonoBold.ttf");
pub static FONT_ZPL_GS: &[u8] = include_bytes!("fonts/ZplGSCustom.ttf");
pub static WENQUANYI_BITMAP_SONG_12PX: &[u8] = include_bytes!("fonts/WenQuanYiBitmapSong12px.ttf");
pub static WENQUANYI_BITMAP_SONG_16PX: &[u8] = include_bytes!("fonts/WenQuanYiBitmapSong16px.ttf");
Loading