^JM - Set Dots per Millimetre
Halves the print density, which doubles the physical size of everything on the label.
^JMB halves the printhead's dot density: 24 dots/mm becomes 12, 12 becomes 6,
8 becomes 4 and 6 becomes 3. The format does not change, but every coordinate
and dimension in it covers twice the distance, so the label doubles in size. It
scales the whole format, not one field, and it must appear before the first
^FS of the format.
Syntax
^JMaSupport
Every documented parameter renders the same output Labelary produces.
The parser reads the density letter and the renderer applies it. ^JMB halves the printhead's dot density, so one ZPL dot covers two device pixels and every coordinate, dimension, font height and barcode module doubles. The page keeps the size the request asked for, so a label authored for full density overflows it and the overflow is clipped, which is what Labelary does. The magnification reaches the finished page geometry and not the arguments. ^MU's inch and millimeter conversions still divide by the head's real resolution. The ^PW window is still centered on the unscaled page width. The density is a printer setting and survives ^XZ until a later ^JMA takes it back. A ^JM outside a format is ignored silently, and one past the format's first ^FS is ignored with Labelary's own report. Measured against Labelary on 2026-08-20 at 6, 8 and 12 dpmm. — not pinned by a test
Labelary renders this command.
Parameters
aDensityoptional · one of a setSelects full or half the printhead's dot density. Half density doubles every coordinate and dimension on the label.
- Default
- the density already in force, or
Aat power-up - Invalid value
- discarded, and the current value is kept. A letter outside A and B is reported as
Value 'X' is not a valid density adjustment (A/B); used 'A' insteadand leaves the density already in force in place. Labelary's message namesA, but its render does not use it:^XA^JMB^JMX...^XZstays at half density (measured 2026-08-20). - Test coverage
- No documented value is exercised by a test (A, B). The invalid-value rule is pinned by 2 tests.
A- Normal print density (default)
B- Half print density; all content doubles in size
Behavior
Half density doubles field origins as well as field sizes. Under ^JMB,
^FO50,50 lands where ^FO100,100 lands at full density, so a layout that fits
at ^JMA runs off the label at ^JMB.
The guide states that the effect outlives the format. One ^JMB applies to
every label after it until ^JMA or a power cycle, which makes it a risk in a
shared prologue.
The guide names one casualty. Under ^JMB the UPS MaxiCode symbol falls out of
specification, because a doubled module size breaks the geometry the symbology
requires.
The renderer does not parse ^JM, so a format that uses it renders at full
density. Every element sits at half its correct size and half its intended
position, with nothing in the image to show the error. The only workaround is to
write the doubled coordinates and sizes directly.
Differences from the specification
zpl.tools against Labelary
Where our output differs from Labelary for the same input. These are the differences that break a migration.
- A density of more than one character is trimmed in both engines, and reported on the same argument at the same bytes, in a different sentence. Labelary says the value
is too long and was trimmed to one character; the report here names the character that survived, as inValue 'BB' is too long and was trimmed to 'B'(measured 2026-08-21). The wording is deliberate and belongs toParseWarning::TrimmedArgument, so^MCand^PMread the same way, each adding that the value is a boolean. — pinned bytest_jm_two_letter_density_reports_the_surviving_letter
Example
Related commands
^MUSet Units of MeasurementSwitches position and size arguments from dots to inches or millimeters.^PWPrint WidthSets the printable width of the label.^FOField OriginSets the top-left corner of the next field.^FSField SeparatorEnds the current field.