Feat/gfc support#83
Conversation
Enterprise-Systeme emittieren GF-Payloads üblicherweise nicht als raw hex oder raw binary, sondern als :B64:<base64>:<crc>-Wrapper. Bisher landeten ^GFB/^GFC unbedingt im browserLimit und ^GFA mit Wrapper im decompressGFA-Pfad, der dort gar nicht greift. Neue Pipeline: parseGfWrapper sniffe das :B64:/:Z64:-Format, validiere CRC-16/CCITT-FALSE, dekodiere Base64 zu Bytes, normalisiere zu Hex und reiche die in den bestehenden Pixel-Pfad weiter. CRC- Mismatch wird gerendert (Zebra tolerieren das auch) aber als partial gemeldet. :Z64: bleibt erstmal browserLimit, weil sync zlib eine zusätzliche Dep oder einen async-Refactor bräuchte.
parseGfWrapper und seine Typen waren exportiert, ohne externe Nutzung —
zusätzliche API-Surface ohne Grund. Außerdem das viermal duplizierte
'^GF${rest.slice(0, 80)}…' in eine lokale Konstante gehoben.
Z64 ist real-world die Standard-Form für komprimierte ZPL-Grafiken aus Enterprise-Systemen (SAP/Oracle/etc.); B64 alleine reicht für hochauflösende Logos nicht, weil dann doch Base64 von rohen Bitmap-Bytes übrigbleibt. fflate.unzlibSync deckt sync inflate ohne async-Refactor ab (MIT, ~13 KB gzip). Magic numbers an einer Stelle benannt: CRC16_CCITT_POLY, CRC16_MASK, CRC_HEX_DIGITS, IMPORT_FINDING_PAYLOAD_LIMIT. Polynomial und Maskenwerte sind CRC-Standardkonstanten und bleiben hex; nur die Namensvergabe verschiebt die Bedeutung von 'magic' nach 'spec'.
GF-Handler war 100 Zeilen mit vier Abstraction-Levels in einem Block: Command-Tokenparsing, Payload-Normalisierung (B64/Z64/RLE/bail), Pixel-Painting, Cache-Anbindung. gfPayloadToHex isoliert die zweite Stufe als pures Helper-Pair (parseGfWrapper + Inflate) und nimmt aus dem Handler die ganze if-Treppe raus.
Zwei mutable Patterns ersetzt: 'let bytes; if (z64) bytes = inflate(…)'
und 'let bytes; try { bytes = decodeBase64() }' werden zu 'const bytes ='
Ausdrücken über tryInflateZlib bzw. base64ToBytes. Die try/catches sind
in die Helpers gewandert, sodass die Aufrufer als reine Datenflüsse
lesen.
There was a problem hiding this comment.
Code Review
This pull request introduces support for :B64: and :Z64: (zlib-compressed) wrappers in ZPL ^GF graphic commands, utilizing the fflate library for decompression. It adds CRC-16/CCITT-FALSE validation and updates the parser to handle ^GFB and ^GFC formats alongside existing RLE-hex data. Review feedback focuses on significant performance optimizations for large graphic payloads, specifically recommending a refactor to use Uint8Array directly to avoid redundant hex-to-string conversions. Other suggestions include replacing greedy regular expressions with more efficient string splitting and ensuring robustness against trailing whitespace in ZPL commands.
- parseGfWrapper.trim() vor dem Regex-Match — Tokenizer behält trailing \n auf rest, ohne trim hätte das Pattern jedes real-world Label mit Zeilenumbrüchen verfehlt. Neuer Test deckt das ab. - gfPayloadToHex → gfPayloadToBytes: Uint8Array statt Hex-String durch- reichen spart 30k+ String-Slice + parseInt-Calls in der Paint-Loop bei mittelgroßen Logos. bytesToHex weg; gfaHexToBytes als Brücke für den decompressGFA-Pfad. - _gfaCache erhält den originalen Format-Buchstaben (A/B/C). War hardcoded auf 'A'; mit B/C-Support hätte ein ^GFC,:Z64:… als ^GFA,:Z64:… re-exportiert, was Zebra/Labelary ablehnen. - Veralteten Kommentar zu :Z64:-Support entfernt (ist seit fflate aktiv).
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for :B64: and :Z64: (zlib-compressed) wrappers within ZPL ^GF (Graphic Field) commands by adding the fflate dependency. The parser is refactored to handle ^GFA, ^GFB, and ^GFC formats, normalizing payloads into byte arrays for more efficient rendering. Review feedback identifies a critical correction for the CRC-16/CCITT-FALSE initial value (which should be 0xFFFF), suggests allowing and stripping whitespace in base64 payloads to accommodate common ZPL formatting, and recommends performance optimizations for hex-to-byte conversion.
…espace, faster hex decode - CRC ist CRC-16/XMODEM (init=0), nicht CCITT-FALSE (init=0xFFFF). Mein vorheriger Kommentar war fehlbenannt — Gemini ist auf die Bezeichnung reingefallen und hat init=0xFFFF empfohlen. Empirisch via Labelary bestätigt: XMODEM-CRC wird akzeptiert, CCITT-FALSE abgelehnt. Umbenannt zu crc16Xmodem. - GF_WRAPPER_RE erlaubt jetzt \s im base64-Anteil; parseGfWrapper stripped Whitespace vor atob/CRC. Real-world ZPL bricht große Payloads auf ~80 Char/Zeile um. Neuer Test deckt das ab. - gfaHexToBytes nutzt jetzt Index-Zugriff + Nibble-Shift statt parseInt über Slices — wegen `noUncheckedIndexedAccess` mit ?? '0'-Fallback. - Veralteten Kommentar zu :Z64:-Limit aus dem GF-Handler entfernt.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for :B64: and :Z64: wrapped payloads in ZPL ^GF commands, integrating the fflate library for zlib decompression and implementing CRC-16/XMODEM validation. The ^GF command handler was refactored to support formats A, B, and C while optimizing hex-to-bytes conversion. Reviewers identified performance bottlenecks in the bit-by-bit CRC calculation and the hex parsing logic for large bitmaps, suggesting table-based implementations. Additionally, feedback was provided to preserve original command parameters in the internal cache to maintain round-trip stability for compressed data.
…ming - _gfaCache übernimmt totalBytes/dataBytes aus den Original-Params statt beide auf gfBytes.length zu setzen. Bei :Z64: sind die zwei Werte unterschiedlich (uncompressed vs. on-wire), und die Firmware nutzt den zweiten für die Buffer-Allocation beim Re-Import. - crc16Xmodem-JSDoc neben die Funktion gezogen (saß deplatziert vor einer Konstante). - parseGfWrapper-JSDoc sagte noch 'CRC-16/CCITT-FALSE' — das war genau der Stolperdraht, der Geminis fehlerhafte HIGH-Suggestion ausgelöst hat. Auf XMODEM korrigiert. - CRC16_CCITT_POLY → CRC16_POLY: das Polynom 0x1021 gehört zu mehreren CRC-Varianten; kontextfreier Name verhindert die nächste Verwirrung. Andere Gemini-Findings aus dieser Runde übersprungen: die meisten zitieren altes Code-Snippets (Stale-Cache im Review-Bot), das HIGH-Finding zur CRC-init wurde empirisch via Labelary widerlegt (XMODEM-CRC akzeptiert, CCITT-FALSE abgelehnt), LUT-Optimierungen ohne Messung als Beleg sind spekulativ.
No description provided.