@sythos/js_barcode_universal 1.3.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/AI_USAGE.md +33 -0
  2. package/LICENSE +4 -2
  3. package/NOTICE.md +8 -5
  4. package/README.md +74 -23
  5. package/bundle/sythos-barcode.esm.js +2313 -92
  6. package/bundle/sythos-barcode.js +2229 -88
  7. package/examples/create.html +2 -1
  8. package/examples/read.html +1 -0
  9. package/licenses/README.md +6 -1
  10. package/licenses/aztec-rune.license +76 -0
  11. package/licenses/compact-pdf417.license +76 -0
  12. package/licenses/ean-2.license +74 -0
  13. package/licenses/ean-5.license +74 -0
  14. package/licenses/frameqr.license +6 -6
  15. package/licenses/gs1-databar.license +81 -0
  16. package/package.json +16 -4
  17. package/src/aztec/decoder.js +1 -0
  18. package/src/aztec/detector.js +1 -0
  19. package/src/aztec/encoder.js +1 -0
  20. package/src/aztec/high-level.js +1 -0
  21. package/src/aztec/index.js +1 -0
  22. package/src/aztec/tables.js +1 -0
  23. package/src/aztecrune/decoder.js +156 -0
  24. package/src/aztecrune/detector.js +167 -0
  25. package/src/aztecrune/encoder.js +122 -0
  26. package/src/aztecrune/index.js +50 -0
  27. package/src/aztecrune/tables.js +138 -0
  28. package/src/compactpdf417/decoder.js +129 -0
  29. package/src/compactpdf417/detector.js +140 -0
  30. package/src/compactpdf417/encoder.js +141 -0
  31. package/src/compactpdf417/index.js +22 -0
  32. package/src/compactpdf417/tables.js +174 -0
  33. package/src/core/bit-buffer.js +1 -0
  34. package/src/core/bit-matrix.js +1 -0
  35. package/src/core/errors.js +1 -0
  36. package/src/core/galois-field.js +1 -0
  37. package/src/core/index.js +1 -0
  38. package/src/core/reed-solomon.js +1 -0
  39. package/src/databar/codec.js +182 -0
  40. package/src/databar/decoder.js +115 -0
  41. package/src/databar/encoder.js +97 -0
  42. package/src/databar/gs1.js +178 -0
  43. package/src/databar/index.js +69 -0
  44. package/src/databar/patterns.js +144 -0
  45. package/src/databar/tables.js +125 -0
  46. package/src/datamatrix/decoder.js +1 -0
  47. package/src/datamatrix/detector.js +1 -0
  48. package/src/datamatrix/encoder.js +1 -0
  49. package/src/datamatrix/index.js +1 -0
  50. package/src/datamatrix/tables.js +1 -0
  51. package/src/frameqr/decoder.js +16 -15
  52. package/src/frameqr/detector.js +3 -2
  53. package/src/frameqr/encoder.js +8 -7
  54. package/src/frameqr/index.js +1 -0
  55. package/src/frameqr/tables.js +11 -10
  56. package/src/image/binarizer.js +1 -0
  57. package/src/image/grid-sampler.js +1 -0
  58. package/src/image/index.js +1 -0
  59. package/src/image/luminance.js +1 -0
  60. package/src/image/perspective.js +1 -0
  61. package/src/index.js +72 -8
  62. package/src/micropdf417/compaction.js +1 -0
  63. package/src/micropdf417/decoder.js +1 -0
  64. package/src/micropdf417/detector.js +1 -0
  65. package/src/micropdf417/encoder.js +1 -0
  66. package/src/micropdf417/error-correction.js +1 -0
  67. package/src/micropdf417/index.js +1 -0
  68. package/src/micropdf417/tables.js +1 -0
  69. package/src/microqr/decoder.js +1 -0
  70. package/src/microqr/detector.js +1 -0
  71. package/src/microqr/encoder.js +1 -0
  72. package/src/microqr/index.js +1 -0
  73. package/src/microqr/tables.js +1 -0
  74. package/src/oned/addons.js +421 -0
  75. package/src/oned/index.js +18 -0
  76. package/src/oned/patterns.js +1 -0
  77. package/src/oned/reader.js +1 -0
  78. package/src/oned/writers.js +1 -0
  79. package/src/pdf417/compaction.js +1 -0
  80. package/src/pdf417/decoder.js +1 -0
  81. package/src/pdf417/detector.js +1 -0
  82. package/src/pdf417/encoder.js +1 -0
  83. package/src/pdf417/error-correction.js +1 -0
  84. package/src/pdf417/index.js +5 -0
  85. package/src/pdf417/tables.js +1 -0
  86. package/src/qr/decoder.js +1 -0
  87. package/src/qr/detector.js +1 -0
  88. package/src/qr/encoder.js +1 -0
  89. package/src/qr/index.js +1 -0
  90. package/src/qr/tables.js +1 -0
  91. package/src/render/image-data.js +1 -0
  92. package/src/render/index.js +1 -0
  93. package/src/render/options.js +1 -0
  94. package/src/render/png.js +1 -0
  95. package/src/render/svg.js +1 -0
  96. package/src/render/webgl.js +1 -0
  97. package/src/render/webgpu.js +1 -0
  98. package/src/rmqr/decoder.js +1 -0
  99. package/src/rmqr/detector.js +1 -0
  100. package/src/rmqr/encoder.js +1 -0
  101. package/src/rmqr/index.js +1 -0
  102. package/src/rmqr/tables.js +1 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Sythos Barcode Suite v1.3.1
2
+ * Sythos Barcode Suite v1.4.1
3
3
  *
4
4
  * MIT License
5
5
  *
@@ -1822,6 +1822,413 @@ __exports.encodeMSI = encodeMSI;
1822
1822
  __exports.encodePharmacode = encodePharmacode;
1823
1823
  };
1824
1824
 
1825
+ __modules["oned/addons.js"] = function (__require, __exports) {
1826
+ /**
1827
+ * UPC/EAN two- and five-digit supplements.
1828
+ *
1829
+ * Supplements are small symbols printed to the right of an EAN/UPC symbol.
1830
+ * They use the ordinary EAN odd/even digit patterns, a 1011 start guard and
1831
+ * 01 separators between digits. EAN-2 selects its parity from the numeric
1832
+ * value modulo four. EAN-5 derives a checksum from the five digits and uses
1833
+ * that value to select one of ten parity rows.
1834
+ *
1835
+ * This module intentionally keeps supplements separate from the base EAN/UPC
1836
+ * writers. `composeEANAddon` and the `*WithAddon` helpers are opt-in; existing
1837
+ * EAN/UPC APIs continue to return their original one-row matrices unchanged.
1838
+ *
1839
+ * @module oned/addons
1840
+ */
1841
+ const { BitMatrix } = __require("core/bit-matrix.js");
1842
+ const { EncodeError, FormatError } = __require("core/errors.js");
1843
+ const { EAN_L, EAN_G } = __require("oned/patterns.js");
1844
+ const { encodeEAN13, encodeEAN8, encodeUPCA, encodeUPCE } = __require("oned/writers.js");
1845
+
1846
+ /** EAN-2 parity rows, indexed by the two-digit value modulo four. */
1847
+ const EAN2_PARITY = Object.freeze([
1848
+ 'AA', 'AB', 'BA', 'BB',
1849
+ ]);
1850
+
1851
+ /** EAN-5 parity rows, indexed by the supplemental checksum. */
1852
+ const EAN5_PARITY = Object.freeze([
1853
+ 'BBAAA', 'BABAA', 'BAABA', 'BAAAB', 'ABBAA',
1854
+ 'AABBA', 'AAABB', 'ABABA', 'ABAAB', 'AABAB',
1855
+ ]);
1856
+
1857
+ /** Start guard used by both UPC/EAN supplemental symbols. */
1858
+ const EAN_ADDON_START = '1011';
1859
+
1860
+ /** Separator inserted between adjacent supplemental digits. */
1861
+ const EAN_ADDON_SEPARATOR = '01';
1862
+ const EAN2_WIDTH = EAN_ADDON_START.length + 2 * 7 + EAN_ADDON_SEPARATOR.length;
1863
+ const EAN5_WIDTH = EAN_ADDON_START.length + 5 * 7 + EAN_ADDON_SEPARATOR.length * 4;
1864
+
1865
+ /**
1866
+ * @param {unknown} value
1867
+ * @param {number} length
1868
+ * @param {string} format
1869
+ * @returns {string}
1870
+ */
1871
+ function normalizeDigits(value, length, format) {
1872
+ const digits = String(value);
1873
+ if (!new RegExp(`^[0-9]{${length}}$`).test(digits)) {
1874
+ throw new EncodeError(`${format}: payload must contain exactly ${length} digits`);
1875
+ }
1876
+ return digits;
1877
+ }
1878
+
1879
+ /**
1880
+ * EAN-5 supplemental checksum.
1881
+ *
1882
+ * The first, third and fifth digits carry weight three; the second and fourth
1883
+ * carry weight nine. The checksum is not printed as a sixth digit: it selects
1884
+ * the odd/even parity row for the five encoded digits.
1885
+ *
1886
+ * @param {string|number} value Five digits.
1887
+ * @returns {number} Checksum value, 0-9.
1888
+ */
1889
+ function ean5Checksum(value) {
1890
+ const digits = normalizeDigits(value, 5, 'EAN-5');
1891
+ const weighted =
1892
+ 3 * (Number(digits[0]) + Number(digits[2]) + Number(digits[4])) +
1893
+ 9 * (Number(digits[1]) + Number(digits[3]));
1894
+ return weighted % 10;
1895
+ }
1896
+
1897
+ /** Alias for callers that use the EAN family check-digit terminology. */
1898
+ const ean5CheckDigit = ean5Checksum;
1899
+
1900
+ /**
1901
+ * Resolve the EAN-2 parity row for a payload.
1902
+ *
1903
+ * @param {string|number} value Two digits.
1904
+ * @returns {string} Two-character A/B parity row.
1905
+ */
1906
+ function ean2Parity(value) {
1907
+ const digits = normalizeDigits(value, 2, 'EAN-2');
1908
+ return EAN2_PARITY[Number(digits) % 4];
1909
+ }
1910
+
1911
+ /**
1912
+ * Resolve the EAN-5 parity row for a payload.
1913
+ *
1914
+ * @param {string|number} value Five digits.
1915
+ * @returns {string} Five-character A/B parity row.
1916
+ */
1917
+ function ean5Parity(value) {
1918
+ return EAN5_PARITY[ean5Checksum(value)];
1919
+ }
1920
+
1921
+ /**
1922
+ * Expand an A/B parity row into EAN digit patterns.
1923
+ *
1924
+ * @param {string} digits
1925
+ * @param {string} parity
1926
+ * @returns {string}
1927
+ */
1928
+ function encodeDigitPatterns(digits, parity) {
1929
+ let modules = EAN_ADDON_START;
1930
+ for (let i = 0; i < digits.length; i++) {
1931
+ if (i > 0) modules += EAN_ADDON_SEPARATOR;
1932
+ const table = parity[i] === 'A' ? EAN_L : EAN_G;
1933
+ modules += table[Number(digits[i])];
1934
+ }
1935
+ return modules;
1936
+ }
1937
+
1938
+ /**
1939
+ * Turn a module string into a one-row matrix and attach immutable source
1940
+ * metadata for composition/rendering callers.
1941
+ *
1942
+ * @param {string} modules
1943
+ * @param {{format: string, text: string, parity: string, checksum?: number}} metadata
1944
+ * @returns {BitMatrix}
1945
+ */
1946
+ function toAddonMatrix(modules, metadata) {
1947
+ const matrix = new BitMatrix(modules.length, 1);
1948
+ for (let x = 0; x < modules.length; x++) {
1949
+ if (modules[x] === '1') matrix.set(x, 0);
1950
+ }
1951
+ matrix.eanAddon = Object.freeze({ ...metadata });
1952
+ return matrix;
1953
+ }
1954
+
1955
+ /**
1956
+ * Encode an EAN-2 supplement.
1957
+ *
1958
+ * @param {string|number} value Exactly two decimal digits.
1959
+ * @returns {BitMatrix} A 20-module, one-row supplement.
1960
+ */
1961
+ function encodeEAN2(value) {
1962
+ const digits = normalizeDigits(value, 2, 'EAN-2');
1963
+ const parity = ean2Parity(digits);
1964
+ const matrix = toAddonMatrix(encodeDigitPatterns(digits, parity), {
1965
+ format: 'ean2',
1966
+ text: digits,
1967
+ parity,
1968
+ });
1969
+ if (matrix.width !== EAN2_WIDTH) {
1970
+ throw new EncodeError(`EAN-2: internal width is ${matrix.width}, expected ${EAN2_WIDTH}`);
1971
+ }
1972
+ return matrix;
1973
+ }
1974
+
1975
+ /**
1976
+ * Encode an EAN-5 supplement.
1977
+ *
1978
+ * @param {string|number} value Exactly five decimal digits.
1979
+ * @returns {BitMatrix} A 47-module, one-row supplement.
1980
+ */
1981
+ function encodeEAN5(value) {
1982
+ const digits = normalizeDigits(value, 5, 'EAN-5');
1983
+ const checksum = ean5Checksum(digits);
1984
+ const parity = EAN5_PARITY[checksum];
1985
+ const matrix = toAddonMatrix(encodeDigitPatterns(digits, parity), {
1986
+ format: 'ean5',
1987
+ text: digits,
1988
+ parity,
1989
+ checksum,
1990
+ });
1991
+ if (matrix.width !== EAN5_WIDTH) {
1992
+ throw new EncodeError(`EAN-5: internal width is ${matrix.width}, expected ${EAN5_WIDTH}`);
1993
+ }
1994
+ return matrix;
1995
+ }
1996
+
1997
+ /**
1998
+ * Encode either supported supplement length.
1999
+ *
2000
+ * @param {string|number} value Two or five decimal digits.
2001
+ * @returns {BitMatrix}
2002
+ */
2003
+ function encodeEANAddon(value) {
2004
+ const digits = String(value);
2005
+ if (digits.length === 2) return encodeEAN2(digits);
2006
+ if (digits.length === 5) return encodeEAN5(digits);
2007
+ throw new EncodeError('EAN add-on: payload must contain exactly two or five digits');
2008
+ }
2009
+
2010
+ /** Alias using the spelling used by some EAN documentation. */
2011
+ const encodeEANAddOn = encodeEANAddon;
2012
+
2013
+ /**
2014
+ * @param {BitMatrix} matrix
2015
+ * @param {number} offset
2016
+ * @param {string} pattern
2017
+ * @returns {boolean}
2018
+ */
2019
+ function matches(matrix, offset, pattern) {
2020
+ if (offset < 0 || offset + pattern.length > matrix.width) return false;
2021
+ for (let i = 0; i < pattern.length; i++) {
2022
+ if ((matrix.get(offset + i, 0) ? '1' : '0') !== pattern[i]) return false;
2023
+ }
2024
+ return true;
2025
+ }
2026
+
2027
+ /**
2028
+ * @param {BitMatrix} matrix
2029
+ * @param {number} start
2030
+ * @param {2|5} digitCount
2031
+ * @returns {{format:string,text:string,parity:string,checksum?:number,end:number}|null}
2032
+ */
2033
+ function decodeAt(matrix, start, digitCount) {
2034
+ const width = digitCount === 2 ? EAN2_WIDTH : EAN5_WIDTH;
2035
+ if (!matches(matrix, start, EAN_ADDON_START)) return null;
2036
+ if (start > 0 && matrix.get(start - 1, 0)) return null;
2037
+
2038
+ let offset = start + EAN_ADDON_START.length;
2039
+ let text = '';
2040
+ let parity = '';
2041
+
2042
+ for (let i = 0; i < digitCount; i++) {
2043
+ let found = null;
2044
+ for (let digit = 0; digit < 10; digit++) {
2045
+ for (const [letter, table] of [['A', EAN_L], ['B', EAN_G]]) {
2046
+ if (matches(matrix, offset, table[digit]) &&
2047
+ (!found || found.letter !== letter || found.digit !== digit)) {
2048
+ if (found) return null;
2049
+ found = { digit, letter };
2050
+ }
2051
+ }
2052
+ }
2053
+ if (!found) return null;
2054
+ text += String(found.digit);
2055
+ parity += found.letter;
2056
+ offset += 7;
2057
+ if (i < digitCount - 1) {
2058
+ if (!matches(matrix, offset, EAN_ADDON_SEPARATOR)) return null;
2059
+ offset += EAN_ADDON_SEPARATOR.length;
2060
+ }
2061
+ }
2062
+
2063
+ if (offset - start !== width) return null;
2064
+ if (digitCount === 2) {
2065
+ if (EAN2_PARITY[Number(text) % 4] !== parity) return null;
2066
+ return { format: 'ean2', text, parity, end: offset };
2067
+ }
2068
+
2069
+ const checksum = ean5Checksum(text);
2070
+ if (EAN5_PARITY[checksum] !== parity) return null;
2071
+ return { format: 'ean5', text, parity, checksum, end: offset };
2072
+ }
2073
+
2074
+ /**
2075
+ * Validate and decode an EAN-2 supplement. A leading quiet zone is accepted;
2076
+ * the decoder searches the row for a valid start guard so a composed base
2077
+ * EAN/UPC matrix can be passed directly as well.
2078
+ *
2079
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
2080
+ * @returns {{format:'ean2',text:string,parity:string}}
2081
+ * @throws {FormatError} When no valid supplement is found.
2082
+ */
2083
+ function decodeEAN2(matrix) {
2084
+ if (!matrix || !Number.isInteger(matrix.width) || matrix.height !== 1) {
2085
+ throw new FormatError('EAN-2: expected a one-row module matrix');
2086
+ }
2087
+ for (let start = 0; start + EAN2_WIDTH <= matrix.width; start++) {
2088
+ const result = decodeAt(matrix, start, 2);
2089
+ if (result) {
2090
+ const { end, ...publicResult } = result;
2091
+ void end;
2092
+ return publicResult;
2093
+ }
2094
+ }
2095
+ throw new FormatError('EAN-2: start, parity or digit pattern is invalid');
2096
+ }
2097
+
2098
+ /**
2099
+ * Validate and decode an EAN-5 supplement.
2100
+ *
2101
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
2102
+ * @returns {{format:'ean5',text:string,parity:string,checksum:number}}
2103
+ * @throws {FormatError} When no valid supplement is found.
2104
+ */
2105
+ function decodeEAN5(matrix) {
2106
+ if (!matrix || !Number.isInteger(matrix.width) || matrix.height !== 1) {
2107
+ throw new FormatError('EAN-5: expected a one-row module matrix');
2108
+ }
2109
+ for (let start = 0; start + EAN5_WIDTH <= matrix.width; start++) {
2110
+ const result = decodeAt(matrix, start, 5);
2111
+ if (result) {
2112
+ const { end, ...publicResult } = result;
2113
+ void end;
2114
+ return publicResult;
2115
+ }
2116
+ }
2117
+ throw new FormatError('EAN-5: start, parity, checksum or digit pattern is invalid');
2118
+ }
2119
+
2120
+ /**
2121
+ * Decode either supported supplement length.
2122
+ *
2123
+ * @param {BitMatrix} matrix One-row, module-aligned supplement or composition.
2124
+ * @returns {{format:'ean2'|'ean5',text:string,parity:string,checksum?:number}}
2125
+ * @throws {FormatError} When neither supplement grammar matches.
2126
+ */
2127
+ function decodeEANAddon(matrix) {
2128
+ try {
2129
+ return decodeEAN5(matrix);
2130
+ } catch (fiveError) {
2131
+ try {
2132
+ return decodeEAN2(matrix);
2133
+ } catch (twoError) {
2134
+ throw new FormatError(`EAN add-on: ${fiveError.message}; ${twoError.message}`);
2135
+ }
2136
+ }
2137
+ }
2138
+
2139
+ /** Alias using the spelling used by some EAN documentation. */
2140
+ const decodeEANAddOn = decodeEANAddon;
2141
+
2142
+ /**
2143
+ * Join a base EAN/UPC matrix and a supplement with the standard quiet gap.
2144
+ *
2145
+ * The helper does not alter either input. By default it inserts nine light
2146
+ * modules, the conventional separation between the base symbol and an add-on.
2147
+ * The result carries the supplement metadata under `eanAddon` for renderers or
2148
+ * callers that need to label the composed symbol.
2149
+ *
2150
+ * @param {BitMatrix} base Base EAN/UPC matrix.
2151
+ * @param {BitMatrix|string|number} addon Add-on matrix or two/five digits.
2152
+ * @param {{gap?:number}} [options]
2153
+ * @returns {BitMatrix}
2154
+ */
2155
+ function composeEANAddon(base, addon, options = {}) {
2156
+ if (!base || !Number.isInteger(base.width) || base.height !== 1) {
2157
+ throw new TypeError('EAN add-on: base must be a one-row module matrix');
2158
+ }
2159
+ const addonMatrix = typeof addon === 'string' || typeof addon === 'number'
2160
+ ? encodeEANAddon(addon)
2161
+ : addon;
2162
+ if (!addonMatrix || !Number.isInteger(addonMatrix.width) || addonMatrix.height !== 1) {
2163
+ throw new TypeError('EAN add-on: supplement must be a one-row module matrix or digits');
2164
+ }
2165
+
2166
+ const gap = options.gap === undefined ? 9 : Number(options.gap);
2167
+ if (!Number.isInteger(gap) || gap < 1) {
2168
+ throw new EncodeError(`EAN add-on: gap must be a positive integer, got ${options.gap}`);
2169
+ }
2170
+
2171
+ const result = new BitMatrix(base.width + gap + addonMatrix.width, 1);
2172
+ for (let x = 0; x < base.width; x++) if (base.get(x, 0)) result.set(x, 0);
2173
+ for (let x = 0; x < addonMatrix.width; x++) {
2174
+ if (addonMatrix.get(x, 0)) result.set(base.width + gap + x, 0);
2175
+ }
2176
+ if (addonMatrix.eanAddon) result.eanAddon = { ...addonMatrix.eanAddon, gap };
2177
+ return result;
2178
+ }
2179
+
2180
+ /**
2181
+ * Compose an EAN-13 symbol with an EAN-2 or EAN-5 supplement.
2182
+ *
2183
+ * @param {string} value Base EAN-13 payload.
2184
+ * @param {string|number} addon Two or five supplemental digits.
2185
+ * @param {{gap?:number}} [options]
2186
+ * @returns {BitMatrix}
2187
+ */
2188
+ function encodeEAN13WithAddon(value, addon, options = {}) {
2189
+ return composeEANAddon(encodeEAN13(value), addon, options);
2190
+ }
2191
+
2192
+ /** @see encodeEAN13WithAddon */
2193
+ function encodeEAN8WithAddon(value, addon, options = {}) {
2194
+ return composeEANAddon(encodeEAN8(value), addon, options);
2195
+ }
2196
+
2197
+ /** @see encodeEAN13WithAddon */
2198
+ function encodeUPCAWithAddon(value, addon, options = {}) {
2199
+ return composeEANAddon(encodeUPCA(value), addon, options);
2200
+ }
2201
+
2202
+ /** @see encodeEAN13WithAddon */
2203
+ function encodeUPCEWithAddon(value, addon, options = {}) {
2204
+ return composeEANAddon(encodeUPCE(value), addon, options);
2205
+ }
2206
+
2207
+ __exports.EAN2_PARITY = EAN2_PARITY;
2208
+ __exports.EAN5_PARITY = EAN5_PARITY;
2209
+ __exports.EAN_ADDON_START = EAN_ADDON_START;
2210
+ __exports.EAN_ADDON_SEPARATOR = EAN_ADDON_SEPARATOR;
2211
+ __exports.EAN2_WIDTH = EAN2_WIDTH;
2212
+ __exports.EAN5_WIDTH = EAN5_WIDTH;
2213
+ __exports.ean5Checksum = ean5Checksum;
2214
+ __exports.ean5CheckDigit = ean5CheckDigit;
2215
+ __exports.ean2Parity = ean2Parity;
2216
+ __exports.ean5Parity = ean5Parity;
2217
+ __exports.encodeEAN2 = encodeEAN2;
2218
+ __exports.encodeEAN5 = encodeEAN5;
2219
+ __exports.encodeEANAddon = encodeEANAddon;
2220
+ __exports.encodeEANAddOn = encodeEANAddOn;
2221
+ __exports.decodeEAN2 = decodeEAN2;
2222
+ __exports.decodeEAN5 = decodeEAN5;
2223
+ __exports.decodeEANAddon = decodeEANAddon;
2224
+ __exports.decodeEANAddOn = decodeEANAddOn;
2225
+ __exports.composeEANAddon = composeEANAddon;
2226
+ __exports.encodeEAN13WithAddon = encodeEAN13WithAddon;
2227
+ __exports.encodeEAN8WithAddon = encodeEAN8WithAddon;
2228
+ __exports.encodeUPCAWithAddon = encodeUPCAWithAddon;
2229
+ __exports.encodeUPCEWithAddon = encodeUPCEWithAddon;
2230
+ };
2231
+
1825
2232
  __modules["oned/reader.js"] = function (__require, __exports) {
1826
2233
  /**
1827
2234
  * Linear barcode reading.
@@ -2715,7 +3122,10 @@ __modules["oned/index.js"] = function (__require, __exports) {
2715
3122
  * Linear symbologies.
2716
3123
  *
2717
3124
  * @module oned
2718
- */
3125
+ */
3126
+ const __reexport1 = __require("oned/addons.js"); __exports.EAN2_PARITY = __reexport1.EAN2_PARITY; __exports.EAN5_PARITY = __reexport1.EAN5_PARITY; __exports.EAN2_WIDTH = __reexport1.EAN2_WIDTH; __exports.EAN5_WIDTH = __reexport1.EAN5_WIDTH; __exports.EAN_ADDON_START = __reexport1.EAN_ADDON_START; __exports.EAN_ADDON_SEPARATOR = __reexport1.EAN_ADDON_SEPARATOR; __exports.ean2Parity = __reexport1.ean2Parity; __exports.ean5Checksum = __reexport1.ean5Checksum; __exports.ean5CheckDigit = __reexport1.ean5CheckDigit; __exports.ean5Parity = __reexport1.ean5Parity; __exports.encodeEAN2 = __reexport1.encodeEAN2; __exports.encodeEAN5 = __reexport1.encodeEAN5; __exports.encodeEANAddon = __reexport1.encodeEANAddon; __exports.encodeEANAddOn = __reexport1.encodeEANAddOn; __exports.decodeEAN2 = __reexport1.decodeEAN2; __exports.decodeEAN5 = __reexport1.decodeEAN5; __exports.decodeEANAddon = __reexport1.decodeEANAddon; __exports.decodeEANAddOn = __reexport1.decodeEANAddOn; __exports.composeEANAddon = __reexport1.composeEANAddon; __exports.encodeEAN13WithAddon = __reexport1.encodeEAN13WithAddon; __exports.encodeEAN8WithAddon = __reexport1.encodeEAN8WithAddon; __exports.encodeUPCAWithAddon = __reexport1.encodeUPCAWithAddon; __exports.encodeUPCEWithAddon = __reexport1.encodeUPCEWithAddon;
3127
+ const __reexport2 = __require("oned/reader.js"); __exports.decodeOneD = __reexport2.decodeOneD; __exports.decodeOneDStrict = __reexport2.decodeOneDStrict; __exports.patternVariance = __reexport2.patternVariance; __exports.recordPattern = __reexport2.recordPattern; __exports.toNarrowWidePattern = __reexport2.toNarrowWidePattern;
3128
+ const { encodeEAN2, encodeEAN5 } = __require("oned/addons.js");
2719
3129
 
2720
3130
  /**
2721
3131
  * Writers by format id, for the top-level `encode()` dispatcher.
@@ -2726,7 +3136,7 @@ __modules["oned/index.js"] = function (__require, __exports) {
2726
3136
  * failing at runtime.
2727
3137
  *
2728
3138
  * @type {Record<string, {encode: Function, readable: boolean, label: string}>}
2729
- */
3139
+ */
2730
3140
  ean13: { encode: encodeEAN13, readable: true, label: 'EAN-13' },
2731
3141
  ean8: { encode: encodeEAN8, readable: true, label: 'EAN-8' },
2732
3142
  upca: { encode: encodeUPCA, readable: true, label: 'UPC-A' },
@@ -2745,8 +3155,13 @@ __modules["oned/index.js"] = function (__require, __exports) {
2745
3155
  codabar: { encode: encodeCodabar, readable: true, label: 'Codabar' },
2746
3156
  code11: { encode: encodeCode11, readable: false, label: 'Code 11' },
2747
3157
  msi: { encode: encodeMSI, readable: false, label: 'MSI Plessey' },
2748
- pharmacode: { encode: encodePharmacode, readable: false, label: 'Pharmacode' },
2749
- };
3158
+ pharmacode: { encode: encodePharmacode, readable: false, label: 'Pharmacode' },
3159
+ // Supplements are writable standalone matrices, but their reader is
3160
+ // intentionally exposed through the EAN/UPC add-on helpers rather than the
3161
+ // generic one-dimensional scan pipeline.
3162
+ ean2: { encode: encodeEAN2, readable: false, label: 'EAN-2 supplement' },
3163
+ ean5: { encode: encodeEAN5, readable: false, label: 'EAN-5 supplement' },
3164
+ };
2750
3165
 
