Validate LabelManager Wireless PnP support (fixes #81) - #156
Open
willumpie82 wants to merge 3 commits into
Open
Conversation
added 3 commits
August 28, 2026 22:22
PIL's "mm" anchor centers multiline text using the font's line metrics (ascent + descent), not the rendered glyphs' actual bounding box. Text with no descenders (no g/j/p/q/y) then renders visibly shifted toward the top of the canvas, since the reserved descender space below it stays blank. This affects essentially any short label -- names, acronyms, single words in caps. Measure the real ink bounding box via multiline_textbbox and center on that instead.
_send_command's chunk-boundary search stopped AT the synwait-th SYN character rather than at the start of the line after it, so a "chunk of synwait lines" actually contained one line fewer than intended -- and for synwait=1, that boundary always landed back on the current read position, sending an empty chunk and making no progress: an infinite loop, not merely an off-by-one. Fix the boundary search (verified with a 3000-trial fuzz test against random command streams before touching real hardware: no infinite loop, no data loss, correct per-chunk line counts). Separately, _raw_print_label always sent every line at full canvas width starting from dot_tab 0, whatever fraction of that line was actually ink. Real labels are usually mostly blank outside a thin vertical band of content, so this sends far more data than necessary on every single line. Reverse-engineered from a USB capture of DYMO's own Windows software (which never sends a full-height line): trim each line to the byte range containing ink, position it with the (previously unused) _dot_tab command, and batch runs of fully blank lines into a single _skip_lines call instead of full-width zero bytes. Produces the exact same printed image, just far less data per job -- on hardware with a small firmware buffer, the previous encoding could overrun it mid-print and produce visible banding purely from data volume, independent of any USB-level flow control strategy. _dot_tab's bounds check used the generic _max_bytes_per_line(tape_size) formula, which is calibrated for the models it was originally written against; a model with a much larger real addressable range (like the LabelManager Wireless PnP, see the following commit) would have valid dot_tab values incorrectly rejected. DymoLabelerFunctions now accepts an optional max_bytes_per_line override (DymoLabeler._functions passes its DeviceConfig's own print_head_px), falling back to the old formula when not given. It also now skips re-sending ESC B when the value hasn't changed (matching the existing optimization on _bytes_per_line), avoiding redundant commands for the (common) case of several consecutive lines with identical ink extent. Also wires up the existing but previously-unused _cut command as an opt-in `cut` parameter on `print`/`print_label`/`_raw_print_label` (and a new --cut CLI flag), defaulting to False/off to preserve existing behavior for callers/devices that don't want it -- see labelle-org#81, which reported this crashing printers with no cutter when sent unconditionally.
This model's entry has carried a print_head_px=64/print_head_mm=9 placeholder (copy-pasted from other models, ~7.1 px/mm) since it was added, marked "ToDo: Validate config!" and never confirmed -- matching exactly the "squished" output labelle-org#81 reported from this same placeholder. Measured on real hardware three independent ways -- a printed calibration bar's physical width for a known pixel count, the tape distance covered by a fixed-size print batch, and a canvas height that visually filled a 24mm tape edge-to-edge -- all agreeing on ~10.5-10.67 px/mm, and independently corroborated by a decoded USB capture of DYMO's own Windows software using the same scale. print_head_px=256, print_head_mm=24 matches (256/24 ≈ 10.667 px/mm). Also adds 24mm to supported_tape_sizes_mm (physically supported per this model's own datasheet; labelle-org#81 attempted this too, globally rather than per-device) and sets distance_between_print_head_and_cutter_px from this model's own calibration (previously defaulted to a value derived from other models' scale) -- confirmed on hardware to clear the cutter with no content loss, alongside the sparse-encoding and cut fixes from the previous commit. Removes the "not confirmed to work" messaging given the above, plus a full print pipeline exercised end to end on real hardware including the new --cut flag. test_horizontally_combined_render_engine_multiple's golden image is regenerated for the text-centering fix two commits back (unrelated to this commit, just landing in the same golden-image-refresh pass): it renders "Render labelle-org#1/2/3", none of which have descenders, so its previous reference was affected by that same bug. Full render_engines suite: 48/48 (barcode-related tests separately fail in the sandbox this was verified in due to an unrelated python-barcode version mismatch, not a regression here). Thanks to @thinkl33t for the original groundwork in labelle-org#81 -- the auto-cut and 24mm-support ideas here build directly on that; this picks up where it left off per @maresb's request to target develop.
This was referenced Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Picks up where #81 left off, per @maresb's request there to target
developinstead ofmain. Thanks to @thinkl33t for the original groundwork — the auto-cut and 24mm-support ideas here build directly on that PR.DeviceConfig. It's carried aprint_head_px=64/print_head_mm=9placeholder (~7.1 px/mm, copy-pasted from other models) since it was added, marked# ToDo: Validate config!and never confirmed — this is exactly the "squished output" Support for LabelManager Wireless PnP #81 reported. Measured on real hardware three independent ways (a printed calibration bar's physical width for a known pixel count, the tape distance covered by a fixed-size print batch, and a canvas height that visually filled a 24mm tape edge-to-edge), all agreeing on ~10.5–10.67 px/mm, and independently corroborated by a decoded USB capture of DYMO's own Windows software using the same scale.print_head_px=256, print_head_mm=24matches (256/24 ≈ 10.667 px/mm).supported_tape_sizes_mm(physically supported per this model's own datasheet)._cutas an opt-incutparam (print/print_label/_raw_print_label) plus a new--cutCLI flag, defaulting off — Support for LabelManager Wireless PnP #81 found unconditional cut crashes printers without a cutter._send_command's chunk-boundary search: it stopped at the synwait-th SYN character rather than past it, so forsynwait=1the boundary always landed back on the current read position — an empty chunk, no progress, forever. Verified with a 3000-trial fuzz test before touching real hardware.dot_tab0. Real labels are usually mostly blank outside a thin band of content; reverse-engineered from a USB capture of DYMO's own software, which never sends a full-height line. Same printed image, far less data per job — likely why this device's small firmware buffer showed visible banding under the previous encoding, independent of USB-level flow control.Test plan
render_enginestest suite (48/48; apython-barcodeversion mismatch in my sandbox caused unrelated pre-existing failures there, not a regression from this PR)--cutflagruff check/ruff format --checkclean🤖 Generated with Claude Code