|
| 1 | +# Native GS1 Composite 2D component |
| 2 | + |
| 3 | +This feature branch builds a dependency-free GS1 Composite Component on the |
| 4 | +shared PDF417 foundation from `feat/pdf417-core`. It generates the complete 2D |
| 5 | +component as an unscaled `boolean[][]` module matrix: |
| 6 | + |
| 7 | +- CC-A using all 17 Composite-specific MicroPDF417 layouts; |
| 8 | +- CC-B using the standardized MicroPDF417 layouts and the Composite linkage |
| 9 | + codeword; |
| 10 | +- CC-C using standard PDF417 layouts, adaptive error correction, and the |
| 11 | + Composite linkage codeword. |
| 12 | + |
| 13 | +The runtime imports no BWIPP or ZXing code. BWIPP is used only outside the |
| 14 | +repository to produce deterministic development references. The committed |
| 15 | +tests contain the resulting SHA-256 module fingerprints. |
| 16 | + |
| 17 | +## API |
| 18 | + |
| 19 | +```js |
| 20 | +import { Gs1CompositeCore } from '../libs/GS1CompositeCore.js' |
| 21 | + |
| 22 | +const component = new Gs1CompositeCore( |
| 23 | + '(01)09521234543213(3103)000123', |
| 24 | + { version: 'a', columns: 3 }, |
| 25 | +).generate() |
| 26 | +``` |
| 27 | + |
| 28 | +`version` accepts `auto`, `a`, `b`, or `c`. CC-A and CC-B accept two through |
| 29 | +four data columns. CC-C accepts one through 30 columns and may increase the |
| 30 | +requested column count when the symbol would otherwise exceed 30 rows. |
| 31 | + |
| 32 | +The result contains: |
| 33 | + |
| 34 | +```js |
| 35 | +{ |
| 36 | + modules, // boolean[][], no scaling or quiet zone |
| 37 | + rows, |
| 38 | + columns, // actual module columns |
| 39 | + dataColumns, |
| 40 | + dataCodewords, |
| 41 | + errorCodewords, |
| 42 | + codewords, |
| 43 | + bits, // padded Composite data bit stream |
| 44 | + bitCapacity, |
| 45 | + version, // CC-A, CC-B, or CC-C |
| 46 | + variant, |
| 47 | + method, |
| 48 | + elements, |
| 49 | + rowAddressPatterns, // present for CC-A and CC-B |
| 50 | +} |
| 51 | +``` |
| 52 | + |
| 53 | +Bracketed AI syntax with either parentheses or square brackets is accepted. |
| 54 | +An already assembled GS1 element string can instead use ASCII Group Separator |
| 55 | +(`\x1d`) between variable-length fields. |
| 56 | + |
| 57 | +## Shared PDF417 architecture |
| 58 | + |
| 59 | +`GS1CompositeCore.js` owns only Composite sizing, linkage, and orchestration. |
| 60 | +It reuses: |
| 61 | + |
| 62 | +- the 3 × 929 PDF417 codeword pattern table; |
| 63 | +- Reed-Solomon error correction modulo 929; |
| 64 | +- byte compaction for CC-B and CC-C; |
| 65 | +- the MicroPDF417 Row Address Patterns and matrix builder; |
| 66 | +- the standard PDF417 row-indicator and matrix builder. |
| 67 | + |
| 68 | +The shared matrix functions and constants are exported from `PDF417core.js`. |
| 69 | +The existing public PDF417 and MicroPDF417 classes continue to call those same |
| 70 | +functions, so this extraction does not create a second implementation. |
| 71 | + |
| 72 | +## Data encodation |
| 73 | + |
| 74 | +The current core implements GS1 Composite encodation method 0 and the complete |
| 75 | +general-purpose field state machine: numeric, alphanumeric, ISO/IEC 646, |
| 76 | +latches, FNC1, terminal digit handling, and capacity-specific padding. Method 0 |
| 77 | +is valid for arbitrary GS1 element strings. Optional encodation methods 10 and |
| 78 | +11, which compress certain leading AIs such as 10, 11, 17, and 90 more tightly, |
| 79 | +are not yet implemented. Such inputs still generate valid symbols through |
| 80 | +method 0 but can select a larger component. |
| 81 | + |
| 82 | +The lightweight bracket parser identifies the fixed-length AI families needed |
| 83 | +to place FNC1 separators. It does not act as a full GS1 data validator. Callers |
| 84 | +that already validate against a current GS1 application-identifier table can |
| 85 | +pass the canonical element string form directly. |
| 86 | + |
| 87 | +## Linear component boundary |
| 88 | + |
| 89 | +This core deliberately returns the native **2D Composite Component**. A complete |
| 90 | +printed GS1 Composite symbol also needs a linked linear component (EAN/UPC, |
| 91 | +GS1-128, or a GS1 DataBar family), its linkage flag, separator pattern, and |
| 92 | +alignment. Those linear encoders remain independent barcode-family modules and |
| 93 | +can consume this matrix later. Keeping that composition outside this core avoids |
| 94 | +introducing a hidden dependency on one particular linear symbology. |
| 95 | + |
| 96 | +For a future ZPL integration, `^BR` mode 11 can combine a GS1-128 core with CC-A |
| 97 | +or CC-B, while mode 12 can combine GS1-128 with CC-C. Painting, row-height |
| 98 | +scaling, orientation, separator placement, and ZPL field positioning belong in |
| 99 | +the ZPL renderer rather than this symbol core. |
| 100 | + |
| 101 | +## Verification |
| 102 | + |
| 103 | +The deterministic tests cover all CC-A layout declarations, capacity maps, |
| 104 | +FNC1 insertion, validation, repeated generation, a large CC-C symbol, and exact |
| 105 | +module fingerprints for CC-A/B/C. The reference set exercises numeric, |
| 106 | +alphanumeric, lowercase ISO/IEC 646, punctuation, and every CC-A/CC-B column |
| 107 | +count. During development all reference matrices were compared module-for-module |
| 108 | +with BWIPP and had zero differing modules. |
| 109 | + |
| 110 | +The repository's ZXing dependency remains development-only. Its JavaScript |
| 111 | +PDF417 reader does not expose GS1 Composite decoding, so it is not used as a |
| 112 | +second decoder for these tests. |
| 113 | + |
| 114 | +## References |
| 115 | + |
| 116 | +- [ISO/IEC 24723, GS1 Composite bar code symbology](https://www.iso.org/standard/75193.html) |
| 117 | +- [GS1 General Specifications](https://www.gs1.org/standards/barcodes-epcrfid-id-keys/gs1-general-specifications) |
| 118 | +- [Barcode Writer in Pure PostScript](https://github.com/bwipp/postscriptbarcode) |
| 119 | +- [Zebra `^BR` command](https://docs.zebra.com/us/en/printers/software/zpl-pg/zpl-commands/%5Ebr.html) |
0 commit comments