2751
3166
  __exports.ONED_FORMATS = ONED_FORMATS;
2752
3167
  };
@@ -12529,118 +12944,1781 @@ const __reexport3 = __require("frameqr/tables.js"); __exports.FRAMEQR_PROFILE =
12529
12944
 
12530
12945
  };
12531
12946
 
12532
- __modules["render/options.js"] = function (__require, __exports) {
12947
+ __modules["aztecrune/tables.js"] = function (__require, __exports) {
12533
12948
  /**
12534
- * Shared render options, normalised once so every backend agrees.
12949
+ * Aztec Rune geometry.
12535
12950
  *
12536
- * @module render/options
12951
+ * Aztec Rune is the 11x11, one-byte member of the Aztec family. Two 4-bit
12952
+ * data words and five 4-bit Reed-Solomon check words are XORed with the fixed
12953
+ * Aztec Rune mask and written clockwise on the outer data ring. The finder and
12954
+ * corner orientation marks are independent of the value.
12955
+ *
12956
+ * The constants below are derived from the public Aztec Code specification and
12957
+ * are kept separate from the general Aztec implementation so a normal Aztec
12958
+ * decoder can never accidentally treat an 11x11 Rune as a regular symbol.
12959
+ *
12960
+ * @module aztecrune/tables
12537
12961
  */
12538
12962
  const { BitMatrix } = __require("core/bit-matrix.js");
12963
+ const { fieldForWordSize } = __require("aztec/tables.js");
12964
+ const AZTEC_RUNE_SIZE = 11;
12965
+ const AZTEC_RUNE_DATA_BITS = 8;
12966
+ const AZTEC_RUNE_WORD_SIZE = 4;
12967
+ const AZTEC_RUNE_DATA_CODEWORDS = 2;
12968
+ const AZTEC_RUNE_ECC_CODEWORDS = 5;
12969
+ const AZTEC_RUNE_TOTAL_CODEWORDS = AZTEC_RUNE_DATA_CODEWORDS + AZTEC_RUNE_ECC_CODEWORDS;
12970
+ const AZTEC_RUNE_MASK = 0b1010;
12539
12971
 
12540
12972
  /**
12541
- * @typedef {object} RenderOptions
12542
- * @property {number} [scale] Pixels per module. Default 8.
12543
- * @property {number} [margin] Quiet-zone modules on every side. Default 4.
12544
- * @property {string} [dark] Colour of set modules. Default '#000000'.
12545
- * @property {string} [light] Colour of clear modules, or 'none' for transparent.
12546
- * @property {number} [barHeight] For 1D symbols: total bar height in pixels.
12973
+ * Data-module coordinates in wire order: clockwise, starting at the top.
12974
+ * Every side contributes seven modules, for 28 bits in total.
12547
12975
  */
12976
+ const AZTEC_RUNE_DATA_POSITIONS = Object.freeze([
12977
+ ...Array.from({ length: 7 }, (_, i) => [i + 2, 0]),
12978
+ ...Array.from({ length: 7 }, (_, i) => [10, i + 2]),
12979
+ ...Array.from({ length: 7 }, (_, i) => [8 - i, 10]),
12980
+ ...Array.from({ length: 7 }, (_, i) => [0, 8 - i]),
12981
+ ].map(([x, y]) => Object.freeze([x, y])));
12982
+
12983
+ const DATA_KEYS = new Set(AZTEC_RUNE_DATA_POSITIONS.map(([x, y]) => `${x},${y}`));
12548
12984
 
12985
+ /** @param {number} x @param {number} y @returns {boolean} */
12986
+ function isAztecRuneDataPosition(x, y) {
12987
+ return DATA_KEYS.has(`${x},${y}`);
12988
+ }
12549
12989
  /**
12550
- * Expand and pad the matrix, and resolve every dimension.
12551
- *
12552
- * Linear symbols arrive one module tall. They are stretched to `barHeight`
12553
- * *before* the quiet zone is applied, so the margin ends up uniform on all
12554
- * four sides — padding first would leave a quiet zone one module tall against
12555
- * bars a hundred pixels tall, which no scanner would accept.
12990
+ * Return the value of a structural module. Data positions return `null`.
12991
+ * The bull's-eye has five square rings including its one-module centre; its
12992
+ * even-radius rings are dark. The four corner groups are the orientation marks
12993
+ * described by the Aztec Rune specification.
12556
12994
  *
12557
- * @param {BitMatrix} matrix
12558
- * @param {RenderOptions} options
12995
+ * @param {number} x @param {number} y
12996
+ * @returns {boolean|null}
12559
12997
  */
12560
- function normalizeOptions(matrix, options = {}) {
12561
- const scale = Math.max(1, Math.floor(options.scale ?? 8));
12562
- const margin = Math.max(0, Math.floor(options.margin ?? 4));
12563
- const dark = options.dark ?? '#000000';
12564
- const light = options.light ?? '#ffffff';
12565
- const barHeight = options.barHeight ?? null;
12998
+ function aztecRuneStructuralValue(x, y) {
12999
+ if (!Number.isInteger(x) || !Number.isInteger(y) || x < 0 || y < 0 || x >= AZTEC_RUNE_SIZE || y >= AZTEC_RUNE_SIZE) {
13000
+ return null;
13001
+ }
13002
+ if (isAztecRuneDataPosition(x, y)) return null;
12566
13003
 
12567
- let base = matrix;
12568
- const is1D = matrix.height === 1;
13004
+ const distance = Math.max(Math.abs(x - 5), Math.abs(y - 5));
13005
+ if (distance <= 4) return (distance & 1) === 0;
12569
13006
 
12570
- if (is1D) {
12571
- // Default to a bar height that stays scannable: tall enough that a laser
12572
- // crossing at a slight angle still passes through the whole symbol.
12573
- const targetPixels = barHeight ?? Math.max(40, Math.round(matrix.width * scale * 0.15));
12574
- const rows = Math.max(1, Math.round(targetPixels / scale));
12575
- base = new BitMatrix(matrix.width, rows);
12576
- for (let x = 0; x < matrix.width; x++) {
12577
- if (!matrix.get(x, 0)) continue;
12578
- for (let y = 0; y < rows; y++) base.set(x, y);
13007
+ // Corner orientation groups, clockwise from the upper-left corner:
13008
+ // three dark, white-dark-dark, dark-white-white, three white.
13009
+ if ((x === 0 && y <= 1) || (y === 0 && x <= 1)) return true;
13010
+ if ((x === 10 && y <= 1) || (y === 0 && x === 10)) return true;
13011
+ if (x === 9 && y === 0) return false;
13012
+ if (x === 10 && y === 10) return false;
13013
+ if (y === 10 && x >= 0 && x <= 1) return false;
13014
+ if (x === 0 && y >= 9) return false;
13015
+ if (x === 10 && y === 9) return true;
13016
+
13017
+ // All non-data cells are covered by the bull's-eye or the four corners.
13018
+ return false;
13019
+ }
13020
+
13021
+ /** Build only the fixed finder/orientation structure. */
13022
+ function buildAztecRuneStructure() {
13023
+ const matrix = new BitMatrix(AZTEC_RUNE_SIZE);
13024
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++) {
13025
+ for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
13026
+ const value = aztecRuneStructuralValue(x, y);
13027
+ if (value === true) matrix.set(x, y);
12579
13028
  }
12580
13029
  }
13030
+ return matrix;
13031
+ }
12581
13032
 
12582
- const source = margin > 0 ? base.withMargin(margin) : base;
13033
+ /** Return the field used by Rune data/check words. */
13034
+ function aztecRuneField() {
13035
+ return fieldForWordSize(AZTEC_RUNE_WORD_SIZE);
13036
+ }
12583
13037
 
12584
- return {
12585
- scale,
12586
- margin,
12587
- dark,
12588
- light,
12589
- is1D,
12590
- source,
12591
- rowHeight: scale,
12592
- pixelWidth: source.width * scale,
12593
- pixelHeight: source.height * scale,
12594
- };
13038
+ /** Validate the fixed Rune contract and coordinate layout. */
13039
+ function validateAztecRuneTables() {
13040
+ const problems = [];
13041
+ if (AZTEC_RUNE_SIZE !== 11) problems.push('Rune symbol size must be 11');
13042
+ if (AZTEC_RUNE_TOTAL_CODEWORDS * AZTEC_RUNE_WORD_SIZE !== 28) problems.push('Rune outer ring must carry 28 bits');
13043
+ if (AZTEC_RUNE_DATA_POSITIONS.length !== 28) problems.push('Rune data ring must contain 28 modules');
13044
+ if (new Set(AZTEC_RUNE_DATA_POSITIONS.map(([x, y]) => `${x},${y}`)).size !== 28) problems.push('Rune data coordinates must be unique');
13045
+ const structure = buildAztecRuneStructure();
13046
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
13047
+ if (isAztecRuneDataPosition(x, y)) continue;
13048
+ const expected = aztecRuneStructuralValue(x, y) === true;
13049
+ if (structure.get(x, y) !== expected) problems.push(`Rune structure mismatch at ${x},${y}`);
13050
+ }
13051
+ return problems;
12595
13052
  }
12596
13053
 
13054
+ __exports.AZTEC_RUNE_SIZE = AZTEC_RUNE_SIZE;
13055
+ __exports.AZTEC_RUNE_DATA_BITS = AZTEC_RUNE_DATA_BITS;
13056
+ __exports.AZTEC_RUNE_WORD_SIZE = AZTEC_RUNE_WORD_SIZE;
13057
+ __exports.AZTEC_RUNE_DATA_CODEWORDS = AZTEC_RUNE_DATA_CODEWORDS;
13058
+ __exports.AZTEC_RUNE_ECC_CODEWORDS = AZTEC_RUNE_ECC_CODEWORDS;
13059
+ __exports.AZTEC_RUNE_TOTAL_CODEWORDS = AZTEC_RUNE_TOTAL_CODEWORDS;
13060
+ __exports.AZTEC_RUNE_MASK = AZTEC_RUNE_MASK;
13061
+ __exports.AZTEC_RUNE_DATA_POSITIONS = AZTEC_RUNE_DATA_POSITIONS;
13062
+ __exports.isAztecRuneDataPosition = isAztecRuneDataPosition;
13063
+ __exports.aztecRuneStructuralValue = aztecRuneStructuralValue;
13064
+ __exports.buildAztecRuneStructure = buildAztecRuneStructure;
13065
+ __exports.aztecRuneField = aztecRuneField;
13066
+ __exports.validateAztecRuneTables = validateAztecRuneTables;
13067
+ };
13068
+
13069
+ __modules["aztecrune/encoder.js"] = function (__require, __exports) {
12597
13070
  /**
12598
- * Parse a CSS colour into RGBA bytes.
13071
+ * Aztec Rune encoder.
12599
13072
  *
12600
- * Supports the forms a barcode actually needs: #rgb, #rgba, #rrggbb,
12601
- * #rrggbbaa, rgb(), rgba(), plus 'none' and 'transparent'.
13073
+ * A Rune carries exactly one byte. Numeric strings are accepted for convenient
13074
+ * human-readable input and are normalized to the canonical three-digit text;
13075
+ * binary callers can pass one byte in an ArrayBuffer or typed-array view.
12602
13076
  *
12603
- * @param {string} colour
12604
- * @returns {[number, number, number, number]}
13077
+ * @module aztecrune/encoder
12605
13078
  */
12606
- function parseColor(colour) {
12607
- const value = String(colour).trim().toLowerCase();
13079
+ const { BitMatrix } = __require("core/bit-matrix.js");
13080
+ const { EncodeError } = __require("core/errors.js");
13081
+ const { rsEncode } = __require("core/reed-solomon.js");
13082
+ const { AZTEC_RUNE_DATA_POSITIONS, AZTEC_RUNE_ECC_CODEWORDS, AZTEC_RUNE_MASK, AZTEC_RUNE_SIZE, aztecRuneField, buildAztecRuneStructure } = __require("aztecrune/tables.js");
12608
13083
 
12609
- if (value === 'none' || value === 'transparent') return [0, 0, 0, 0];
12610
- if (value === 'white') return [255, 255, 255, 255];
12611
- if (value === 'black') return [0, 0, 0, 255];
13084
+ /** @param {unknown} value @returns {number} */
13085
+ function normalizeAztecRuneValue(value) {
13086
+ if (typeof value === 'number') {
13087
+ if (Number.isInteger(value) && value >= 0 && value <= 255) return value;
13088
+ throw new EncodeError('Aztec Rune: numeric value must be an integer from 0 to 255');
13089
+ }
12612
13090
 
12613
- if (value[0] === '#') {
12614
- const hex = value.slice(1);
12615
- const expand = (c) => parseInt(c + c, 16);
12616
- if (hex.length === 3) {
12617
- return [expand(hex[0]), expand(hex[1]), expand(hex[2]), 255];
12618
- }
12619
- if (hex.length === 4) {
12620
- return [expand(hex[0]), expand(hex[1]), expand(hex[2]), expand(hex[3])];
12621
- }
12622
- if (hex.length === 6) {
12623
- return [
12624
- parseInt(hex.slice(0, 2), 16),
12625
- parseInt(hex.slice(2, 4), 16),
12626
- parseInt(hex.slice(4, 6), 16),
12627
- 255,
12628
- ];
12629
- }
12630
- if (hex.length === 8) {
12631
- return [
12632
- parseInt(hex.slice(0, 2), 16),
12633
- parseInt(hex.slice(2, 4), 16),
12634
- parseInt(hex.slice(4, 6), 16),
12635
- parseInt(hex.slice(6, 8), 16),
12636
- ];
12637
- }
13091
+ if (typeof value === 'string') {
13092
+ if (!/^\d{1,3}$/.test(value)) throw new EncodeError('Aztec Rune: text input must contain one to three decimal digits');
13093
+ const numeric = Number(value);
13094
+ if (numeric > 255) throw new EncodeError('Aztec Rune: decimal value must be from 000 to 255');
13095
+ return numeric;
12638
13096
  }
12639
13097
 
12640
- const fn = value.match(/^rgba?\(([^)]+)\)$/);
12641
- if (fn) {
12642
- const parts = fn[1].split(/[,/\s]+/).filter(Boolean);
12643
- const channel = (s) => (s.endsWith('%')
13098
+ let bytes = null;
13099
+ if (value instanceof ArrayBuffer) bytes = new Uint8Array(value);
13100
+ else if (ArrayBuffer.isView(value)) bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
13101
+ if (bytes) {
13102
+ if (bytes.length !== 1) throw new EncodeError('Aztec Rune: binary input must contain exactly one byte');
13103
+ return bytes[0];
13104
+ }
13105
+ throw new EncodeError('Aztec Rune: expected a number, decimal string or one-byte binary value');
13106
+ }
13107
+
13108
+ /** @param {number} value @returns {number[]} */
13109
+ function codewordsForValue(value) {
13110
+ const data = [value >>> 4, value & 0x0f];
13111
+ const parity = rsEncode(data, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
13112
+ return data.concat(parity).map((word) => word ^ AZTEC_RUNE_MASK);
13113
+ }
13114
+
13115
+ /** @param {BitMatrix} matrix @param {number[]} codewords */
13116
+ function writeDataRing(matrix, codewords) {
13117
+ for (let word = 0; word < codewords.length; word++) {
13118
+ for (let bit = 0; bit < 4; bit++) {
13119
+ const at = word * 4 + bit;
13120
+ const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
13121
+ matrix.setValue(x, y, ((codewords[word] >>> (3 - bit)) & 1) !== 0);
13122
+ }
13123
+ }
13124
+ }
13125
+
13126
+ /**
13127
+ * Encode one byte as an Aztec Rune.
13128
+ *
13129
+ * @param {number|string|ArrayBuffer|ArrayBufferView} value
13130
+ * @param {{inverted?: boolean}} [options]
13131
+ * @returns {import('../core/bit-matrix.js').BitMatrix & {
13132
+ * format: 'aztecrune', value: number, inverted: boolean
13133
+ * }}
13134
+ */
13135
+ function encodeAztecRune(value, options = {}) {
13136
+ const numeric = normalizeAztecRuneValue(value);
13137
+ if (options.inverted !== undefined && typeof options.inverted !== 'boolean') {
13138
+ throw new EncodeError('Aztec Rune: inverted must be boolean');
13139
+ }
13140
+ const inverted = options.inverted === true;
13141
+ const matrix = buildAztecRuneStructure();
13142
+ writeDataRing(matrix, codewordsForValue(numeric));
13143
+ if (inverted) {
13144
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) matrix.flip(x, y);
13145
+ }
13146
+ matrix.format = 'aztecrune';
13147
+ matrix.value = numeric;
13148
+ matrix.inverted = inverted;
13149
+ return matrix;
13150
+ }
13151
+ __exports.codewordsForValue = codewordsForValue;
13152
+
13153
+ __exports.normalizeAztecRuneValue = normalizeAztecRuneValue;
13154
+ __exports.encodeAztecRune = encodeAztecRune;
13155
+ };
13156
+
13157
+ __modules["aztecrune/decoder.js"] = function (__require, __exports) {
13158
+ /**
13159
+ * Aztec Rune decoder.
13160
+ *
13161
+ * The input is a square 11x11 module matrix. Structural modules are checked
13162
+ * before the seven masked GF(16) codewords are Reed-Solomon corrected. The
13163
+ * decoder tries the four in-plane quarter turns and both polarities, allowing
13164
+ * it to consume an oriented sampled image while still rejecting ordinary
13165
+ * Aztec/QR matrices.
13166
+ *
13167
+ * @module aztecrune/decoder
13168
+ */
13169
+ const { FormatError } = __require("core/errors.js");
13170
+ const { rsDecode } = __require("core/reed-solomon.js");
13171
+ const { AZTEC_RUNE_DATA_CODEWORDS, AZTEC_RUNE_DATA_POSITIONS, AZTEC_RUNE_ECC_CODEWORDS, AZTEC_RUNE_MASK, AZTEC_RUNE_SIZE, aztecRuneField, aztecRuneStructuralValue } = __require("aztecrune/tables.js");
13172
+
13173
+ /** @param {import('../core/bit-matrix.js').BitMatrix} source @param {number} turns */
13174
+ function rotateClockwise(source, turns) {
13175
+ let current = source.clone();
13176
+ for (let turn = 0; turn < turns; turn++) {
13177
+ const out = new source.constructor(current.height, current.width);
13178
+ for (let y = 0; y < current.height; y++) for (let x = 0; x < current.width; x++) {
13179
+ if (current.get(x, y)) out.set(current.height - 1 - y, x);
13180
+ }
13181
+ current = out;
13182
+ }
13183
+ return current;
13184
+ }
13185
+
13186
+ /** @param {import('../core/bit-matrix.js').BitMatrix} matrix */
13187
+ function invert(matrix) {
13188
+ const out = matrix.clone();
13189
+ for (let y = 0; y < out.height; y++) for (let x = 0; x < out.width; x++) out.flip(x, y);
13190
+ return out;
13191
+ }
13192
+
13193
+ /** @param {import('../core/bit-matrix.js').BitMatrix} matrix @param {boolean} inverted */
13194
+ function structureMatches(matrix, inverted) {
13195
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
13196
+ const expected = aztecRuneStructuralValue(x, y);
13197
+ if (expected === null) continue;
13198
+ if (matrix.get(x, y) !== (inverted ? !expected : expected)) return false;
13199
+ }
13200
+ return true;
13201
+ }
13202
+
13203
+ /** @param {import('../core/bit-matrix.js').BitMatrix} matrix @param {boolean} inverted */
13204
+ function readCodewords(matrix, inverted) {
13205
+ const words = new Array(2 + AZTEC_RUNE_ECC_CODEWORDS).fill(0);
13206
+ for (let at = 0; at < AZTEC_RUNE_DATA_POSITIONS.length; at++) {
13207
+ const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
13208
+ const bit = matrix.get(x, y) !== inverted;
13209
+ words[at >>> 2] = (words[at >>> 2] << 1) | (bit ? 1 : 0);
13210
+ }
13211
+ return words.map((word) => word ^ AZTEC_RUNE_MASK);
13212
+ }
13213
+
13214
+ /** @param {number} value @param {boolean} inverted @param {number} rotation @param {number} corrections */
13215
+ function result(value, inverted, rotation, corrections) {
13216
+ return {
13217
+ format: 'aztecrune',
13218
+ value,
13219
+ text: String(value).padStart(3, '0'),
13220
+ bytes: Uint8Array.of(value),
13221
+ dimension: AZTEC_RUNE_SIZE,
13222
+ inverted,
13223
+ rotation,
13224
+ corrections,
13225
+ };
13226
+ }
13227
+
13228
+ /**
13229
+ * Decode a square Aztec Rune matrix.
13230
+ *
13231
+ * @param {import('../core/bit-matrix.js').BitMatrix} matrix
13232
+ * @param {{inverted?: boolean|'auto', rotation?: number|'auto'}} [options]
13233
+ * @returns {{format:'aztecrune',value:number,text:string,bytes:Uint8Array,dimension:number,inverted:boolean,rotation:number,corrections:number}}
13234
+ * @throws {FormatError} For non-Rune geometry, structure or uncorrectable data.
13235
+ */
13236
+ function decodeAztecRune(matrix, options = {}) {
13237
+ if (!matrix || matrix.width !== AZTEC_RUNE_SIZE || matrix.height !== AZTEC_RUNE_SIZE) {
13238
+ throw new FormatError(`Aztec Rune: expected an ${AZTEC_RUNE_SIZE}x${AZTEC_RUNE_SIZE} module matrix`);
13239
+ }
13240
+ const invertedModes = options.inverted === true ? [true] : options.inverted === false ? [false] : [false, true];
13241
+ const rotations = Number.isInteger(options.rotation)
13242
+ ? [((options.rotation % 360) + 360) % 360]
13243
+ : [0, 90, 180, 270];
13244
+
13245
+ let checksumError = null;
13246
+ for (const requestedRotation of rotations) {
13247
+ if (requestedRotation % 90 !== 0) continue;
13248
+ // To canonicalize an input rotated clockwise by k degrees, rotate it
13249
+ // counter-clockwise by k. `turns` is the clockwise operation we apply.
13250
+ const turns = (4 - requestedRotation / 90) % 4;
13251
+ const canonicalRotation = requestedRotation;
13252
+ const rotated = turns === 0 ? matrix.clone() : rotateClockwise(matrix, turns);
13253
+ for (const inverted of invertedModes) {
13254
+ const canonical = inverted ? invert(rotated) : rotated;
13255
+ if (!structureMatches(canonical, false)) continue;
13256
+ const words = readCodewords(canonical, false);
13257
+ try {
13258
+ const corrections = rsDecode(words, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
13259
+ const value = (words[0] << 4) | words[1];
13260
+ return result(value, inverted, canonicalRotation, corrections);
13261
+ } catch (error) {
13262
+ checksumError = error;
13263
+ }
13264
+ }
13265
+ }
13266
+
13267
+ if (checksumError) {
13268
+ throw new FormatError(`Aztec Rune: Reed-Solomon check failed: ${checksumError.message}`);
13269
+ }
13270
+ throw new FormatError('Aztec Rune: structural pattern or orientation is invalid');
13271
+ }
13272
+ __exports.readCodewords = readCodewords; __exports.structureMatches = structureMatches;
13273
+
13274
+ __exports.decodeAztecRune = decodeAztecRune;
13275
+ };
13276
+
13277
+ __modules["aztecrune/detector.js"] = function (__require, __exports) {
13278
+ /**
13279
+ * Detector for Aztec Rune symbols.
13280
+ *
13281
+ * Rune has a fixed 11x11 geometry and a distinctive five-ring bull's-eye. This
13282
+ * detector targets binarized, module-aligned rasters (including an integer
13283
+ * scale, quiet zone and quarter turns). Arbitrary perspective and severe blur
13284
+ * remain detector-level limitations; callers needing those conditions should
13285
+ * pass a rectified 11x11 matrix to decodeAztecRune.
13286
+ *
13287
+ * @module aztecrune/detector
13288
+ */
13289
+ const { NotFoundError } = __require("core/errors.js");
13290
+ const { BitMatrix } = __require("core/bit-matrix.js");
13291
+ const { decodeAztecRune } = __require("aztecrune/decoder.js");
13292
+ const { AZTEC_RUNE_SIZE } = __require("aztecrune/tables.js");
13293
+
13294
+ /** @typedef {{x:number,y:number}} Point */
13295
+
13296
+ /**
13297
+ * Find connected components of a polarity. Components touching the image
13298
+ * border are ignored when they exceed the plausible module area; this avoids
13299
+ * returning the light background as a candidate while retaining an inverted
13300
+ * Rune's isolated light centre module.
13301
+ */
13302
+ function components(image, value) {
13303
+ const width = image.width;
13304
+ const height = image.height;
13305
+ const seen = new Uint8Array(width * height);
13306
+ const limit = Math.max(64, Math.floor(width * height * 0.04));
13307
+ const found = [];
13308
+
13309
+ for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
13310
+ const start = y * width + x;
13311
+ if (seen[start] || image.get(x, y) !== value) continue;
13312
+ const queue = [[x, y]];
13313
+ seen[start] = 1;
13314
+ let head = 0;
13315
+ let minX = x; let maxX = x; let minY = y; let maxY = y;
13316
+ let count = 0;
13317
+ let touchesBorder = false;
13318
+
13319
+ while (head < queue.length) {
13320
+ const [px, py] = queue[head++];
13321
+ count++;
13322
+ minX = Math.min(minX, px); maxX = Math.max(maxX, px);
13323
+ minY = Math.min(minY, py); maxY = Math.max(maxY, py);
13324
+ if (px === 0 || py === 0 || px === width - 1 || py === height - 1) touchesBorder = true;
13325
+ for (const [nx, ny] of [[px - 1, py], [px + 1, py], [px, py - 1], [px, py + 1]]) {
13326
+ if (nx < 0 || ny < 0 || nx >= width || ny >= height) continue;
13327
+ const at = ny * width + nx;
13328
+ if (!seen[at] && image.get(nx, ny) === value) {
13329
+ seen[at] = 1;
13330
+ queue.push([nx, ny]);
13331
+ }
13332
+ }
13333
+ }
13334
+
13335
+ const boxWidth = maxX - minX + 1;
13336
+ const boxHeight = maxY - minY + 1;
13337
+ if (count <= limit && !touchesBorder &&
13338
+ Math.abs(boxWidth - boxHeight) <= Math.max(1, Math.ceil(Math.max(boxWidth, boxHeight) * 0.35)) &&
13339
+ count >= boxWidth * boxHeight * 0.45) {
13340
+ found.push({ x: (minX + maxX) / 2, y: (minY + maxY) / 2, width: boxWidth, height: boxHeight, count });
13341
+ }
13342
+ }
13343
+ return found.sort((a, b) => b.count - a.count);
13344
+ }
13345
+ /** @param {import('../core/bit-matrix.js').BitMatrix} image @param {Point} center @param {number} pitch */
13346
+ function sample(image, center, pitch) {
13347
+ const matrix = new BitMatrix(AZTEC_RUNE_SIZE);
13348
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
13349
+ const px = Math.round(center.x + (x - 5) * pitch);
13350
+ const py = Math.round(center.y + (y - 5) * pitch);
13351
+ if (px >= 0 && py >= 0 && px < image.width && py < image.height && image.get(px, py)) matrix.set(x, y);
13352
+ }
13353
+ return matrix;
13354
+ }
13355
+
13356
+ function corners(center, pitch) {
13357
+ const half = AZTEC_RUNE_SIZE * pitch / 2;
13358
+ return [
13359
+ { x: center.x - half, y: center.y - half },
13360
+ { x: center.x + half, y: center.y - half },
13361
+ { x: center.x + half, y: center.y + half },
13362
+ { x: center.x - half, y: center.y + half },
13363
+ ];
13364
+ }
13365
+
13366
+ function sameCandidate(left, right) {
13367
+ return Math.hypot(left.center.x - right.center.x, left.center.y - right.center.y) <= Math.max(left.moduleSize, right.moduleSize) * 2;
13368
+ }
13369
+
13370
+ /**
13371
+ * Detect the most prominent Aztec Rune in a binarized image.
13372
+ *
13373
+ * @param {import('../core/bit-matrix.js').BitMatrix} binaryImage
13374
+ * @returns {{corners:Point[],dimension:11,moduleSize:number,matrix:BitMatrix,result:object}|null}
13375
+ */
13376
+ function detectAztecRune(binaryImage) {
13377
+ if (!binaryImage || !binaryImage.width || !binaryImage.height) {
13378
+ throw new NotFoundError('detectAztecRune: no image supplied');
13379
+ }
13380
+ const candidates = [];
13381
+ for (const value of [true, false]) {
13382
+ for (const component of components(binaryImage, value)) {
13383
+ const pitch = (component.width + component.height) / 2;
13384
+ if (pitch < 0.8) continue;
13385
+ const matrix = sample(binaryImage, component, pitch);
13386
+ let decoded;
13387
+ try { decoded = decodeAztecRune(matrix); } catch { continue; }
13388
+ const candidate = {
13389
+ center: component,
13390
+ corners: corners(component, pitch),
13391
+ dimension: AZTEC_RUNE_SIZE,
13392
+ moduleSize: pitch,
13393
+ matrix,
13394
+ result: decoded,
13395
+ };
13396
+ if (!candidates.some((entry) => sameCandidate(entry, candidate))) candidates.push(candidate);
13397
+ }
13398
+ }
13399
+ candidates.sort((a, b) => b.moduleSize - a.moduleSize);
13400
+ const best = candidates[0];
13401
+ if (!best) return null;
13402
+ delete best.center;
13403
+ return best;
13404
+ }
13405
+
13406
+ /** Detect and decode one Aztec Rune, or return `null` when none is verified. */
13407
+ function detectAndDecodeAztecRune(binaryImage) {
13408
+ let detection;
13409
+ try { detection = detectAztecRune(binaryImage); } catch { return null; }
13410
+ if (!detection) return null;
13411
+ return { ...detection.result, corners: detection.corners, moduleSize: detection.moduleSize };
13412
+ }
13413
+
13414
+ __exports.detectAztecRune = detectAztecRune;
13415
+ __exports.detectAndDecodeAztecRune = detectAndDecodeAztecRune;
13416
+ };
13417
+
13418
+ __modules["aztecrune/index.js"] = function (__require, __exports) {
13419
+ /** Aztec Rune entry points. @module aztecrune */
13420
+ const __reexport0 = __require("aztecrune/encoder.js"); __exports.encodeAztecRune = __reexport0.encodeAztecRune; __exports.normalizeAztecRuneValue = __reexport0.normalizeAztecRuneValue;
13421
+ const __reexport1 = __require("aztecrune/decoder.js"); __exports.decodeAztecRune = __reexport1.decodeAztecRune;
13422
+ const __reexport2 = __require("aztecrune/detector.js"); __exports.detectAztecRune = __reexport2.detectAztecRune; __exports.detectAndDecodeAztecRune = __reexport2.detectAndDecodeAztecRune;
13423
+ const __reexport3 = __require("aztecrune/tables.js"); __exports.AZTEC_RUNE_SIZE = __reexport3.AZTEC_RUNE_SIZE; __exports.AZTEC_RUNE_DATA_BITS = __reexport3.AZTEC_RUNE_DATA_BITS; __exports.AZTEC_RUNE_WORD_SIZE = __reexport3.AZTEC_RUNE_WORD_SIZE; __exports.AZTEC_RUNE_DATA_CODEWORDS = __reexport3.AZTEC_RUNE_DATA_CODEWORDS; __exports.AZTEC_RUNE_ECC_CODEWORDS = __reexport3.AZTEC_RUNE_ECC_CODEWORDS; __exports.AZTEC_RUNE_TOTAL_CODEWORDS = __reexport3.AZTEC_RUNE_TOTAL_CODEWORDS; __exports.AZTEC_RUNE_MASK = __reexport3.AZTEC_RUNE_MASK; __exports.AZTEC_RUNE_DATA_POSITIONS = __reexport3.AZTEC_RUNE_DATA_POSITIONS; __exports.aztecRuneStructuralValue = __reexport3.aztecRuneStructuralValue; __exports.buildAztecRuneStructure = __reexport3.buildAztecRuneStructure; __exports.aztecRuneField = __reexport3.aztecRuneField; __exports.validateAztecRuneTables = __reexport3.validateAztecRuneTables;
13424
+
13425
+
13426
+ };
13427
+
13428
+ __modules["compactpdf417/tables.js"] = function (__require, __exports) {
13429
+ /**
13430
+ * Compact (truncated) PDF417 layout.
13431
+ *
13432
+ * Compact PDF417 is a geometric variant of PDF417, not a new high-level
13433
+ * compaction mode. It keeps the same codeword, cluster, row-indicator,
13434
+ * Reed–Solomon and Text/Byte/Numeric compaction rules, while omitting each
13435
+ * row's right row indicator and replacing the normal stop pattern with a
13436
+ * single dark module. The resulting symbol remains distinguishable from the
13437
+ * ordinary PDF417 layout by its width and row terminator.
13438
+ *
13439
+ * @module compactpdf417/tables
13440
+ */
13441
+ const { EncodeError } = __require("core/errors.js");
13442
+
13443
+ /** PDF417 start pattern, in module widths. */
13444
+ const COMPACT_PDF417_START = '81111113';
13445
+
13446
+ /** Binary module representation of the start pattern. */
13447
+ const COMPACT_PDF417_START_BITS = '11111111010101000';
13448
+
13449
+ /** Compact PDF417's reduced stop is one dark module. */
13450
+ const COMPACT_PDF417_STOP_MODULES = 1;
13451
+
13452
+ /** Minimum/maximum number of rows and data columns. */
13453
+ const COMPACT_PDF417_LIMITS = Object.freeze({
13454
+ minRows: 3,
13455
+ maxRows: 90,
13456
+ minColumns: 1,
13457
+ maxColumns: 30,
13458
+ maxCodewords: 928,
13459
+ });
13460
+
13461
+ /**
13462
+ * Return the printed width in modules for a compact symbol.
13463
+ *
13464
+ * 17 start + 17 left indicator + 17 per codeword column + 1 reduced stop.
13465
+ * @param {number} columns
13466
+ */
13467
+ function compactPdf417Width(columns) {
13468
+ if (!Number.isInteger(columns) || columns < 1 || columns > 30) {
13469
+ throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
13470
+ }
13471
+ return 35 + columns * 17;
13472
+ }
13473
+
13474
+ /**
13475
+ * Validate a compact matrix geometry and return its dimensions.
13476
+ *
13477
+ * @param {number} width
13478
+ * @param {number} height
13479
+ * @param {number} rowHeight
13480
+ */
13481
+ function compactPdf417Geometry(width, height, rowHeight = 3) {
13482
+ if (!Number.isInteger(width) || !Number.isInteger(height)) {
13483
+ throw new RangeError('Compact PDF417: matrix dimensions must be integers');
13484
+ }
13485
+ if (!Number.isInteger(rowHeight) || rowHeight < 1) {
13486
+ throw new RangeError('Compact PDF417: rowHeight must be a positive integer');
13487
+ }
13488
+ if ((width - 35) % 17 !== 0) {
13489
+ throw new RangeError(`Compact PDF417: width ${width} does not match the compact layout`);
13490
+ }
13491
+ const columns = (width - 35) / 17;
13492
+ const rows = height / rowHeight;
13493
+ if (!Number.isInteger(rows) || rows < 3 || rows > 90) {
13494
+ throw new RangeError(`Compact PDF417: rows must be an integer in 3..90, got ${rows}`);
13495
+ }
13496
+ if (columns < 1 || columns > 30) {
13497
+ throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
13498
+ }
13499
+ return { rows, columns, rowHeight, width, height };
13500
+ }
13501
+
13502
+ /**
13503
+ * Validate encoder dimensions before codeword packing.
13504
+ * @param {object} options
13505
+ */
13506
+ function validateCompactPdf417Options(options = {}) {
13507
+ const { minRows, maxRows, minColumns, maxColumns } = COMPACT_PDF417_LIMITS;
13508
+ const rowHeight = options.rowHeight ?? 3;
13509
+ if (!Number.isInteger(rowHeight) || rowHeight < 3) {
13510
+ throw new EncodeError('Compact PDF417: rowHeight must be an integer of at least 3');
13511
+ }
13512
+ for (const [name, value, min, max] of [
13513
+ ['rows', options.rows, minRows, maxRows],
13514
+ ['columns', options.columns, minColumns, maxColumns],
13515
+ ]) {
13516
+ if (value !== undefined && (!Number.isInteger(value) || value < min || value > max)) {
13517
+ throw new EncodeError(`Compact PDF417: ${name} must be an integer in ${min}..${max}`);
13518
+ }
13519
+ }
13520
+ if (options.aspectRatio !== undefined &&
13521
+ (!Number.isFinite(options.aspectRatio) || options.aspectRatio <= 0)) {
13522
+ throw new EncodeError('Compact PDF417: aspectRatio must be positive');
13523
+ }
13524
+ return rowHeight;
13525
+ }
13526
+
13527
+ /**
13528
+ * The row indicator values used by ordinary PDF417 are retained unchanged.
13529
+ * Compact symbols omit only the right indicator, so the left indicator still
13530
+ * carries the row group, row count, error-correction level and column count.
13531
+ */
13532
+ function compactPdf417Indicators(row, rows, columns, level) {
13533
+ const group = Math.floor(row / 3);
13534
+ const y = Math.floor((rows - 1) / 3);
13535
+ const z = level * 3 + (rows - 1) % 3;
13536
+ const v = columns - 1;
13537
+ if (row % 3 === 0) return 30 * group + y;
13538
+ if (row % 3 === 1) return 30 * group + z;
13539
+ return 30 * group + v;
13540
+ }
13541
+
13542
+ /**
13543
+ * Return all standard ECC levels which agree with the observed left
13544
+ * indicators. This is kept as a table helper so decoder and tests share the
13545
+ * same compact-layout rule.
13546
+ */
13547
+ function compactPdf417MatchingLevels(leftIndicators, rows, columns) {
13548
+ const matches = [];
13549
+ for (let level = 0; level <= 8; level++) {
13550
+ if (leftIndicators.every((value, row) =>
13551
+ value === compactPdf417Indicators(row, rows, columns, level))) matches.push(level);
13552
+ }
13553
+ return matches;
13554
+ }
13555
+
13556
+ /** Validate representative layout invariants. */
13557
+ function validateCompactPdf417Tables() {
13558
+ const problems = [];
13559
+ for (const columns of [1, 2, 3, 10, 30]) {
13560
+ const width = compactPdf417Width(columns);
13561
+ if (width !== 35 + columns * 17) problems.push(`columns ${columns}: width mismatch`);
13562
+ }
13563
+ for (const rows of [3, 4, 5, 6, 90]) {
13564
+ const left = Array.from({ length: rows }, (_, row) => compactPdf417Indicators(row, rows, 3, 2));
13565
+ if (compactPdf417MatchingLevels(left, rows, 3).length !== 1) {
13566
+ problems.push(`rows ${rows}: row indicators do not identify one ECC level`);
13567
+ }
13568
+ }
13569
+ return problems;
13570
+ }
13571
+
13572
+ __exports.COMPACT_PDF417_START = COMPACT_PDF417_START;
13573
+ __exports.COMPACT_PDF417_START_BITS = COMPACT_PDF417_START_BITS;
13574
+ __exports.COMPACT_PDF417_STOP_MODULES = COMPACT_PDF417_STOP_MODULES;
13575
+ __exports.COMPACT_PDF417_LIMITS = COMPACT_PDF417_LIMITS;
13576
+ __exports.compactPdf417Width = compactPdf417Width;
13577
+ __exports.compactPdf417Geometry = compactPdf417Geometry;
13578
+ __exports.validateCompactPdf417Options = validateCompactPdf417Options;
13579
+ __exports.compactPdf417Indicators = compactPdf417Indicators;
13580
+ __exports.compactPdf417MatchingLevels = compactPdf417MatchingLevels;
13581
+ __exports.validateCompactPdf417Tables = validateCompactPdf417Tables;
13582
+ };
13583
+
13584
+ __modules["compactpdf417/encoder.js"] = function (__require, __exports) {
13585
+ /** Compact PDF417 (truncated PDF417) encoder. @module compactpdf417/encoder */
13586
+ const { BitMatrix } = __require("core/bit-matrix.js");
13587
+ const { EncodeError } = __require("core/errors.js");
13588
+ const { compactPdf417 } = __require("pdf417/compaction.js");
13589
+ const { pdf417ErrorCorrection, pdf417EccLength } = __require("pdf417/error-correction.js");
13590
+ const { pdf417PatternForCodeword } = __require("pdf417/tables.js");
13591
+ const { COMPACT_PDF417_START, compactPdf417Indicators, compactPdf417Width, validateCompactPdf417Options } = __require("compactpdf417/tables.js");
13592
+
13593
+ function appendWidths(matrix, y, x, sequence, height) {
13594
+ let dark = true;
13595
+ for (const digit of sequence) {
13596
+ const width = digit.charCodeAt(0) - 48;
13597
+ if (!Number.isInteger(width) || width < 1 || width > 8) {
13598
+ throw new EncodeError('Compact PDF417: invalid module-width sequence');
13599
+ }
13600
+ if (dark) matrix.setRegion(x, y, width, height);
13601
+ x += width;
13602
+ dark = !dark;
13603
+ }
13604
+ return x;
13605
+ }
13606
+
13607
+ function patternSequence(pattern) {
13608
+ return pattern.toString(2).padStart(17, '0').replace(/0+|1+/g, (run) => String(run.length));
13609
+ }
13610
+
13611
+ function dimensions(needed, level, options, rowHeight) {
13612
+ const ecc = pdf417EccLength(level);
13613
+ let best = null;
13614
+ for (let rows = options.rows ?? 3; rows <= (options.rows ?? 90); rows++) {
13615
+ for (let columns = options.columns ?? 1; columns <= (options.columns ?? 30); columns++) {
13616
+ if (rows * columns > 928 || rows * columns - ecc < needed) continue;
13617
+ const ratio = compactPdf417Width(columns) / (rows * rowHeight);
13618
+ const score = (rows * columns - ecc - needed) * 10 +
13619
+ Math.abs(ratio - (options.aspectRatio ?? 3));
13620
+ if (!best || score < best.score) best = { rows, columns, score };
13621
+ }
13622
+ }
13623
+ if (!best) {
13624
+ throw new EncodeError(
13625
+ 'Compact PDF417: payload does not fit the requested dimensions and error correction level'
13626
+ );
13627
+ }
13628
+ return best;
13629
+ }
13630
+
13631
+ /**
13632
+ * Encode Compact PDF417.
13633
+ *
13634
+ * High-level Text/Byte/Numeric compaction is intentionally delegated to the
13635
+ * existing PDF417 compaction implementation. `compact` here describes only
13636
+ * the physical truncated layout: right row indicators are omitted and the
13637
+ * stop pattern is reduced to one dark module.
13638
+ *
13639
+ * @param {string|Uint8Array|number[]} value
13640
+ * @param {object} [options]
13641
+ * @returns {import('../core/bit-matrix.js').BitMatrix}
13642
+ */
13643
+ function encodeCompactPDF417(value, options = {}) {
13644
+ const rowHeight = validateCompactPdf417Options(options);
13645
+ const level = options.eccLevel ?? 2;
13646
+ if (!Number.isInteger(level) || level < 0 || level > 8) {
13647
+ throw new EncodeError('Compact PDF417: eccLevel must be an integer in 0..8');
13648
+ }
13649
+
13650
+ const payload = compactPdf417(value, { compaction: options.compaction, charset: options.charset });
13651
+ const { rows, columns } = dimensions(payload.length + 1, level, options, rowHeight);
13652
+ const eccLength = pdf417EccLength(level);
13653
+ const dataLength = rows * columns - eccLength;
13654
+ const data = [dataLength, ...payload];
13655
+ while (data.length < dataLength) data.push(900);
13656
+ const codewords = data.concat(pdf417ErrorCorrection(data, level));
13657
+
13658
+ const matrix = new BitMatrix(compactPdf417Width(columns), rows * rowHeight);
13659
+ for (let row = 0; row < rows; row++) {
13660
+ const y = row * rowHeight;
13661
+ const cluster = (row % 3) * 3;
13662
+ let x = appendWidths(matrix, y, 0, COMPACT_PDF417_START, rowHeight);
13663
+ const left = compactPdf417Indicators(row, rows, columns, level);
13664
+ x = appendWidths(matrix, y, x, patternSequence(pdf417PatternForCodeword(left, cluster)), rowHeight);
13665
+ for (let column = 0; column < columns; column++) {
13666
+ const codeword = codewords[row * columns + column];
13667
+ x = appendWidths(matrix, y, x,
13668
+ patternSequence(pdf417PatternForCodeword(codeword, cluster)), rowHeight);
13669
+ }
13670
+ // Compact PDF417 terminates every row with one dark module, not the normal
13671
+ // right indicator plus 18-module stop pattern.
13672
+ matrix.setRegion(x, y, 1, rowHeight);
13673
+ x++;
13674
+ if (x !== matrix.width) throw new EncodeError('Compact PDF417: internal row width mismatch');
13675
+ }
13676
+
13677
+ matrix.compactPdf417 = {
13678
+ rows,
13679
+ columns,
13680
+ eccLevel: level,
13681
+ rowHeight,
13682
+ codewords,
13683
+ layout: 'compact',
13684
+ };
13685
+ return matrix;
13686
+ }
13687
+ __exports.compactPdf417Dimensions = dimensions;
13688
+
13689
+ __exports.encodeCompactPDF417 = encodeCompactPDF417;
13690
+ };
13691
+
13692
+ __modules["compactpdf417/decoder.js"] = function (__require, __exports) {
13693
+ /** Compact PDF417 decoder. @module compactpdf417/decoder */
13694
+ const { FormatError } = __require("core/errors.js");
13695
+ const { decodePdf417CompactionDetailed } = __require("pdf417/compaction.js");
13696
+ const { pdf417CorrectErrors, pdf417EccLength } = __require("pdf417/error-correction.js");
13697
+ const { pdf417CodewordForPattern } = __require("pdf417/tables.js");
13698
+ const { COMPACT_PDF417_START_BITS, compactPdf417Geometry, compactPdf417Indicators, compactPdf417MatchingLevels } = __require("compactpdf417/tables.js");
13699
+
13700
+ function bits(matrix, y, x, width) {
13701
+ let value = 0;
13702
+ for (let index = 0; index < width; index++) value = (value << 1) | (matrix.get(x + index, y) ? 1 : 0);
13703
+ return value;
13704
+ }
13705
+
13706
+ function patternString(matrix, y, x, width) {
13707
+ return bits(matrix, y, x, width).toString(2).padStart(width, '0');
13708
+ }
13709
+
13710
+ /**
13711
+ * Decode a compact/truncated PDF417 module matrix.
13712
+ *
13713
+ * The high-level payload uses the normal PDF417 Text/Byte/Numeric compaction
13714
+ * rules. This function only changes the physical row parser: no right row
13715
+ * indicator is expected and the final module of each row must be dark.
13716
+ *
13717
+ * @param {import('../core/bit-matrix.js').BitMatrix} matrix
13718
+ * @param {object} [options]
13719
+ * @param {number} [options.rowHeight]
13720
+ */
13721
+ function decodeCompactPDF417(matrix, options = {}) {
13722
+ if (!matrix?.width || !matrix?.height) throw new FormatError('Compact PDF417: no matrix supplied');
13723
+ const rowHeight = options.rowHeight ?? matrix.compactPdf417?.rowHeight ?? 3;
13724
+ let geometry;
13725
+ try { geometry = compactPdf417Geometry(matrix.width, matrix.height, rowHeight); }
13726
+ catch (error) { throw new FormatError(error.message); }
13727
+
13728
+ const { rows, columns } = geometry;
13729
+ const all = [];
13730
+ const erasures = [];
13731
+ const leftIndicators = [];
13732
+
13733
+ for (let row = 0; row < rows; row++) {
13734
+ const y = row * rowHeight;
13735
+ if (patternString(matrix, y, 0, 17) !== COMPACT_PDF417_START_BITS) {
13736
+ throw new FormatError('Compact PDF417: missing start pattern');
13737
+ }
13738
+ const cluster = (row % 3) * 3;
13739
+ const leftDecoded = pdf417CodewordForPattern(bits(matrix, y, 17, 17));
13740
+ if (!leftDecoded || leftDecoded.cluster !== cluster) {
13741
+ throw new FormatError('Compact PDF417: invalid left row indicator');
13742
+ }
13743
+ leftIndicators.push(leftDecoded.codeword);
13744
+
13745
+ const dataStart = 34;
13746
+ const stopX = dataStart + columns * 17;
13747
+ if (!matrix.get(stopX, y)) throw new FormatError('Compact PDF417: missing reduced stop module');
13748
+ for (let column = 0; column < columns; column++) {
13749
+ const decoded = pdf417CodewordForPattern(bits(matrix, y, dataStart + column * 17, 17));
13750
+ if (!decoded || decoded.cluster !== cluster) {
13751
+ erasures.push(all.length);
13752
+ all.push(0);
13753
+ } else {
13754
+ all.push(decoded.codeword);
13755
+ }
13756
+ }
13757
+ }
13758
+
13759
+ const levels = compactPdf417MatchingLevels(leftIndicators, rows, columns);
13760
+ if (levels.length !== 1) throw new FormatError('Compact PDF417: row indicator mismatch');
13761
+ const level = levels[0];
13762
+ const eccLength = pdf417EccLength(level);
13763
+ if (all.length <= eccLength) throw new FormatError('Compact PDF417: insufficient codewords for ECC');
13764
+
13765
+ const corrected = all.slice();
13766
+ const corrections = pdf417CorrectErrors(corrected, level, erasures);
13767
+ const length = corrected[0];
13768
+ if (length < 1 || length > corrected.length - eccLength) {
13769
+ throw new FormatError('Compact PDF417: invalid symbol length descriptor');
13770
+ }
13771
+ const payload = corrected.slice(1, length);
13772
+ const decoded = decodePdf417CompactionDetailed(payload);
13773
+ return {
13774
+ ...decoded,
13775
+ format: 'compact-pdf417',
13776
+ compact: true,
13777
+ codewords: corrected,
13778
+ rows,
13779
+ columns,
13780
+ eccLevel: level,
13781
+ rowHeight,
13782
+ corrections,
13783
+ };
13784
+ }
13785
+
13786
+ __exports.decodeCompactPDF417 = decodeCompactPDF417;
13787
+ };
13788
+
13789
+ __modules["compactpdf417/detector.js"] = function (__require, __exports) {
13790
+ /** Compact PDF417 detector for clean, integer-scaled rasters. @module compactpdf417/detector */
13791
+ const { BitMatrix } = __require("core/bit-matrix.js");
13792
+ const { compactPdf417Width } = __require("compactpdf417/tables.js");
13793
+ const { decodeCompactPDF417 } = __require("compactpdf417/decoder.js");
13794
+
13795
+ function rotateClockwise(source) {
13796
+ const out = new BitMatrix(source.height, source.width);
13797
+ for (let y = 0; y < source.height; y++) {
13798
+ for (let x = 0; x < source.width; x++) {
13799
+ if (source.get(x, y)) out.set(source.height - 1 - y, x);
13800
+ }
13801
+ }
13802
+ return out;
13803
+ }
13804
+ function cropAndDownsample(source, box, width, height, scale) {
13805
+ const out = new BitMatrix(width, height);
13806
+ for (let y = 0; y < height; y++) {
13807
+ for (let x = 0; x < width; x++) {
13808
+ let dark = 0;
13809
+ for (let dy = 0; dy < scale; dy++) {
13810
+ for (let dx = 0; dx < scale; dx++) {
13811
+ if (source.get(box.x + x * scale + dx, box.y + y * scale + dy)) dark++;
13812
+ }
13813
+ }
13814
+ if (dark * 2 >= scale * scale) out.set(x, y);
13815
+ }
13816
+ }
13817
+ return out;
13818
+ }
13819
+
13820
+ function cornersFor(box) {
13821
+ return [
13822
+ { x: box.x, y: box.y },
13823
+ { x: box.x + box.width, y: box.y },
13824
+ { x: box.x + box.width, y: box.y + box.height },
13825
+ { x: box.x, y: box.y + box.height },
13826
+ ];
13827
+ }
13828
+
13829
+ function mapCorners(corners, toOriginal) {
13830
+ return corners.map((point) => toOriginal(point));
13831
+ }
13832
+
13833
+ /**
13834
+ * Detect one Compact PDF417 symbol in a binarized raster.
13835
+ *
13836
+ * The clean-raster detector uses the dark bounding box and enumerates legal
13837
+ * compact widths, integer module scales, row counts and row heights. It is
13838
+ * deliberately conservative: arbitrary perspective, non-integer resampling,
13839
+ * grayscale thresholding and damaged stop bars belong to a future photo
13840
+ * detector and are not claimed here.
13841
+ *
13842
+ * @param {import('../core/bit-matrix.js').BitMatrix} binaryImage
13843
+ * @param {object} [options]
13844
+ * @param {number} [options.rowHeight] Restrict the row-height search.
13845
+ * @returns {object|null}
13846
+ */
13847
+ function detectCompactPDF417(binaryImage, options = {}) {
13848
+ if (!binaryImage?.width || !binaryImage?.height || typeof binaryImage.get !== 'function') return null;
13849
+
13850
+ let oriented = binaryImage;
13851
+ let toOriginal = (point) => ({ x: point.x, y: point.y });
13852
+ for (let rotation = 0; rotation < 4; rotation++) {
13853
+ const bounds = oriented.getBounds();
13854
+ if (bounds) {
13855
+ for (let columns = 1; columns <= 30; columns++) {
13856
+ const width = compactPdf417Width(columns);
13857
+ const scale = bounds.width / width;
13858
+ if (!Number.isInteger(scale) || scale < 1) continue;
13859
+ const baseHeight = bounds.height / scale;
13860
+ const rowHeights = Number.isInteger(options.rowHeight)
13861
+ ? [options.rowHeight]
13862
+ : Array.from({ length: 18 }, (_, index) => index + 3);
13863
+ for (const rowHeight of rowHeights) {
13864
+ if (!Number.isInteger(baseHeight / rowHeight)) continue;
13865
+ const rows = baseHeight / rowHeight;
13866
+ if (rows < 3 || rows > 90) continue;
13867
+ const matrix = cropAndDownsample(oriented, bounds, width, baseHeight, scale);
13868
+ try {
13869
+ const result = decodeCompactPDF417(matrix, { rowHeight });
13870
+ const corners = mapCorners(cornersFor(bounds), toOriginal);
13871
+ return {
13872
+ ...result,
13873
+ matrix,
13874
+ corners,
13875
+ rotation: rotation * 90,
13876
+ moduleSize: scale,
13877
+ compact: true,
13878
+ };
13879
+ } catch {
13880
+ // Try another geometry; a standard PDF417 or random artwork should
13881
+ // never be accepted unless the compact decoder validates every row.
13882
+ }
13883
+ }
13884
+ }
13885
+ }
13886
+
13887
+ const previous = oriented;
13888
+ const previousToOriginal = toOriginal;
13889
+ oriented = rotateClockwise(previous);
13890
+ toOriginal = (point) => previousToOriginal({ x: point.y, y: previous.height - point.x });
13891
+ }
13892
+ return null;
13893
+ }
13894
+ function detectAndDecodeCompactPDF417(binaryImage, options = {}) {
13895
+ return detectCompactPDF417(binaryImage, options);
13896
+ }
13897
+
13898
+ __exports.detectCompactPDF417 = detectCompactPDF417;
13899
+ __exports.detectAndDecodeCompactPDF417 = detectAndDecodeCompactPDF417;
13900
+ };
13901
+
13902
+ __modules["compactpdf417/index.js"] = function (__require, __exports) {
13903
+ /* Compact PDF417 public module exports. */
13904
+ const __reexport0 = __require("compactpdf417/tables.js"); __exports.COMPACT_PDF417_START = __reexport0.COMPACT_PDF417_START; __exports.COMPACT_PDF417_START_BITS = __reexport0.COMPACT_PDF417_START_BITS; __exports.COMPACT_PDF417_STOP_MODULES = __reexport0.COMPACT_PDF417_STOP_MODULES; __exports.COMPACT_PDF417_LIMITS = __reexport0.COMPACT_PDF417_LIMITS; __exports.compactPdf417Width = __reexport0.compactPdf417Width; __exports.compactPdf417Geometry = __reexport0.compactPdf417Geometry; __exports.compactPdf417Indicators = __reexport0.compactPdf417Indicators; __exports.compactPdf417MatchingLevels = __reexport0.compactPdf417MatchingLevels; __exports.validateCompactPdf417Options = __reexport0.validateCompactPdf417Options; __exports.validateCompactPdf417Tables = __reexport0.validateCompactPdf417Tables;
13905
+ const __reexport1 = __require("compactpdf417/encoder.js"); __exports.encodeCompactPDF417 = __reexport1.encodeCompactPDF417; __exports.compactPdf417Dimensions = __reexport1.compactPdf417Dimensions;
13906
+ const __reexport2 = __require("compactpdf417/decoder.js"); __exports.decodeCompactPDF417 = __reexport2.decodeCompactPDF417;
13907
+ const __reexport3 = __require("compactpdf417/detector.js"); __exports.detectCompactPDF417 = __reexport3.detectCompactPDF417; __exports.detectAndDecodeCompactPDF417 = __reexport3.detectAndDecodeCompactPDF417;
13908
+
13909
+
13910
+ };
13911
+
13912
+ __modules["databar/tables.js"] = function (__require, __exports) {
13913
+ /**
13914
+ * Static GS1 DataBar facts used by the GTIN compaction codec.
13915
+ *
13916
+ * The numbers in the DataBar-14 group tables are the public tables in
13917
+ * ISO/IEC 24724:2011, clauses 5.2.2 and 5.2.3. They describe values, not a
13918
+ * third-party implementation. Pattern construction deliberately belongs in
13919
+ * the renderer/encoder layer so this module stays a small, auditable contract.
13920
+ *
13921
+ * @module databar/tables
13922
+ */
13923
+
13924
+ const group = (first, last, gsum, oddModules, evenModules, oddWidest, evenWidest, oddTotal, evenTotal) => Object.freeze({
13925
+ first, last, gsum, oddModules, evenModules, oddWidest, evenWidest, oddTotal, evenTotal,
13926
+ });
13927
+
13928
+ /** The four GTIN-only layouts sharing the DataBar-14 compaction rules. */
13929
+ const DATABAR14_VARIANTS = Object.freeze({
13930
+ omnidirectional: Object.freeze({ id: 'omnidirectional', rows: 1, modules: 96, checksumModulus: 79, pointOfSale: true }),
13931
+ truncated: Object.freeze({ id: 'truncated', rows: 1, modules: 96, checksumModulus: 79, pointOfSale: false }),
13932
+ stacked: Object.freeze({ id: 'stacked', rows: 2, modules: 50, checksumModulus: 79, pointOfSale: false }),
13933
+ 'stacked-omnidirectional': Object.freeze({ id: 'stacked-omnidirectional', rows: 2, modules: 50, checksumModulus: 79, pointOfSale: true }),
13934
+ });
13935
+
13936
+ /** GS1 DataBar Limited is a distinct two-character symbology. */
13937
+ const DATABAR_LIMITED_VARIANT = Object.freeze({
13938
+ id: 'limited', rows: 1, checksumModulus: 89, pointOfSale: false,
13939
+ permittedIndicatorDigits: Object.freeze([0, 1]),
13940
+ });
13941
+
13942
+ /** (16,4) outside character groups, ISO/IEC 24724:2011 Table 1. */
13943
+ const DATABAR14_OUTSIDE_GROUPS = Object.freeze([
13944
+ group(0, 160, 0, 12, 4, 8, 1, 161, 1),
13945
+ group(161, 960, 161, 10, 6, 6, 3, 80, 10),
13946
+ group(961, 2014, 961, 8, 8, 4, 5, 31, 34),
13947
+ group(2015, 2714, 2015, 6, 10, 3, 6, 10, 70),
13948
+ group(2715, 2840, 2715, 4, 12, 1, 8, 1, 126),
13949
+ ]);
13950
+
13951
+ /** (15,4) inside character groups, ISO/IEC 24724:2011 Table 2. */
13952
+ const DATABAR14_INSIDE_GROUPS = Object.freeze([
13953
+ group(0, 335, 0, 5, 10, 2, 7, 4, 84),
13954
+ group(336, 1035, 336, 7, 8, 4, 5, 20, 35),
13955
+ group(1036, 1515, 1036, 9, 6, 6, 3, 48, 10),
13956
+ group(1516, 1596, 1516, 11, 4, 8, 1, 81, 1),
13957
+ ]);
13958
+
13959
+ /** Number of values carried by an inside (15,4) character. */
13960
+ const DATABAR14_INSIDE_RADIX = 1597;
13961
+ /** Number of values carried by one outside/inside character pair. */
13962
+ const DATABAR14_PAIR_RADIX = 4537077;
13963
+ /** Stand-alone and composite DataBar-14 payload domain, including linkage. */
13964
+ const DATABAR14_SYMBOL_LIMIT = 20000000000000n;
13965
+
13966
+ /** GS1 DataBar Limited divides its 13 data digits into two character values. */
13967
+ const DATABAR_LIMITED_PAIR_RADIX = 2013571;
13968
+ /** Offset that switches a DataBar Limited value from stand-alone to composite. */
13969
+ const DATABAR_LIMITED_LINKAGE_OFFSET = 2015133531096n;
13970
+ /** DataBar Limited carries GTIN values whose first digit is zero or one. */
13971
+ const DATABAR_LIMITED_DATA_LIMIT = 2000000000000n;
13972
+
13973
+ /** Locate the value group that an outside or inside character belongs to. */
13974
+ function dataBar14GroupFor(value, kind) {
13975
+ if (!Number.isInteger(value)) throw new TypeError('GS1 DataBar character value must be an integer');
13976
+ const groups = kind === 'outside' ? DATABAR14_OUTSIDE_GROUPS
13977
+ : kind === 'inside' ? DATABAR14_INSIDE_GROUPS : null;
13978
+ if (!groups) throw new RangeError(`Unknown GS1 DataBar character kind "${kind}"`);
13979
+ const found = groups.find((entry) => value >= entry.first && value <= entry.last);
13980
+ if (!found) throw new RangeError(`GS1 DataBar ${kind} character value ${value} is out of range`);
13981
+ return found;
13982
+ }
13983
+ /** Check the independently represented table identities. */
13984
+ function validateDataBarTables() {
13985
+ const problems = [];
13986
+ const validateGroups = (name, groups, expectedLast) => {
13987
+ let next = 0;
13988
+ for (const entry of groups) {
13989
+ if (entry.first !== next) problems.push(`${name}: gap before ${entry.first}`);
13990
+ if (entry.last < entry.first) problems.push(`${name}: inverted range ${entry.first}-${entry.last}`);
13991
+ if (entry.oddTotal * entry.evenTotal !== entry.last - entry.first + 1) {
13992
+ problems.push(`${name}: combination count mismatch at ${entry.first}`);
13993
+ }
13994
+ next = entry.last + 1;
13995
+ }
13996
+ if (next - 1 !== expectedLast) problems.push(`${name}: final value is ${next - 1}, expected ${expectedLast}`);
13997
+ };
13998
+ validateGroups('outside', DATABAR14_OUTSIDE_GROUPS, 2840);
13999
+ validateGroups('inside', DATABAR14_INSIDE_GROUPS, 1596);
14000
+ if (DATABAR14_PAIR_RADIX !== 2841 * DATABAR14_INSIDE_RADIX) problems.push('pair radix mismatch');
14001
+ if (DATABAR14_SYMBOL_LIMIT !== 2n * 10000000000000n) problems.push('symbol limit mismatch');
14002
+ if (DATABAR_LIMITED_LINKAGE_OFFSET !== BigInt(DATABAR_LIMITED_PAIR_RADIX) * 1000776n) {
14003
+ problems.push('limited linkage offset mismatch');
14004
+ }
14005
+ return problems;
14006
+ }
14007
+
14008
+ __exports.DATABAR14_VARIANTS = DATABAR14_VARIANTS;
14009
+ __exports.DATABAR_LIMITED_VARIANT = DATABAR_LIMITED_VARIANT;
14010
+ __exports.DATABAR14_OUTSIDE_GROUPS = DATABAR14_OUTSIDE_GROUPS;
14011
+ __exports.DATABAR14_INSIDE_GROUPS = DATABAR14_INSIDE_GROUPS;
14012
+ __exports.DATABAR14_INSIDE_RADIX = DATABAR14_INSIDE_RADIX;
14013
+ __exports.DATABAR14_PAIR_RADIX = DATABAR14_PAIR_RADIX;
14014
+ __exports.DATABAR14_SYMBOL_LIMIT = DATABAR14_SYMBOL_LIMIT;
14015
+ __exports.DATABAR_LIMITED_PAIR_RADIX = DATABAR_LIMITED_PAIR_RADIX;
14016
+ __exports.DATABAR_LIMITED_LINKAGE_OFFSET = DATABAR_LIMITED_LINKAGE_OFFSET;
14017
+ __exports.DATABAR_LIMITED_DATA_LIMIT = DATABAR_LIMITED_DATA_LIMIT;
14018
+ __exports.dataBar14GroupFor = dataBar14GroupFor;
14019
+ __exports.validateDataBarTables = validateDataBarTables;
14020
+ };
14021
+
14022
+ __modules["databar/codec.js"] = function (__require, __exports) {
14023
+ /**
14024
+ * GTIN validation and numeric compaction for GS1 DataBar GTIN-only symbols.
14025
+ *
14026
+ * This is intentionally not a bar-pattern encoder. It emits the exact symbol
14027
+ * character values required by ISO/IEC 24724:2011; a later encoder can turn
14028
+ * those values into widths without reinterpreting a GTIN or linkage flag.
14029
+ *
14030
+ * @module databar/codec
14031
+ */
14032
+ const { DATABAR14_INSIDE_RADIX, DATABAR14_PAIR_RADIX, DATABAR14_SYMBOL_LIMIT, DATABAR_LIMITED_DATA_LIMIT, DATABAR_LIMITED_LINKAGE_OFFSET, DATABAR_LIMITED_PAIR_RADIX } = __require("databar/tables.js");
14033
+
14034
+ const GTIN_LENGTHS = new Set([8, 12, 13, 14]);
14035
+
14036
+ function digits(value, label) {
14037
+ const text = String(value);
14038
+ if (!/^\d+$/.test(text)) throw new TypeError(`${label} must contain only decimal digits`);
14039
+ return text;
14040
+ }
14041
+
14042
+ function asCharacterValue(value, label, maximum) {
14043
+ if (!Number.isInteger(value) || value < 0 || value > maximum) {
14044
+ throw new RangeError(`${label} must be an integer from 0 to ${maximum}`);
14045
+ }
14046
+ return value;
14047
+ }
14048
+
14049
+ /** Calculate the GS1 modulo-10 check digit for a GTIN body. */
14050
+ function gtinCheckDigit(body) {
14051
+ const text = digits(body, 'GTIN body');
14052
+ if (text.length < 1 || text.length > 13) throw new RangeError('GTIN body must contain 1 to 13 digits');
14053
+ let sum = 0;
14054
+ for (let i = text.length - 1, weight = 3; i >= 0; i--, weight = weight === 3 ? 1 : 3) {
14055
+ sum += Number(text[i]) * weight;
14056
+ }
14057
+ return String((10 - (sum % 10)) % 10);
14058
+ }
14059
+
14060
+ /** Return a checked 14-digit GTIN, preserving only its standardized digits. */
14061
+ function normalizeGTIN(value) {
14062
+ const input = digits(value, 'GTIN');
14063
+ if (!GTIN_LENGTHS.has(input.length)) {
14064
+ throw new RangeError('GTIN must contain 8, 12, 13, or 14 digits including its check digit');
14065
+ }
14066
+ if (gtinCheckDigit(input.slice(0, -1)) !== input.at(-1)) {
14067
+ throw new RangeError(`GTIN check digit is invalid for ${input}`);
14068
+ }
14069
+ return input.padStart(14, '0');
14070
+ }
14071
+
14072
+ /** Build a checked GTIN-14 from its thirteen-digit data body. */
14073
+ function makeGTIN14(body) {
14074
+ const input = digits(body, 'GTIN-14 body');
14075
+ if (input.length > 13) throw new RangeError('GTIN-14 body must contain at most 13 digits');
14076
+ const padded = input.padStart(13, '0');
14077
+ return padded + gtinCheckDigit(padded);
14078
+ }
14079
+
14080
+ function gtinFromSymbolValue(symbolValue) {
14081
+ const value = BigInt(symbolValue);
14082
+ if (value < 0n || value >= DATABAR14_SYMBOL_LIMIT) throw new RangeError('GS1 DataBar-14 symbol value is out of range');
14083
+ const linkage = value >= 10000000000000n;
14084
+ const body = (linkage ? value - 10000000000000n : value).toString().padStart(13, '0');
14085
+ return { linkage, gtin: body + gtinCheckDigit(body) };
14086
+ }
14087
+
14088
+ /**
14089
+ * Compact a GTIN into the four values shared by Omnidirectional, Truncated,
14090
+ * Stacked and Stacked Omnidirectional. The `physicalCharacters` sequence is
14091
+ * left-to-right on a linear DataBar-14 row: 1, 2, 4, 3.
14092
+ */
14093
+ function encodeDataBar14GTIN(value, options = {}) {
14094
+ const gtin = normalizeGTIN(value);
14095
+ const linkage = options.linkage === true;
14096
+ if (options.linkage !== undefined && typeof options.linkage !== 'boolean') {
14097
+ throw new TypeError('GS1 DataBar linkage must be a boolean');
14098
+ }
14099
+ const dataBody = gtin.slice(0, -1);
14100
+ const symbolValue = BigInt(dataBody) + (linkage ? 10000000000000n : 0n);
14101
+ const leftPair = symbolValue / BigInt(DATABAR14_PAIR_RADIX);
14102
+ const rightPair = symbolValue % BigInt(DATABAR14_PAIR_RADIX);
14103
+ const outerLeft = Number(leftPair / BigInt(DATABAR14_INSIDE_RADIX));
14104
+ const innerLeft = Number(leftPair % BigInt(DATABAR14_INSIDE_RADIX));
14105
+ const outerRight = Number(rightPair / BigInt(DATABAR14_INSIDE_RADIX));
14106
+ const innerRight = Number(rightPair % BigInt(DATABAR14_INSIDE_RADIX));
14107
+
14108
+ return Object.freeze({
14109
+ gtin, linkage, symbolValue, leftPair, rightPair,
14110
+ logicalCharacters: Object.freeze({ outerLeft, innerLeft, outerRight, innerRight }),
14111
+ physicalCharacters: Object.freeze([outerLeft, innerLeft, innerRight, outerRight]),
14112
+ });
14113
+ }
14114
+
14115
+ /** Reconstruct and validate a GTIN from the four DataBar-14 character values. */
14116
+ function decodeDataBar14GTIN(values) {
14117
+ if (values === null || typeof values !== 'object') throw new TypeError('GS1 DataBar-14 characters must be an object');
14118
+ const outerLeft = asCharacterValue(values.outerLeft, 'outerLeft', 2840);
14119
+ const innerLeft = asCharacterValue(values.innerLeft, 'innerLeft', 1596);
14120
+ const outerRight = asCharacterValue(values.outerRight, 'outerRight', 2840);
14121
+ const innerRight = asCharacterValue(values.innerRight, 'innerRight', 1596);
14122
+ const leftPair = BigInt(outerLeft) * BigInt(DATABAR14_INSIDE_RADIX) + BigInt(innerLeft);
14123
+ const rightPair = BigInt(outerRight) * BigInt(DATABAR14_INSIDE_RADIX) + BigInt(innerRight);
14124
+ return Object.freeze({
14125
+ ...gtinFromSymbolValue(leftPair * BigInt(DATABAR14_PAIR_RADIX) + rightPair),
14126
+ leftPair, rightPair,
14127
+ });
14128
+ }
14129
+
14130
+ /** Compact a DataBar Limited-eligible GTIN into its two data character values. */
14131
+ function encodeDataBarLimitedGTIN(value, options = {}) {
14132
+ const gtin = normalizeGTIN(value);
14133
+ const linkage = options.linkage === true;
14134
+ if (options.linkage !== undefined && typeof options.linkage !== 'boolean') {
14135
+ throw new TypeError('GS1 DataBar linkage must be a boolean');
14136
+ }
14137
+ const dataBody = BigInt(gtin.slice(0, -1));
14138
+ if (dataBody >= DATABAR_LIMITED_DATA_LIMIT) {
14139
+ throw new RangeError('GS1 DataBar Limited requires a GTIN whose indicator digit is 0 or 1');
14140
+ }
14141
+ const symbolValue = dataBody + (linkage ? DATABAR_LIMITED_LINKAGE_OFFSET : 0n);
14142
+ const left = Number(symbolValue / BigInt(DATABAR_LIMITED_PAIR_RADIX));
14143
+ const right = Number(symbolValue % BigInt(DATABAR_LIMITED_PAIR_RADIX));
14144
+ return Object.freeze({ gtin, linkage, symbolValue, left, right });
14145
+ }
14146
+
14147
+ /** Reconstruct and validate a GTIN from DataBar Limited data character values. */
14148
+ function decodeDataBarLimitedGTIN(values) {
14149
+ if (values === null || typeof values !== 'object') throw new TypeError('GS1 DataBar Limited characters must be an object');
14150
+ const left = asCharacterValue(values.left, 'left', 1994036);
14151
+ const right = asCharacterValue(values.right, 'right', DATABAR_LIMITED_PAIR_RADIX - 1);
14152
+ let symbolValue = BigInt(left) * BigInt(DATABAR_LIMITED_PAIR_RADIX) + BigInt(right);
14153
+ const linkage = symbolValue >= DATABAR_LIMITED_LINKAGE_OFFSET;
14154
+ if (linkage) symbolValue -= DATABAR_LIMITED_LINKAGE_OFFSET;
14155
+ if (symbolValue < 0n || symbolValue >= DATABAR_LIMITED_DATA_LIMIT) {
14156
+ throw new RangeError('GS1 DataBar Limited character values do not encode a permitted GTIN');
14157
+ }
14158
+ const body = symbolValue.toString().padStart(13, '0');
14159
+ return Object.freeze({ linkage, gtin: body + gtinCheckDigit(body), symbolValue: BigInt(left) * BigInt(DATABAR_LIMITED_PAIR_RADIX) + BigInt(right) });
14160
+ }
14161
+
14162
+ /** GS1 transmitted form for the GTIN-only DataBar variants. */
14163
+ function dataBarGtinTransmission(value) {
14164
+ return `]e001${normalizeGTIN(value)}`;
14165
+ }
14166
+
14167
+ __exports.gtinCheckDigit = gtinCheckDigit;
14168
+ __exports.normalizeGTIN = normalizeGTIN;
14169
+ __exports.makeGTIN14 = makeGTIN14;
14170
+ __exports.encodeDataBar14GTIN = encodeDataBar14GTIN;
14171
+ __exports.decodeDataBar14GTIN = decodeDataBar14GTIN;
14172
+ __exports.encodeDataBarLimitedGTIN = encodeDataBarLimitedGTIN;
14173
+ __exports.decodeDataBarLimitedGTIN = decodeDataBarLimitedGTIN;
14174
+ __exports.dataBarGtinTransmission = dataBarGtinTransmission;
14175
+ };
14176
+
14177
+ __modules["databar/gs1.js"] = function (__require, __exports) {
14178
+ /** GS1 element-string codec used by GS1 DataBar Expanded. @module databar/gs1 */
14179
+ const { EncodeError, FormatError } = __require("core/errors.js");
14180
+ const GS1_SEPARATOR = '\x1d';
14181
+
14182
+ const EXACT = new Map([
14183
+ ['00', [18, true]], ['01', [14, true]], ['02', [14, true]],
14184
+ ['10', [20, false]], ['11', [6, true]], ['12', [6, true]],
14185
+ ['13', [6, true]], ['15', [6, true]], ['16', [6, true]],
14186
+ ['17', [6, true]], ['20', [2, true]], ['21', [20, false]],
14187
+ ['22', [29, false]], ['30', [8, false]], ['37', [8, false]],
14188
+ ['240', [30, false]], ['241', [30, false]], ['242', [6, false]],
14189
+ ['243', [20, false]], ['250', [30, false]], ['251', [30, false]],
14190
+ ['253', [30, false]], ['254', [20, false]], ['255', [13, true]],
14191
+ ['400', [30, false]], ['401', [30, false]], ['402', [17, true]],
14192
+ ['403', [30, false]], ['410', [13, true]], ['411', [13, true]],
14193
+ ['412', [13, true]], ['413', [13, true]], ['414', [13, true]],
14194
+ ['415', [13, true]], ['416', [13, true]], ['417', [13, true]],
14195
+ ['420', [20, false]], ['421', [15, false]], ['422', [3, true]],
14196
+ ['423', [15, false]], ['424', [3, true]], ['425', [3, true]],
14197
+ ['426', [3, true]], ['427', [3, false]],
14198
+ ['7001', [13, true]], ['7002', [30, false]], ['7003', [10, true]],
14199
+ ['7004', [4, false]], ['7005', [12, false]], ['7006', [6, true]],
14200
+ ['7007', [12, false]], ['7008', [3, false]], ['7009', [10, false]],
14201
+ ['7010', [2, false]], ['7020', [20, false]], ['7021', [20, false]],
14202
+ ['7022', [20, false]], ['710', [20, false]], ['711', [20, false]],
14203
+ ['712', [20, false]], ['713', [20, false]], ['714', [20, false]],
14204
+ ['715', [20, false]],
14205
+ ['8001', [14, true]], ['8002', [20, false]], ['8003', [30, false]],
14206
+ ['8004', [30, false]], ['8005', [6, true]], ['8006', [18, true]],
14207
+ ['8007', [34, false]], ['8008', [12, false]], ['8009', [50, false]],
14208
+ ['8010', [30, false]], ['8011', [12, false]], ['8012', [20, false]],
14209
+ ['8013', [30, false]], ['8017', [18, true]], ['8018', [18, true]],
14210
+ ['8019', [10, false]], ['8020', [25, false]], ['8026', [18, true]],
14211
+ ['8110', [70, false]], ['8111', [4, true]], ['8112', [70, false]],
14212
+ ['8200', [70, false]],
14213
+ ]);
14214
+
14215
+ function rangedAI(ai) {
14216
+ if (/^31[0-6]\d$/.test(ai) || /^32[0-7]\d$/.test(ai) ||
14217
+ /^33[0-7]\d$/.test(ai) || /^34[0-9]\d$/.test(ai) ||
14218
+ /^35[0-7]\d$/.test(ai) || /^36[0-9]\d$/.test(ai)) return [6, true];
14219
+ if (/^390\d$/.test(ai) || /^392\d$/.test(ai)) return [15, false];
14220
+ if (/^391\d$/.test(ai) || /^393\d$/.test(ai)) return [18, false];
14221
+ if (/^394\d$/.test(ai)) return [4, true];
14222
+ if (/^395\d$/.test(ai)) return [6, true];
14223
+ if (/^703\d$/.test(ai) || /^723\d$/.test(ai)) return [30, false];
14224
+ return undefined;
14225
+ }
14226
+ function gs1AIInfo(ai) {
14227
+ if (typeof ai !== 'string' || !/^\d{2,4}$/.test(ai)) return undefined;
14228
+ const spec = EXACT.get(ai) || rangedAI(ai);
14229
+ if (!spec) return undefined;
14230
+ return { ai, length: spec[0], fixed: spec[1] };
14231
+ }
14232
+
14233
+ function assertCharacters(value, label, ErrorType) {
14234
+ if (/[^\x20-\x7e]/.test(value)) {
14235
+ throw new ErrorType(`GS1: ${label} contains a character outside the GS1 element-string character set`);
14236
+ }
14237
+ }
14238
+
14239
+ function validateElement(ai, value, ErrorType) {
14240
+ const info = gs1AIInfo(ai);
14241
+ if (!info) throw new ErrorType(`GS1: unsupported or invalid Application Identifier ${ai}`);
14242
+ if (value.length === 0) throw new ErrorType(`GS1: AI ${ai} must not be empty`);
14243
+ if (info.fixed ? value.length !== info.length : value.length > info.length) {
14244
+ const expectation = info.fixed ? `exactly ${info.length}` : `at most ${info.length}`;
14245
+ throw new ErrorType(`GS1: AI ${ai} requires ${expectation} characters`);
14246
+ }
14247
+ assertCharacters(value, `AI ${ai}`, ErrorType);
14248
+ return { ai, value, fixed: info.fixed };
14249
+ }
14250
+ function parseGS1ElementString(input) {
14251
+ if (typeof input !== 'string' || input.length === 0) {
14252
+ throw new EncodeError('GS1: element string must be a non-empty string');
14253
+ }
14254
+ const elements = [];
14255
+ let offset = 0;
14256
+ while (offset < input.length) {
14257
+ const match = /^\((\d{2,4})\)/.exec(input.slice(offset));
14258
+ if (!match) throw new EncodeError(`GS1: expected an Application Identifier at offset ${offset}`);
14259
+ const ai = match[1];
14260
+ offset += match[0].length;
14261
+ const next = input.indexOf('(', offset);
14262
+ const end = next < 0 ? input.length : next;
14263
+ elements.push(validateElement(ai, input.slice(offset, end), EncodeError));
14264
+ offset = end;
14265
+ }
14266
+ return elements;
14267
+ }
14268
+ function encodeGS1ElementString(input) {
14269
+ const elements = Array.isArray(input)
14270
+ ? input.map(({ ai, value }) => validateElement(String(ai), String(value), EncodeError))
14271
+ : parseGS1ElementString(input);
14272
+ return elements.map((element, index) =>
14273
+ `${element.ai}${element.value}${!element.fixed && index + 1 < elements.length ? GS1_SEPARATOR : ''}`
14274
+ ).join('');
14275
+ }
14276
+
14277
+ function matchAIAt(data, offset) {
14278
+ for (const length of [4, 3, 2]) {
14279
+ const ai = data.slice(offset, offset + length);
14280
+ if (gs1AIInfo(ai)) return ai;
14281
+ }
14282
+ return undefined;
14283
+ }
14284
+ function decodeGS1ElementString(data) {
14285
+ if (typeof data !== 'string' || data.length === 0) {
14286
+ throw new FormatError('GS1: encoded data must be a non-empty string');
14287
+ }
14288
+ const elements = [];
14289
+ let offset = 0;
14290
+ while (offset < data.length) {
14291
+ if (data[offset] === GS1_SEPARATOR) {
14292
+ throw new FormatError(`GS1: unexpected separator at offset ${offset}`);
14293
+ }
14294
+ const ai = matchAIAt(data, offset);
14295
+ if (!ai) throw new FormatError(`GS1: unknown Application Identifier at offset ${offset}`);
14296
+ offset += ai.length;
14297
+ const info = gs1AIInfo(ai);
14298
+ let value;
14299
+ if (info.fixed) {
14300
+ value = data.slice(offset, offset + info.length);
14301
+ if (value.length !== info.length || value.includes(GS1_SEPARATOR)) {
14302
+ throw new FormatError(`GS1: truncated fixed-length AI ${ai}`);
14303
+ }
14304
+ offset += info.length;
14305
+ } else {
14306
+ const separator = data.indexOf(GS1_SEPARATOR, offset);
14307
+ const end = separator < 0 ? data.length : separator;
14308
+ value = data.slice(offset, end);
14309
+ offset = separator < 0 ? data.length : separator + 1;
14310
+ }
14311
+ elements.push(validateElement(ai, value, FormatError));
14312
+ }
14313
+ return elements;
14314
+ }
14315
+ function formatGS1Elements(elements) {
14316
+ return elements.map(({ ai, value }) => `(${ai})${value}`).join('');
14317
+ }
14318
+
14319
+ __exports.GS1_SEPARATOR = GS1_SEPARATOR;
14320
+ __exports.gs1AIInfo = gs1AIInfo;
14321
+ __exports.parseGS1ElementString = parseGS1ElementString;
14322
+ __exports.encodeGS1ElementString = encodeGS1ElementString;
14323
+ __exports.decodeGS1ElementString = decodeGS1ElementString;
14324
+ __exports.formatGS1Elements = formatGS1Elements;
14325
+ };
14326
+
14327
+ __modules["databar/patterns.js"] = function (__require, __exports) {
14328
+ /** Mathematical width construction for GS1 DataBar characters. @module databar/patterns */
14329
+ const { dataBar14GroupFor } = __require("databar/tables.js");
14330
+
14331
+ function combinations(n, r) {
14332
+ if (n < r || r < 0) return 0;
14333
+ if (r === 0 || n === r) return 1;
14334
+ let result = 1;
14335
+ const k = Math.min(r, n - r);
14336
+ for (let i = 1; i <= k; i++) result = result * (n - k + i) / i;
14337
+ return result;
14338
+ }
14339
+
14340
+ /**
14341
+ * Unrank one constrained positive composition.
14342
+ *
14343
+ * The rank is the GS1 DataBar symbol-character value inside its group. This
14344
+ * implementation follows the combinatorial definition directly: it counts
14345
+ * every remaining admissible suffix rather than storing third-party patterns.
14346
+ */
14347
+ function dataBarWidths(rank, modules, elements, maximumWidth, noNarrow) {
14348
+ if (!Number.isInteger(rank) || rank < 0) throw new RangeError('GS1 DataBar width rank must be non-negative');
14349
+ const widths = new Array(elements).fill(0);
14350
+ let remaining = modules;
14351
+ let narrowMask = 0;
14352
+
14353
+ for (let bar = 0; bar < elements - 1; bar++) {
14354
+ let count = 0;
14355
+ for (let width = 1; ; width++) {
14356
+ narrowMask |= width === 1 ? 1 << bar : 0;
14357
+ count = combinations(remaining - width - 1, elements - bar - 2);
14358
+
14359
+ if (noNarrow && narrowMask === 0 && remaining - width - (elements - bar - 1) >= elements - bar - 1) {
14360
+ count -= combinations(remaining - width - (elements - bar), elements - bar - 2);
14361
+ }
14362
+
14363
+ if (elements - bar - 1 > 1) {
14364
+ let tooWide = 0;
14365
+ for (let last = remaining - width - (elements - bar - 2); last > maximumWidth; last--) {
14366
+ tooWide += combinations(remaining - width - last - 1, elements - bar - 3);
14367
+ }
14368
+ count -= tooWide * (elements - 1 - bar);
14369
+ } else if (remaining - width > maximumWidth) {
14370
+ count--;
14371
+ }
14372
+
14373
+ if (rank < count) {
14374
+ widths[bar] = width;
14375
+ remaining -= width;
14376
+ break;
14377
+ }
14378
+ rank -= count;
14379
+ narrowMask &= ~(1 << bar);
14380
+ }
14381
+ }
14382
+ widths[elements - 1] = remaining;
14383
+ if (rank !== 0 || widths.some((width) => width < 1 || width > maximumWidth)) {
14384
+ throw new RangeError('GS1 DataBar width rank exceeds its character group');
14385
+ }
14386
+ return widths;
14387
+ }
14388
+
14389
+ /** Convert one DataBar-14 character value into its eight alternating widths. */
14390
+ function dataBar14CharacterWidths(value, kind) {
14391
+ const group = dataBar14GroupFor(value, kind);
14392
+ const offset = value - group.gsum;
14393
+ const outside = kind === 'outside';
14394
+ const oddRank = outside ? Math.floor(offset / group.evenTotal) : offset % group.oddTotal;
14395
+ const evenRank = outside ? offset % group.evenTotal : Math.floor(offset / group.oddTotal);
14396
+ const odd = dataBarWidths(oddRank, group.oddModules, 4, group.oddWidest, !outside);
14397
+ const even = dataBarWidths(evenRank, group.evenModules, 4, group.evenWidest, outside);
14398
+ const result = [];
14399
+ for (let i = 0; i < 4; i++) result.push(odd[i], even[i]);
14400
+ return result;
14401
+ }
14402
+
14403
+ const inverseCharacterMaps = new Map();
14404
+
14405
+ /** Recover a character value from its canonical eight-width representation. */
14406
+ function dataBar14ValueForWidths(widths, kind) {
14407
+ if (!Array.isArray(widths) || widths.length !== 8 || widths.some((width) => !Number.isInteger(width) || width < 1)) {
14408
+ throw new TypeError('GS1 DataBar character widths must contain eight positive integers');
14409
+ }
14410
+ if (kind !== 'outside' && kind !== 'inside') throw new RangeError(`Unknown GS1 DataBar character kind "${kind}"`);
14411
+ let inverse = inverseCharacterMaps.get(kind);
14412
+ if (!inverse) {
14413
+ inverse = new Map();
14414
+ const maximum = kind === 'outside' ? 2840 : 1596;
14415
+ for (let value = 0; value <= maximum; value++) {
14416
+ inverse.set(dataBar14CharacterWidths(value, kind).join(','), value);
14417
+ }
14418
+ inverseCharacterMaps.set(kind, inverse);
14419
+ }
14420
+ const value = inverse.get(widths.join(','));
14421
+ if (value === undefined) throw new RangeError(`Invalid GS1 DataBar ${kind} character widths`);
14422
+ return value;
14423
+ }
14424
+
14425
+ /** Nine finder patterns, expressed as normative five-element widths. */
14426
+ const DATABAR14_FINDERS = Object.freeze([
14427
+ Object.freeze([3, 8, 2, 1, 1]), Object.freeze([3, 5, 5, 1, 1]),
14428
+ Object.freeze([3, 3, 7, 1, 1]), Object.freeze([3, 1, 9, 1, 1]),
14429
+ Object.freeze([2, 7, 4, 1, 1]), Object.freeze([2, 5, 6, 1, 1]),
14430
+ Object.freeze([2, 3, 8, 1, 1]), Object.freeze([1, 5, 7, 1, 1]),
14431
+ Object.freeze([1, 3, 9, 1, 1]),
14432
+ ]);
14433
+
14434
+ /** Weight sequence generated as powers of three modulo 79. */
14435
+ const DATABAR14_CHECKSUM_WEIGHTS = Object.freeze(Array.from({ length: 32 }, (_, index) => {
14436
+ let value = 1;
14437
+ for (let i = 0; i < index; i++) value = (value * 3) % 79;
14438
+ return value;
14439
+ }));
14440
+
14441
+ __exports.dataBarWidths = dataBarWidths;
14442
+ __exports.dataBar14CharacterWidths = dataBar14CharacterWidths;
14443
+ __exports.dataBar14ValueForWidths = dataBar14ValueForWidths;
14444
+ __exports.DATABAR14_FINDERS = DATABAR14_FINDERS;
14445
+ __exports.DATABAR14_CHECKSUM_WEIGHTS = DATABAR14_CHECKSUM_WEIGHTS;
14446
+ };
14447
+
14448
+ __modules["databar/encoder.js"] = function (__require, __exports) {
14449
+ /** GS1 DataBar Omnidirectional and Truncated encoder. @module databar/encoder */
14450
+ const { BitMatrix } = __require("core/bit-matrix.js");
14451
+ const { EncodeError } = __require("core/errors.js");
14452
+ const { encodeDataBar14GTIN } = __require("databar/codec.js");
14453
+ const { DATABAR14_CHECKSUM_WEIGHTS, DATABAR14_FINDERS, dataBar14CharacterWidths } = __require("databar/patterns.js");
14454
+
14455
+ function finderIndexes(characters) {
14456
+ const widths = characters.map((value, index) =>
14457
+ dataBar14CharacterWidths(value, index === 0 || index === 3 ? 'outside' : 'inside')
14458
+ );
14459
+ let checksum = 0;
14460
+ const weightOffsets = [0, 8, 24, 16];
14461
+ for (let character = 0; character < 4; character++) {
14462
+ for (let element = 0; element < 8; element++) {
14463
+ checksum += widths[character][element] * DATABAR14_CHECKSUM_WEIGHTS[weightOffsets[character] + element];
14464
+ }
14465
+ }
14466
+ checksum %= 79;
14467
+ if (checksum >= 8) checksum++;
14468
+ if (checksum >= 72) checksum++;
14469
+ return { widths, checksum, left: Math.floor(checksum / 9), right: checksum % 9 };
14470
+ }
14471
+
14472
+ function widthsToMatrix(widths, height) {
14473
+ const width = widths.reduce((sum, value) => sum + value, 0);
14474
+ const matrix = new BitMatrix(width, height);
14475
+ let dark = false;
14476
+ let x = 0;
14477
+ for (const run of widths) {
14478
+ if (dark) matrix.setRegion(x, 0, run, height);
14479
+ x += run;
14480
+ dark = !dark;
14481
+ }
14482
+ return matrix;
14483
+ }
14484
+
14485
+ /** Encode a checked GTIN as DataBar Omnidirectional or Truncated. */
14486
+ function encodeDataBar14(value, options = {}) {
14487
+ const variant = options.variant ?? 'omnidirectional';
14488
+ if (variant !== 'omnidirectional' && variant !== 'truncated') {
14489
+ throw new EncodeError('GS1 DataBar-14 physical encoder currently supports omnidirectional and truncated');
14490
+ }
14491
+ const height = options.height ?? (variant === 'omnidirectional' ? 33 : 13);
14492
+ if (!Number.isInteger(height) || height < (variant === 'omnidirectional' ? 33 : 13)) {
14493
+ throw new EncodeError(`GS1 DataBar ${variant} height is below its normative minimum`);
14494
+ }
14495
+ const compacted = encodeDataBar14GTIN(value, { linkage: options.linkage });
14496
+ const characters = compacted.physicalCharacters;
14497
+ const check = finderIndexes(characters);
14498
+ const widths = [1, 1];
14499
+ widths.push(...check.widths[0]);
14500
+ widths.push(...DATABAR14_FINDERS[check.left]);
14501
+ widths.push(...check.widths[1].slice().reverse());
14502
+ widths.push(...check.widths[2]);
14503
+ widths.push(...DATABAR14_FINDERS[check.right].slice().reverse());
14504
+ widths.push(...check.widths[3].slice().reverse());
14505
+ widths.push(1, 1);
14506
+ const matrix = widthsToMatrix(widths, height);
14507
+ matrix.databar = Object.freeze({ variant, gtin: compacted.gtin, linkage: compacted.linkage, checksum: check.checksum });
14508
+ return matrix;
14509
+ }
14510
+
14511
+ __exports.encodeDataBar14 = encodeDataBar14;
14512
+ };
14513
+
14514
+ __modules["databar/decoder.js"] = function (__require, __exports) {
14515
+ /** Clean-matrix decoder for GS1 DataBar Omnidirectional and Truncated. @module databar/decoder */
14516
+ const { ChecksumError, FormatError } = __require("core/errors.js");
14517
+ const { decodeDataBar14GTIN } = __require("databar/codec.js");
14518
+ const { DATABAR14_CHECKSUM_WEIGHTS, DATABAR14_FINDERS, dataBar14ValueForWidths } = __require("databar/patterns.js");
14519
+
14520
+ function sampledRuns(matrix) {
14521
+ if (!matrix || !Number.isInteger(matrix.width) || !Number.isInteger(matrix.height)) {
14522
+ throw new TypeError('GS1 DataBar decoder expects a BitMatrix-like value');
14523
+ }
14524
+ if (matrix.width % 96 !== 0) throw new FormatError('GS1 DataBar-14 matrix width must be an integer multiple of 96 modules');
14525
+ const scale = matrix.width / 96;
14526
+ const y = Math.floor(matrix.height / 2);
14527
+ const bits = Array.from({ length: 96 }, (_, x) => matrix.get(x * scale + Math.floor(scale / 2), y));
14528
+ if (bits[0] || !bits[95]) throw new FormatError('GS1 DataBar-14 guard pattern is invalid');
14529
+ const runs = [];
14530
+ let current = bits[0];
14531
+ let length = 0;
14532
+ for (const bit of bits) {
14533
+ if (bit === current) length++;
14534
+ else {
14535
+ runs.push(length);
14536
+ current = bit;
14537
+ length = 1;
14538
+ }
14539
+ }
14540
+ runs.push(length);
14541
+ if (runs.length !== 46 || runs[0] !== 1 || runs[1] !== 1 || runs[44] !== 1 || runs[45] !== 1) {
14542
+ throw new FormatError('GS1 DataBar-14 element count or guard widths are invalid');
14543
+ }
14544
+ return runs;
14545
+ }
14546
+
14547
+ function finderIndex(widths) {
14548
+ const key = widths.join(',');
14549
+ return DATABAR14_FINDERS.findIndex((candidate) => candidate.join(',') === key);
14550
+ }
14551
+
14552
+ function expectedChecksum(widths) {
14553
+ const offsets = [0, 8, 24, 16];
14554
+ let checksum = 0;
14555
+ for (let character = 0; character < 4; character++) {
14556
+ for (let element = 0; element < 8; element++) {
14557
+ checksum += widths[character][element] * DATABAR14_CHECKSUM_WEIGHTS[offsets[character] + element];
14558
+ }
14559
+ }
14560
+ checksum %= 79;
14561
+ if (checksum >= 8) checksum++;
14562
+ if (checksum >= 72) checksum++;
14563
+ return checksum;
14564
+ }
14565
+
14566
+ /** Decode a clean or integer-scaled 96-module DataBar-14 matrix. */
14567
+ function decodeDataBar14(matrix) {
14568
+ const runs = sampledRuns(matrix);
14569
+ const widths = [
14570
+ runs.slice(2, 10),
14571
+ runs.slice(15, 23).slice().reverse(),
14572
+ runs.slice(23, 31),
14573
+ runs.slice(36, 44).slice().reverse(),
14574
+ ];
14575
+ const leftFinder = finderIndex(runs.slice(10, 15));
14576
+ const rightFinder = finderIndex(runs.slice(31, 36).slice().reverse());
14577
+ if (leftFinder < 0 || rightFinder < 0) throw new FormatError('GS1 DataBar-14 finder pattern is invalid');
14578
+ const encodedChecksum = leftFinder * 9 + rightFinder;
14579
+ if (encodedChecksum !== expectedChecksum(widths)) throw new ChecksumError('GS1 DataBar-14 checksum mismatch');
14580
+
14581
+ const outerLeft = dataBar14ValueForWidths(widths[0], 'outside');
14582
+ const innerLeft = dataBar14ValueForWidths(widths[1], 'inside');
14583
+ const innerRight = dataBar14ValueForWidths(widths[2], 'inside');
14584
+ const outerRight = dataBar14ValueForWidths(widths[3], 'outside');
14585
+ const decoded = decodeDataBar14GTIN({ outerLeft, innerLeft, outerRight, innerRight });
14586
+ return Object.freeze({
14587
+ format: 'databar-omnidirectional',
14588
+ text: decoded.gtin,
14589
+ gtin: decoded.gtin,
14590
+ linkage: decoded.linkage,
14591
+ symbologyIdentifier: ']e0',
14592
+ });
14593
+ }
14594
+
14595
+ __exports.decodeDataBar14 = decodeDataBar14;
14596
+ };
14597
+
14598
+ __modules["databar/index.js"] = function (__require, __exports) {
14599
+ /** Verified GS1 DataBar data-layer primitives. @module databar */
14600
+ const __reexport0 = __require("databar/codec.js"); __exports.dataBarGtinTransmission = __reexport0.dataBarGtinTransmission; __exports.decodeDataBar14GTIN = __reexport0.decodeDataBar14GTIN; __exports.decodeDataBarLimitedGTIN = __reexport0.decodeDataBarLimitedGTIN; __exports.encodeDataBar14GTIN = __reexport0.encodeDataBar14GTIN; __exports.encodeDataBarLimitedGTIN = __reexport0.encodeDataBarLimitedGTIN; __exports.gtinCheckDigit = __reexport0.gtinCheckDigit; __exports.makeGTIN14 = __reexport0.makeGTIN14; __exports.normalizeGTIN = __reexport0.normalizeGTIN;
14601
+ const __reexport1 = __require("databar/gs1.js"); __exports.GS1_SEPARATOR = __reexport1.GS1_SEPARATOR; __exports.decodeGS1ElementString = __reexport1.decodeGS1ElementString; __exports.encodeGS1ElementString = __reexport1.encodeGS1ElementString; __exports.formatGS1Elements = __reexport1.formatGS1Elements; __exports.gs1AIInfo = __reexport1.gs1AIInfo; __exports.parseGS1ElementString = __reexport1.parseGS1ElementString;
14602
+ const __reexport2 = __require("databar/tables.js"); __exports.DATABAR14_VARIANTS = __reexport2.DATABAR14_VARIANTS; __exports.DATABAR_LIMITED_VARIANT = __reexport2.DATABAR_LIMITED_VARIANT; __exports.dataBar14GroupFor = __reexport2.dataBar14GroupFor; __exports.validateDataBarTables = __reexport2.validateDataBarTables;
14603
+ const __reexport3 = __require("databar/encoder.js"); __exports.encodeDataBar14 = __reexport3.encodeDataBar14;
14604
+ const __reexport4 = __require("databar/decoder.js"); __exports.decodeDataBar14 = __reexport4.decodeDataBar14;
14605
+ const __reexport5 = __require("databar/patterns.js"); __exports.DATABAR14_CHECKSUM_WEIGHTS = __reexport5.DATABAR14_CHECKSUM_WEIGHTS; __exports.DATABAR14_FINDERS = __reexport5.DATABAR14_FINDERS; __exports.dataBar14CharacterWidths = __reexport5.dataBar14CharacterWidths; __exports.dataBar14ValueForWidths = __reexport5.dataBar14ValueForWidths; __exports.dataBarWidths = __reexport5.dataBarWidths;
14606
+
14607
+
14608
+ };
14609
+
14610
+ __modules["render/options.js"] = function (__require, __exports) {
14611
+ /**
14612
+ * Shared render options, normalised once so every backend agrees.
14613
+ *
14614
+ * @module render/options
14615
+ */
14616
+ const { BitMatrix } = __require("core/bit-matrix.js");
14617
+
14618
+ /**
14619
+ * @typedef {object} RenderOptions
14620
+ * @property {number} [scale] Pixels per module. Default 8.
14621
+ * @property {number} [margin] Quiet-zone modules on every side. Default 4.
14622
+ * @property {string} [dark] Colour of set modules. Default '#000000'.
14623
+ * @property {string} [light] Colour of clear modules, or 'none' for transparent.
14624
+ * @property {number} [barHeight] For 1D symbols: total bar height in pixels.
14625
+ */
14626
+
14627
+ /**
14628
+ * Expand and pad the matrix, and resolve every dimension.
14629
+ *
14630
+ * Linear symbols arrive one module tall. They are stretched to `barHeight`
14631
+ * *before* the quiet zone is applied, so the margin ends up uniform on all
14632
+ * four sides — padding first would leave a quiet zone one module tall against
14633
+ * bars a hundred pixels tall, which no scanner would accept.
14634
+ *
14635
+ * @param {BitMatrix} matrix
14636
+ * @param {RenderOptions} options
14637
+ */
14638
+ function normalizeOptions(matrix, options = {}) {
14639
+ const scale = Math.max(1, Math.floor(options.scale ?? 8));
14640
+ const margin = Math.max(0, Math.floor(options.margin ?? 4));
14641
+ const dark = options.dark ?? '#000000';
14642
+ const light = options.light ?? '#ffffff';
14643
+ const barHeight = options.barHeight ?? null;
14644
+
14645
+ let base = matrix;
14646
+ const is1D = matrix.height === 1;
14647
+
14648
+ if (is1D) {
14649
+ // Default to a bar height that stays scannable: tall enough that a laser
14650
+ // crossing at a slight angle still passes through the whole symbol.
14651
+ const targetPixels = barHeight ?? Math.max(40, Math.round(matrix.width * scale * 0.15));
14652
+ const rows = Math.max(1, Math.round(targetPixels / scale));
14653
+ base = new BitMatrix(matrix.width, rows);
14654
+ for (let x = 0; x < matrix.width; x++) {
14655
+ if (!matrix.get(x, 0)) continue;
14656
+ for (let y = 0; y < rows; y++) base.set(x, y);
14657
+ }
14658
+ }
14659
+
14660
+ const source = margin > 0 ? base.withMargin(margin) : base;
14661
+
14662
+ return {
14663
+ scale,
14664
+ margin,
14665
+ dark,
14666
+ light,
14667
+ is1D,
14668
+ source,
14669
+ rowHeight: scale,
14670
+ pixelWidth: source.width * scale,
14671
+ pixelHeight: source.height * scale,
14672
+ };
14673
+ }
14674
+
14675
+ /**
14676
+ * Parse a CSS colour into RGBA bytes.
14677
+ *
14678
+ * Supports the forms a barcode actually needs: #rgb, #rgba, #rrggbb,
14679
+ * #rrggbbaa, rgb(), rgba(), plus 'none' and 'transparent'.
14680
+ *
14681
+ * @param {string} colour
14682
+ * @returns {[number, number, number, number]}
14683
+ */
14684
+ function parseColor(colour) {
14685
+ const value = String(colour).trim().toLowerCase();
14686
+
14687
+ if (value === 'none' || value === 'transparent') return [0, 0, 0, 0];
14688
+ if (value === 'white') return [255, 255, 255, 255];
14689
+ if (value === 'black') return [0, 0, 0, 255];
14690
+
14691
+ if (value[0] === '#') {
14692
+ const hex = value.slice(1);
14693
+ const expand = (c) => parseInt(c + c, 16);
14694
+ if (hex.length === 3) {
14695
+ return [expand(hex[0]), expand(hex[1]), expand(hex[2]), 255];
14696
+ }
14697
+ if (hex.length === 4) {
14698
+ return [expand(hex[0]), expand(hex[1]), expand(hex[2]), expand(hex[3])];
14699
+ }
14700
+ if (hex.length === 6) {
14701
+ return [
14702
+ parseInt(hex.slice(0, 2), 16),
14703
+ parseInt(hex.slice(2, 4), 16),
14704
+ parseInt(hex.slice(4, 6), 16),
14705
+ 255,
14706
+ ];
14707
+ }
14708
+ if (hex.length === 8) {
14709
+ return [
14710
+ parseInt(hex.slice(0, 2), 16),
14711
+ parseInt(hex.slice(2, 4), 16),
14712
+ parseInt(hex.slice(4, 6), 16),
14713
+ parseInt(hex.slice(6, 8), 16),
14714
+ ];
14715
+ }
14716
+ }
14717
+
14718
+ const fn = value.match(/^rgba?\(([^)]+)\)$/);
14719
+ if (fn) {
14720
+ const parts = fn[1].split(/[,/\s]+/).filter(Boolean);
14721
+ const channel = (s) => (s.endsWith('%')
12644
14722
  ? Math.round((parseFloat(s) / 100) * 255)
12645
14723
  : Math.round(parseFloat(s)));
12646
14724
  const r = channel(parts[0]);
@@ -13790,6 +15868,9 @@ const micropdf417 = __require("micropdf417/index.js");
13790
15868
  const microqr = __require("microqr/index.js");
13791
15869
  const rmqr = __require("rmqr/index.js");
13792
15870
  const frameqr = __require("frameqr/index.js");
15871
+ const aztecRune = __require("aztecrune/index.js");
15872
+ const compactPdf417 = __require("compactpdf417/index.js");
15873
+ const databar = __require("databar/index.js");
13793
15874
  __exports.BitMatrix = BitMatrix;
13794
15875
  const __reexport0 = __require("core/errors.js"); __exports.BarcodeError = __reexport0.BarcodeError; __exports.EncodeError = __reexport0.EncodeError; __exports.NotFoundError = __reexport0.NotFoundError; __exports.FormatError = __reexport0.FormatError; __exports.ChecksumError = __reexport0.ChecksumError;
13795
15876
  const __reexport1 = __require("image/luminance.js"); __exports.LuminanceSource = __reexport1.LuminanceSource;
@@ -13803,7 +15884,12 @@ const __reexport7 = __require("render/index.js"); __exports.renderToCanvasAutoAs
13803
15884
  const __reexport8 = __require("qr/index.js"); __exports.encodeQR = __reexport8.encodeQR; __exports.decodeQR = __reexport8.decodeQR; __exports.detectQR = __reexport8.detectQR; __exports.detectAndDecodeQR = __reexport8.detectAndDecodeQR;
13804
15885
  const __reexport9 = __require("datamatrix/index.js"); __exports.encodeDataMatrix = __reexport9.encodeDataMatrix; __exports.decodeDataMatrix = __reexport9.decodeDataMatrix; __exports.detectDataMatrix = __reexport9.detectDataMatrix; __exports.detectAndDecodeDataMatrix = __reexport9.detectAndDecodeDataMatrix;
13805
15886
  const __reexport10 = __require("aztec/index.js"); __exports.encodeAztec = __reexport10.encodeAztec; __exports.decodeAztec = __reexport10.decodeAztec; __exports.detectAztec = __reexport10.detectAztec; __exports.detectAndDecodeAztec = __reexport10.detectAndDecodeAztec;
15887
+ Object.assign(__exports, __require("aztecrune/index.js"));
13806
15888
  const __reexport11 = __require("pdf417/index.js"); __exports.encodePDF417 = __reexport11.encodePDF417; __exports.decodePDF417 = __reexport11.decodePDF417; __exports.detectPDF417 = __reexport11.detectPDF417; __exports.detectAndDecodePDF417 = __reexport11.detectAndDecodePDF417;
15889
+ Object.assign(__exports, __require("compactpdf417/index.js"));
15890
+ // DataBar currently exposes verified GS1 data-layer codecs only; physical
15891
+ // symbol rendering and image detection remain deliberately out of scope.
15892
+ Object.assign(__exports, __require("databar/index.js"));
13807
15893
  const __reexport12 = __require("micropdf417/index.js"); __exports.encodeMicroPDF417 = __reexport12.encodeMicroPDF417; __exports.decodeMicroPDF417 = __reexport12.decodeMicroPDF417; __exports.detectMicroPDF417 = __reexport12.detectMicroPDF417; __exports.detectAndDecodeMicroPDF417 = __reexport12.detectAndDecodeMicroPDF417;
13808
15894
  const __reexport13 = __require("microqr/index.js"); __exports.encodeMicroQR = __reexport13.encodeMicroQR; __exports.decodeMicroQR = __reexport13.decodeMicroQR; __exports.detectMicroQR = __reexport13.detectMicroQR; __exports.detectAndDecodeMicroQR = __reexport13.detectAndDecodeMicroQR;
13809
15895
  const __reexport14 = __require("rmqr/index.js"); __exports.encodeRMQR = __reexport14.encodeRMQR; __exports.decodeRMQR = __reexport14.decodeRMQR; __exports.detectRMQR = __reexport14.detectRMQR; __exports.detectAndDecodeRMQR = __reexport14.detectAndDecodeRMQR;
@@ -13849,6 +15935,11 @@ const rmqrCanEncode = typeof rmqr.encodeRMQR === 'function';
13849
15935
  const rmqrCanDecode = typeof rmqr.detectAndDecodeRMQR === 'function';
13850
15936
  const frameQrCanEncode = typeof frameqr.encodeFrameQR === 'function';
13851
15937
  const frameQrCanDecode = typeof frameqr.detectAndDecodeFrameQR === 'function';
15938
+ const aztecRuneCanEncode = typeof aztecRune.encodeAztecRune === 'function';
15939
+ const aztecRuneCanDecode = typeof aztecRune.detectAndDecodeAztecRune === 'function';
15940
+ const compactPdf417CanEncode = typeof compactPdf417.encodeCompactPDF417 === 'function';
15941
+ const compactPdf417CanDecode = typeof compactPdf417.detectAndDecodeCompactPDF417 === 'function';
15942
+ const dataBarCanEncode = typeof databar.encodeDataBar14 === 'function';
13852
15943
 
13853
15944
  /**
13854
15945
  * Every format this build supports.
@@ -13890,6 +15981,13 @@ function listFormats() {
13890
15981
  canRead: aztecCanDecode,
13891
15982
  kind: /** @type {'2D'} */ ('2D'),
13892
15983
  });
15984
+ formats.push({
15985
+ id: 'aztecrune',
15986
+ label: 'Aztec Rune',
15987
+ canWrite: aztecRuneCanEncode,
15988
+ canRead: aztecRuneCanDecode,
15989
+ kind: /** @type {'2D'} */ ('2D'),
15990
+ });
13893
15991
  formats.push({
13894
15992
  id: 'pdf417',
13895
15993
  label: 'PDF417',
@@ -13897,6 +15995,13 @@ function listFormats() {
13897
15995
  canRead: pdf417CanDecode,
13898
15996
  kind: /** @type {'2D'} */ ('2D'),
13899
15997
  });
15998
+ formats.push({
15999
+ id: 'compactpdf417',
16000
+ label: 'Compact PDF417',
16001
+ canWrite: compactPdf417CanEncode,
16002
+ canRead: compactPdf417CanDecode,
16003
+ kind: /** @type {'2D'} */ ('2D'),
16004
+ });
13900
16005
  formats.push({
13901
16006
  id: 'micropdf417',
13902
16007
  label: 'MicroPDF417',
@@ -13925,6 +16030,13 @@ function listFormats() {
13925
16030
  canRead: frameQrCanDecode,
13926
16031
  kind: /** @type {'2D'} */ ('2D'),
13927
16032
  });
16033
+ formats.push({
16034
+ id: 'gs1databar14',
16035
+ label: 'GS1 DataBar Omnidirectional / Truncated',
16036
+ canWrite: dataBarCanEncode,
16037
+ canRead: false,
16038
+ kind: /** @type {'1D'} */ ('1D'),
16039
+ });
13928
16040
 
13929
16041
  return formats;
13930
16042
  }
@@ -13978,9 +16090,15 @@ function encode(text, options = {}) {
13978
16090
  if (format === 'aztec' || format === 'aztec-code') {
13979
16091
  return aztec.encodeAztec(value, options);
13980
16092
  }
16093
+ if (format === 'aztecrune' || format === 'aztec-rune' || format === 'rune') {
16094
+ return aztecRune.encodeAztecRune(value, options);
16095
+ }
13981
16096
  if (format === 'pdf417' || format === 'pdf-417') {
13982
16097
  return pdf417.encodePDF417(value, options);
13983
16098
  }
16099
+ if (format === 'compactpdf417' || format === 'compact-pdf417' || format === 'compact-pdf-417') {
16100
+ return compactPdf417.encodeCompactPDF417(value, options);
16101
+ }
13984
16102
  if (format === 'micropdf417' || format === 'micro-pdf417' || format === 'micro-pdf-417') {
13985
16103
  return micropdf417.encodeMicroPDF417(value, options);
13986
16104
  }
@@ -13993,10 +16111,13 @@ function encode(text, options = {}) {
13993
16111
  if (format === 'frameqr' || format === 'frame-qr' || format === 'canvas-qr') {
13994
16112
  return frameqr.encodeFrameQR(value, options);
13995
16113
  }
16114
+ if (format === 'gs1databar14' || format === 'gs1-databar14' || format === 'databar') {
16115
+ return databar.encodeDataBar14(value, options);
16116
+ }
13996
16117
 
13997
16118
  const entry = ONED_FORMATS[format];
13998
16119
  if (!entry) {
13999
- const known = [...Object.keys(ONED_FORMATS), 'qr', 'datamatrix', 'aztec', 'pdf417', 'micropdf417', 'microqr', 'rmqr', 'frameqr'].join(', ');
16120
+ const known = [...Object.keys(ONED_FORMATS), 'qr', 'datamatrix', 'aztec', 'aztecrune', 'pdf417', 'compactpdf417', 'micropdf417', 'microqr', 'rmqr', 'frameqr', 'gs1databar14'].join(', ');
14000
16121
  throw new EncodeError(`Unknown format "${format}". Known formats: ${known}`);
14001
16122
  }
14002
16123
  return entry.encode(value, options);
@@ -14046,7 +16167,9 @@ function decode(image, options = {}) {
14046
16167
  const wantQR = !want || want.has('qr') || want.has('qrcode');
14047
16168
  const wantDataMatrix = !want || want.has('datamatrix') || want.has('data-matrix');
14048
16169
  const wantAztec = !want || want.has('aztec') || want.has('aztec-code');
16170
+ const wantAztecRune = !want || want.has('aztecrune') || want.has('aztec-rune') || want.has('rune');
14049
16171
  const wantPDF417 = !want || want.has('pdf417') || want.has('pdf-417');
16172
+ const wantCompactPDF417 = !want || want.has('compactpdf417') || want.has('compact-pdf417') || want.has('compact-pdf-417');
14050
16173
  const wantMicroPDF417 = !want || want.has('micropdf417') || want.has('micro-pdf417') || want.has('micro-pdf-417');
14051
16174
  const wantMicroQR = !want || want.has('microqr') || want.has('micro-qr');
14052
16175
  const wantRMQR = !want || want.has('rmqr') || want.has('r-mqr') || want.has('rectangular-micro-qr');
@@ -14103,6 +16226,15 @@ function decode(image, options = {}) {
14103
16226
  }
14104
16227
  }
14105
16228
 
16229
+ if (wantAztecRune && aztecRuneCanDecode) {
16230
+ try {
16231
+ const found = aztecRune.detectAndDecodeAztecRune(bits);
16232
+ if (found) results.push({ ...found, format: 'aztecrune' });
16233
+ } catch {
16234
+ /* no Aztec Rune in this pass */
16235
+ }
16236
+ }
16237
+
14106
16238
  if (wantPDF417 && pdf417CanDecode) {
14107
16239
  try {
14108
16240
  const found = pdf417.detectAndDecodePDF417(bits);
@@ -14112,6 +16244,15 @@ function decode(image, options = {}) {
14112
16244
  }
14113
16245
  }
14114
16246
 
16247
+ if (wantCompactPDF417 && compactPdf417CanDecode) {
16248
+ try {
16249
+ const found = compactPdf417.detectAndDecodeCompactPDF417(bits);
16250
+ if (found) results.push({ ...found, format: 'compactpdf417' });
16251
+ } catch {
16252
+ /* no Compact PDF417 in this pass */
16253
+ }
16254
+ }
16255
+
14115
16256
  if (wantMicroPDF417 && microPdf417CanDecode) {
14116
16257
  // MicroPDF417 detection measures runs across the whole raster. Hybrid
14117
16258
  // thresholding can alter uniform modules near local-window boundaries,
@@ -14190,7 +16331,7 @@ function decodeStrict(image, options) {
14190
16331
  }
14191
16332
 
14192
16333
  /** Library version, matching package.json. */
14193
- const VERSION = '1.3.1';
16334
+ const VERSION = '1.4.1';
14194
16335
 
14195
16336
  __exports.listFormats = listFormats;
14196
16337
  __exports.encode = encode;
@@ -14202,22 +16343,69 @@ __exports.VERSION = VERSION;
14202
16343
  const __entry = __require("index.js");
14203
16344
  export default __entry;
14204
16345
  export const {
16346
+ AZTEC_RUNE_DATA_BITS,
16347
+ AZTEC_RUNE_DATA_CODEWORDS,
16348
+ AZTEC_RUNE_DATA_POSITIONS,
16349
+ AZTEC_RUNE_ECC_CODEWORDS,
16350
+ AZTEC_RUNE_MASK,
16351
+ AZTEC_RUNE_SIZE,
16352
+ AZTEC_RUNE_TOTAL_CODEWORDS,
16353
+ AZTEC_RUNE_WORD_SIZE,
14205
16354
  BarcodeError,
14206
16355
  BitMatrix,
16356
+ COMPACT_PDF417_LIMITS,
16357
+ COMPACT_PDF417_START,
16358
+ COMPACT_PDF417_START_BITS,
16359
+ COMPACT_PDF417_STOP_MODULES,
14207
16360
  ChecksumError,
16361
+ DATABAR14_CHECKSUM_WEIGHTS,
16362
+ DATABAR14_FINDERS,
16363
+ DATABAR14_VARIANTS,
16364
+ DATABAR_LIMITED_VARIANT,
16365
+ EAN2_PARITY,
16366
+ EAN2_WIDTH,
16367
+ EAN5_PARITY,
16368
+ EAN5_WIDTH,
16369
+ EAN_ADDON_SEPARATOR,
16370
+ EAN_ADDON_START,
14208
16371
  EncodeError,
14209
16372
  FormatError,
16373
+ GS1_SEPARATOR,
14210
16374
  LuminanceSource,
14211
16375
  NotFoundError,
14212
16376
  ONED_FORMATS,
14213
16377
  VERSION,
16378
+ aztecRuneField,
16379
+ aztecRuneStructuralValue,
14214
16380
  binarize,
14215
16381
  binarizeGlobal,
14216
16382
  binarizeHybrid,
16383
+ buildAztecRuneStructure,
16384
+ compactPdf417Dimensions,
16385
+ compactPdf417Geometry,
16386
+ compactPdf417Indicators,
16387
+ compactPdf417MatchingLevels,
16388
+ compactPdf417Width,
16389
+ composeEANAddon,
16390
+ dataBar14CharacterWidths,
16391
+ dataBar14GroupFor,
16392
+ dataBar14ValueForWidths,
16393
+ dataBarGtinTransmission,
16394
+ dataBarWidths,
14217
16395
  decode,
14218
16396
  decodeAztec,
16397
+ decodeAztecRune,
16398
+ decodeCompactPDF417,
16399
+ decodeDataBar14,
16400
+ decodeDataBar14GTIN,
16401
+ decodeDataBarLimitedGTIN,
14219
16402
  decodeDataMatrix,
16403
+ decodeEAN2,
16404
+ decodeEAN5,
16405
+ decodeEANAddOn,
16406
+ decodeEANAddon,
14220
16407
  decodeFrameQR,
16408
+ decodeGS1ElementString,
14221
16409
  decodeMicroPDF417,
14222
16410
  decodeMicroQR,
14223
16411
  decodeOneD,
@@ -14227,6 +16415,8 @@ export const {
14227
16415
  decodeRMQR,
14228
16416
  decodeStrict,
14229
16417
  detectAndDecodeAztec,
16418
+ detectAndDecodeAztecRune,
16419
+ detectAndDecodeCompactPDF417,
14230
16420
  detectAndDecodeDataMatrix,
14231
16421
  detectAndDecodeFrameQR,
14232
16422
  detectAndDecodeMicroPDF417,
@@ -14235,6 +16425,8 @@ export const {
14235
16425
  detectAndDecodeQR,
14236
16426
  detectAndDecodeRMQR,
14237
16427
  detectAztec,
16428
+ detectAztecRune,
16429
+ detectCompactPDF417,
14238
16430
  detectDataMatrix,
14239
16431
  detectFrameQR,
14240
16432
  detectMicroPDF417,
@@ -14243,17 +16435,33 @@ export const {
14243
16435
  detectQR,
14244
16436
  detectRMQR,
14245
16437
  ean13CheckDigit,
16438
+ ean2Parity,
16439
+ ean5CheckDigit,
16440
+ ean5Checksum,
16441
+ ean5Parity,
14246
16442
  encode,
14247
16443
  encodeAztec,
16444
+ encodeAztecRune,
14248
16445
  encodeCodabar,
14249
16446
  encodeCode11,
14250
16447
  encodeCode128,
14251
16448
  encodeCode39,
14252
16449
  encodeCode93,
16450
+ encodeCompactPDF417,
16451
+ encodeDataBar14,
16452
+ encodeDataBar14GTIN,
16453
+ encodeDataBarLimitedGTIN,
14253
16454
  encodeDataMatrix,
14254
16455
  encodeEAN13,
16456
+ encodeEAN13WithAddon,
16457
+ encodeEAN2,
16458
+ encodeEAN5,
14255
16459
  encodeEAN8,
16460
+ encodeEAN8WithAddon,
16461
+ encodeEANAddOn,
16462
+ encodeEANAddon,
14256
16463
  encodeFrameQR,
16464
+ encodeGS1ElementString,
14257
16465
  encodeISBN,
14258
16466
  encodeITF,
14259
16467
  encodeITF14,
@@ -14265,10 +16473,19 @@ export const {
14265
16473
  encodeQR,
14266
16474
  encodeRMQR,
14267
16475
  encodeUPCA,
16476
+ encodeUPCAWithAddon,
14268
16477
  encodeUPCE,
16478
+ encodeUPCEWithAddon,
16479
+ formatGS1Elements,
16480
+ gs1AIInfo,
16481
+ gtinCheckDigit,
14269
16482
  isWebGL2Available,
14270
16483
  isWebGPUAvailable,
14271
16484
  listFormats,
16485
+ makeGTIN14,
16486
+ normalizeAztecRuneValue,
16487
+ normalizeGTIN,
16488
+ parseGS1ElementString,
14272
16489
  patternVariance,
14273
16490
  recordPattern,
14274
16491
  renderToCanvasAuto,
@@ -14280,5 +16497,9 @@ export const {
14280
16497
  toPNGDataURI,
14281
16498
  toSVG,
14282
16499
  toSVGDataURI,
16500
+ validateAztecRuneTables,
16501
+ validateCompactPdf417Options,
16502
+ validateCompactPdf417Tables,
16503
+ validateDataBarTables,
14283
16504
  validateTables
14284
16505
  } = __entry;