zpl.tools
Fonts and text

^TB - Text Block

Wraps text inside a box of a given width and height, clipping the overflow.

^TB turns the field it precedes into a block of a fixed width and height. It wraps the field data across as many lines as the data needs, and cuts off whatever does not fit. It is the newer of the two wrap commands, and its bounds are on both axes, which distinguishes it from ^FB. Give ^TB a height, and the block cannot grow past it, whatever the data holds.

Syntax

^TBo,w,h

Support

Supportedparsed: full · state: full · rendered: full

Every documented parameter renders the same output Labelary produces.

Labelary renders this command.

Parameters

oOrientationoptional · one of a set

Rotation of the block. Unlike ^FB, which has no orientation of its own, a value here replaces the field's: ^A0R,50,50^TBN draws the same block as ^A0N,50,50^TBN.

Default
the orientation set by ^A or ^FW, or N
Invalid value
discarded, and the default applies. An orientation outside N/R/I/B reports Value 'Q' is not a valid orientation (N/R/I/B) and was ignored, and the block keeps the orientation ^A or ^FW set.
Test coverage
No documented value is exercised by a test (N, R, I, B). The invalid-value rule is pinned by 2 tests.
N
Normal (default)
R
Rotated 90° clockwise
I
Inverted 180°
B
Read from bottom up, 270°
wBlock widthoptional · dots

Width the text wraps at. The wrap itself matches ^FB at the same width, character for character, down to breaking inside a word too wide for the block.

Default
1
Accepted range
1 to 9999 dots
Invalid value
discarded, and the default applies. A value that is not a number is ignored and the dimension falls back to its default of one dot. A number outside the range clamps to the bound it crossed, and a negative one is bounded at 1 rather than read by its magnitude.
Test coverage
Bounds pinned: below the minimum (-400, 0), above the maximum (32000). No test at the minimum or maximum. The invalid-value rule is pinned by 1 test.
hBlock heightoptional · dots

Height of the block. Ink past it is cut on the dot, through the middle of whatever glyphs the boundary crosses, rather than a whole line or a whole word at a time. The width never cuts: a one-dot block still draws each glyph whole.

Default
1
Accepted range
1 to 9999 dots
Invalid value
discarded, and the default applies. A value that is not a number is ignored and the dimension falls back to its default of one dot. A number outside the range clamps to the bound it crossed, and a negative one is bounded at 1 rather than read by its magnitude.
Test coverage
Bounds pinned: below the minimum (0), above the maximum (10000). No test at the minimum or maximum. The invalid-value rule is pinned by 1 test.

Behavior

^TB belongs inside the field, between the origin and the ^FD, alongside the ^A that sets the font. It takes the origin, the font and the size from that field. Only the rotation overrides on ^TB itself, and by default it follows ^A or ^FW.

Both defaults are 1 dot, and a block one dot wide wraps nothing. Treat w and h as required.

^TB or ^FB

They solve the same problem with different limits.

  • A line count bounds ^FB. Text past the last line overwrites it rather than disappears, so an overlong field ends in a pile of glyphs.
  • A height in dots bounds ^TB. Text past the bottom truncates, which loses data quietly and leaves the label legible.

^FB also offers justification and a hanging indent, and ^TB does not, so a right-aligned or justified block still needs ^FB. ^FB cannot work with a large TrueType font from ~DU, where ^TB is the only option.

Line pitch

^TB sets its lines 1.26 times the font height apart, where ^FB sets them one font height apart. So the same data in the same width takes more room under ^TB: at ^A0N,60,60 the pitch is 75.6 dots rather than 60.

^TB reads neither of ^FB's spacing arguments, because it replaced the command that carries them. It also does not read the \& line separator, which prints as its own two characters inside a ^TB block.

Where the block sits

Under ^FO the origin is the box's top-left corner, so the block hangs below the origin. Under ^FT it is the corner that reads as the bottom left, so the block hangs above the origin and its last line lands on the anchor. A tall block under a ^FT near the top of the label therefore falls off the page.

Text that does not fit

A block too short for its lines reports Text does not fit the specified text block dimensions. The report is on the layout rather than on the ink, so it can fire while every line is still drawn in full. The cut itself is on the dot, through the middle of whatever glyphs the boundary crosses, and only ever across the lines: the width never cuts a glyph, so a one-dot block still draws each one whole.

Differences from the specification

Labelary against the ZPL II guide

Where Labelary — our compatibility target — behaves differently from the printed specification.

  • ^TB is absent from the 2006 guide; Labelary's reference is the only description of it used here. — not pinned by a test
  • Labelary spaces a ^TB block's lines 1.26 times the font height apart, where ^FB spaces them by the font height itself. At ^A0N,50,50 the pitch is 63.000 dots and at ^A0N,40,40 it is 50.400. — not pinned by a test
  • Labelary does not read the \& hard break inside a ^TB block; the two characters print as themselves, exactly as they do with no block at all. — not pinned by a test
  • Labelary reports text that does not fit whenever the lines' pitch exceeds the block height. That is stricter than the clip. A 200-dot block over three 60-dot lines reports, yet draws all three in full. — not pinned by a test
  • Labelary sends the overflow advisory on an image response and withholds it from a JSON one. Measured 2026-08-21: one label with Accept: image/png and X-Linter: On answers Text does not fit the specified text block dimensions, and the same label with Accept: application/json answers no X-Warnings header at all. On a label with other advisories the overflow entries arrive appended after them, out of offset order, which is where the report is raised: after layout, which the field-data response never runs. The warning oracle therefore captures both responses and asserts their merge, and the corpus marks an entry only the image response carried. — pinned by test_tb_reports_text_that_does_not_fit

Example

A 420 by 140 dot block.

^XA
^FO50,40^A0N,28^TBN,420,140^FDA delivery note that is too long for one line and wraps inside the block^FS
^XZ

Open in viewer