@sythos/js_barcode_universal 1.5.8 → 1.5.9

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 (179) hide show
  1. package/LICENSE +5 -4
  2. package/NOTICE.md +2 -2
  3. package/README.md +17 -13
  4. package/bundle/sythos-barcode.esm.js +11658 -11244
  5. package/bundle/sythos-barcode.js +11658 -11244
  6. package/package.json +10 -3
  7. package/src/index.d.ts +1 -1
  8. package/src/index.js +508 -516
  9. package/src/js/aztec/decoder.js +208 -199
  10. package/src/js/aztec/detector.js +153 -126
  11. package/src/js/aztec/encoder.js +172 -153
  12. package/src/js/aztec/high-level.js +106 -101
  13. package/src/js/aztec/index.js +1 -12
  14. package/src/js/aztec/tables.js +106 -120
  15. package/src/js/aztecrune/decoder.js +76 -85
  16. package/src/js/aztecrune/detector.js +107 -93
  17. package/src/js/aztecrune/encoder.js +50 -68
  18. package/src/js/aztecrune/index.js +1 -16
  19. package/src/js/aztecrune/tables.js +59 -54
  20. package/src/js/compactpdf417/decoder.js +69 -74
  21. package/src/js/compactpdf417/detector.js +74 -75
  22. package/src/js/compactpdf417/encoder.js +68 -81
  23. package/src/js/compactpdf417/index.js +1 -13
  24. package/src/js/compactpdf417/tables.js +71 -80
  25. package/src/js/core/bit-buffer.js +106 -122
  26. package/src/js/core/bit-matrix.js +196 -194
  27. package/src/js/core/errors.js +13 -15
  28. package/src/js/core/galois-field.js +119 -133
  29. package/src/js/core/index.js +2 -19
  30. package/src/js/core/reed-solomon.js +195 -204
  31. package/src/js/databar/codec.js +93 -108
  32. package/src/js/databar/decoder.js +149 -140
  33. package/src/js/databar/encoder.js +47 -55
  34. package/src/js/databar/gs1.js +122 -123
  35. package/src/js/databar/index.js +4 -36
  36. package/src/js/databar/patterns.js +81 -85
  37. package/src/js/databar/tables.js +51 -52
  38. package/src/js/datamatrix/decoder.js +216 -182
  39. package/src/js/datamatrix/detector.js +161 -132
  40. package/src/js/datamatrix/encoder.js +192 -133
  41. package/src/js/datamatrix/index.js +1 -9
  42. package/src/js/datamatrix/tables.js +68 -69
  43. package/src/js/frameqr/decoder.js +102 -125
  44. package/src/js/frameqr/detector.js +101 -94
  45. package/src/js/frameqr/encoder.js +67 -80
  46. package/src/js/frameqr/index.js +1 -10
  47. package/src/js/frameqr/tables.js +145 -163
  48. package/src/js/image/binarizer.js +146 -162
  49. package/src/js/image/grid-sampler.js +63 -79
  50. package/src/js/image/index.js +0 -2
  51. package/src/js/image/luminance.js +129 -140
  52. package/src/js/image/perspective.js +112 -149
  53. package/src/js/micropdf417/compaction.js +64 -65
  54. package/src/js/micropdf417/decoder.js +106 -109
  55. package/src/js/micropdf417/detector.js +73 -70
  56. package/src/js/micropdf417/encoder.js +129 -154
  57. package/src/js/micropdf417/error-correction.js +6 -11
  58. package/src/js/micropdf417/index.js +2 -16
  59. package/src/js/micropdf417/tables.js +112 -99
  60. package/src/js/microqr/decoder.js +177 -182
  61. package/src/js/microqr/detector.js +240 -256
  62. package/src/js/microqr/encoder.js +239 -194
  63. package/src/js/microqr/index.js +0 -2
  64. package/src/js/microqr/tables.js +208 -200
  65. package/src/js/oned/addons.js +167 -191
  66. package/src/js/oned/index.js +27 -58
  67. package/src/js/oned/patterns.js +194 -213
  68. package/src/js/oned/reader.js +1003 -984
  69. package/src/js/oned/writers.js +411 -466
  70. package/src/js/pdf417/compaction.js +315 -222
  71. package/src/js/pdf417/decoder.js +71 -36
  72. package/src/js/pdf417/detector.js +377 -361
  73. package/src/js/pdf417/encoder.js +57 -46
  74. package/src/js/pdf417/error-correction.js +5 -8
  75. package/src/js/pdf417/tables.js +248 -250
  76. package/src/js/qr/decoder.js +311 -347
  77. package/src/js/qr/detector.js +378 -395
  78. package/src/js/qr/encoder.js +514 -599
  79. package/src/js/qr/index.js +0 -2
  80. package/src/js/qr/tables.js +375 -422
  81. package/src/js/render/image-data.js +57 -62
  82. package/src/js/render/index.js +21 -23
  83. package/src/js/render/options.js +82 -90
  84. package/src/js/render/png.js +144 -169
  85. package/src/js/render/svg.js +41 -44
  86. package/src/js/render/webgl.js +103 -109
  87. package/src/js/render/webgpu.js +205 -217
  88. package/src/js/rmqr/decoder.js +161 -53
  89. package/src/js/rmqr/detector.js +73 -41
  90. package/src/js/rmqr/encoder.js +253 -104
  91. package/src/js/rmqr/index.js +1 -5
  92. package/src/js/rmqr/tables.js +108 -85
  93. package/src/ts/aztec/decoder.ts +317 -0
  94. package/src/ts/aztec/detector.ts +224 -0
  95. package/src/ts/aztec/encoder.ts +257 -0
  96. package/src/ts/aztec/high-level.ts +211 -0
  97. package/src/ts/aztec/index.ts +45 -0
  98. package/src/ts/aztec/tables.ts +210 -0
  99. package/src/ts/aztecrune/decoder.ts +155 -0
  100. package/src/ts/aztecrune/detector.ts +166 -0
  101. package/src/ts/aztecrune/encoder.ts +121 -0
  102. package/src/ts/aztecrune/index.ts +49 -0
  103. package/src/ts/aztecrune/tables.ts +137 -0
  104. package/src/ts/compactpdf417/decoder.ts +128 -0
  105. package/src/ts/compactpdf417/detector.ts +139 -0
  106. package/src/ts/compactpdf417/encoder.ts +140 -0
  107. package/src/ts/compactpdf417/index.ts +17 -0
  108. package/src/ts/compactpdf417/tables.ts +173 -0
  109. package/src/ts/core/bit-buffer.ts +174 -0
  110. package/src/ts/core/bit-matrix.ts +241 -0
  111. package/src/ts/core/errors.ts +61 -0
  112. package/src/ts/core/galois-field.ts +207 -0
  113. package/src/ts/core/index.ts +56 -0
  114. package/src/ts/core/reed-solomon.ts +327 -0
  115. package/src/ts/databar/codec.ts +181 -0
  116. package/src/ts/databar/decoder.ts +215 -0
  117. package/src/ts/databar/encoder.ts +96 -0
  118. package/src/ts/databar/gs1.ts +177 -0
  119. package/src/ts/databar/index.ts +68 -0
  120. package/src/ts/databar/patterns.ts +143 -0
  121. package/src/ts/databar/tables.ts +124 -0
  122. package/src/ts/datamatrix/decoder.ts +262 -0
  123. package/src/ts/datamatrix/detector.ts +225 -0
  124. package/src/ts/datamatrix/encoder.ts +191 -0
  125. package/src/ts/datamatrix/index.ts +42 -0
  126. package/src/ts/datamatrix/tables.ts +123 -0
  127. package/src/ts/frameqr/decoder.ts +239 -0
  128. package/src/ts/frameqr/detector.ts +192 -0
  129. package/src/ts/frameqr/encoder.ts +156 -0
  130. package/src/ts/frameqr/index.ts +42 -0
  131. package/src/ts/frameqr/tables.ts +270 -0
  132. package/src/ts/image/binarizer.ts +270 -0
  133. package/src/ts/image/grid-sampler.ts +164 -0
  134. package/src/ts/image/index.ts +40 -0
  135. package/src/ts/image/luminance.ts +196 -0
  136. package/src/ts/image/perspective.ts +195 -0
  137. package/src/ts/index.d.ts +1 -1
  138. package/src/ts/index.ts +790 -0
  139. package/src/ts/micropdf417/compaction.ts +116 -0
  140. package/src/ts/micropdf417/decoder.ts +183 -0
  141. package/src/ts/micropdf417/detector.ts +149 -0
  142. package/src/ts/micropdf417/encoder.ts +209 -0
  143. package/src/ts/micropdf417/error-correction.ts +55 -0
  144. package/src/ts/micropdf417/index.ts +49 -0
  145. package/src/ts/micropdf417/tables.ts +184 -0
  146. package/src/ts/microqr/decoder.ts +245 -0
  147. package/src/ts/microqr/detector.ts +355 -0
  148. package/src/ts/microqr/encoder.ts +269 -0
  149. package/src/ts/microqr/index.ts +36 -0
  150. package/src/ts/microqr/tables.ts +316 -0
  151. package/src/ts/oned/addons.ts +420 -0
  152. package/src/ts/oned/index.ts +106 -0
  153. package/src/ts/oned/patterns.ts +384 -0
  154. package/src/ts/oned/reader.ts +1364 -0
  155. package/src/ts/oned/writers.ts +746 -0
  156. package/src/ts/pdf417/compaction.ts +298 -0
  157. package/src/ts/pdf417/decoder.ts +75 -0
  158. package/src/ts/pdf417/detector.ts +468 -0
  159. package/src/ts/pdf417/encoder.ts +91 -0
  160. package/src/ts/pdf417/error-correction.ts +47 -0
  161. package/src/ts/pdf417/index.ts +6 -0
  162. package/src/ts/pdf417/tables.ts +317 -0
  163. package/src/ts/qr/decoder.ts +575 -0
  164. package/src/ts/qr/detector.ts +630 -0
  165. package/src/ts/qr/encoder.ts +958 -0
  166. package/src/ts/qr/index.ts +44 -0
  167. package/src/ts/qr/tables.ts +737 -0
  168. package/src/ts/render/image-data.ts +125 -0
  169. package/src/ts/render/index.ts +130 -0
  170. package/src/ts/render/options.ts +160 -0
  171. package/src/ts/render/png.ts +295 -0
  172. package/src/ts/render/svg.ts +120 -0
  173. package/src/ts/render/webgl.ts +206 -0
  174. package/src/ts/render/webgpu.ts +369 -0
  175. package/src/ts/rmqr/decoder.ts +101 -0
  176. package/src/ts/rmqr/detector.ts +90 -0
  177. package/src/ts/rmqr/encoder.ts +172 -0
  178. package/src/ts/rmqr/index.ts +37 -0
  179. package/src/ts/rmqr/tables.ts +154 -0
@@ -27,146 +27,295 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  import { BitMatrix } from '../core/bit-matrix.js';
32
31
  import { BitWriter } from '../core/bit-buffer.js';
33
32
  import { EncodeError } from '../core/errors.js';
34
33
  import { GF256_QR } from '../core/galois-field.js';
35
34
  import { rsEncode } from '../core/reed-solomon.js';
36
- import {
37
- FORMAT_MASK_FINDER, FORMAT_MASK_SUB, dataBitCapacity, dataModuleOrder, formatBits,
38
- functionModules, maskBit, versionForSize, versionInfo,
39
- } from './tables.js';
40
-
35
+ import { FORMAT_MASK_FINDER, FORMAT_MASK_SUB, dataBitCapacity, dataModuleOrder, formatBits, functionModules, maskBit, versionForSize, versionInfo, } from './tables.js';
41
36
  export const ALPHANUMERIC_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';
42
37
  const MODE = Object.freeze({ TERMINATOR: 0, NUMERIC: 1, ALPHANUMERIC: 2, BYTE: 3, KANJI: 4, FNC1: 5, FNC1_SECOND: 6, ECI: 7 });
43
-
44
38
  function utf8Bytes(text) { return new TextEncoder().encode(text); }
45
- function latin1Bytes(text) { const out = new Uint8Array(text.length); for (let i = 0; i < text.length; i++) { const c = text.charCodeAt(i); if (c > 255) throw new EncodeError('rMQR: text is not ISO-8859-1'); out[i] = c; } return out; }
46
- function isAlpha(text) { for (const ch of text) if (ALPHANUMERIC_CHARS.indexOf(ch) < 0) return false; return true; }
39
+ function latin1Bytes(text) { const out = new Uint8Array(text.length); for (let i = 0; i < text.length; i++) {
40
+ const c = text.charCodeAt(i);
41
+ if (c > 255)
42
+ throw new EncodeError('rMQR: text is not ISO-8859-1');
43
+ out[i] = c;
44
+ } return out; }
45
+ function isAlpha(text) { for (const ch of text)
46
+ if (ALPHANUMERIC_CHARS.indexOf(ch) < 0)
47
+ return false; return true; }
47
48
  function isNumeric(text) { return /^[0-9]*$/.test(text); }
48
-
49
49
  let sjisMap;
50
50
  function getSjisMap() {
51
- if (sjisMap !== undefined) return sjisMap;
52
- try {
53
- const decoder = new TextDecoder('shift_jis', { fatal: true });
54
- if (decoder.decode(new Uint8Array([0x82, 0xa0])) !== '') return (sjisMap = null);
55
- const map = new Map(); const buf = new Uint8Array(2);
56
- for (const [lo, hi] of [[0x8140, 0x9ffc], [0xe040, 0xebbf]]) for (let sjis = lo; sjis <= hi; sjis++) {
57
- const trail = sjis & 255; if (trail < 0x40 || trail === 0x7f || trail > 0xfc) continue;
58
- buf[0] = sjis >> 8; buf[1] = trail; let text; try { text = decoder.decode(buf); } catch { continue; }
59
- if (Array.from(text).length === 1 && !map.has(text)) map.set(text, sjis);
51
+ if (sjisMap !== undefined)
52
+ return sjisMap;
53
+ try {
54
+ const decoder = new TextDecoder('shift_jis', { fatal: true });
55
+ if (decoder.decode(new Uint8Array([0x82, 0xa0])) !== 'あ')
56
+ return (sjisMap = null);
57
+ const map = new Map();
58
+ const buf = new Uint8Array(2);
59
+ for (const [lo, hi] of [[0x8140, 0x9ffc], [0xe040, 0xebbf]])
60
+ for (let sjis = lo; sjis <= hi; sjis++) {
61
+ const trail = sjis & 255;
62
+ if (trail < 0x40 || trail === 0x7f || trail > 0xfc)
63
+ continue;
64
+ buf[0] = sjis >> 8;
65
+ buf[1] = trail;
66
+ let text;
67
+ try {
68
+ text = decoder.decode(buf);
69
+ }
70
+ catch {
71
+ continue;
72
+ }
73
+ if (Array.from(text).length === 1 && !map.has(text))
74
+ map.set(text, sjis);
75
+ }
76
+ return (sjisMap = map);
77
+ }
78
+ catch {
79
+ return (sjisMap = null);
60
80
  }
61
- return (sjisMap = map);
62
- } catch { return (sjisMap = null); }
63
81
  }
64
82
  function kanjiValue(ch) {
65
- const sjis = getSjisMap()?.get(ch); if (sjis === undefined) return -1;
66
- let v; if (sjis >= 0x8140 && sjis <= 0x9ffc) v = sjis - 0x8140; else if (sjis >= 0xe040 && sjis <= 0xebbf) v = sjis - 0xc140; else return -1;
67
- return ((v >> 8) * 0xc0) + (v & 0xff);
83
+ const sjis = getSjisMap()?.get(ch);
84
+ if (sjis === undefined)
85
+ return -1;
86
+ let v;
87
+ if (sjis >= 0x8140 && sjis <= 0x9ffc)
88
+ v = sjis - 0x8140;
89
+ else if (sjis >= 0xe040 && sjis <= 0xebbf)
90
+ v = sjis - 0xc140;
91
+ else
92
+ return -1;
93
+ return ((v >> 8) * 0xc0) + (v & 0xff);
68
94
  }
69
-
70
95
  function chooseMode(text, requested) {
71
- if (requested === 'numeric' || requested === 'alphanumeric' || requested === 'byte' || requested === 'kanji') return requested;
72
- if (isNumeric(text)) return 'numeric';
73
- if (isAlpha(text)) return 'alphanumeric';
74
- return 'byte';
96
+ if (requested === 'numeric' || requested === 'alphanumeric' || requested === 'byte' || requested === 'kanji')
97
+ return requested;
98
+ if (isNumeric(text))
99
+ return 'numeric';
100
+ if (isAlpha(text))
101
+ return 'alphanumeric';
102
+ return 'byte';
75
103
  }
76
-
77
104
  function modeBits(mode) { return MODE[mode.toUpperCase()] ?? MODE.BYTE; }
78
105
  function charCount(mode, text, bytes) { return mode === 'byte' ? bytes.length : mode === 'kanji' ? Array.from(text).length : text.length; }
79
106
  function payloadBits(mode, text, bytes) {
80
- if (mode === 'numeric') { let n = 0; for (let i = 0; i < text.length; i += 3) n += text.length - i >= 3 ? 10 : text.length - i === 2 ? 7 : 4; return n; }
81
- if (mode === 'alphanumeric') return Math.floor(text.length / 2) * 11 + (text.length & 1 ? 6 : 0);
82
- if (mode === 'kanji') return Array.from(text).length * 13;
83
- return bytes.length * 8;
107
+ if (mode === 'numeric') {
108
+ let n = 0;
109
+ for (let i = 0; i < text.length; i += 3)
110
+ n += text.length - i >= 3 ? 10 : text.length - i === 2 ? 7 : 4;
111
+ return n;
112
+ }
113
+ if (mode === 'alphanumeric')
114
+ return Math.floor(text.length / 2) * 11 + (text.length & 1 ? 6 : 0);
115
+ if (mode === 'kanji')
116
+ return Array.from(text).length * 13;
117
+ return bytes.length * 8;
84
118
  }
85
-
86
119
  function putEci(writer, assignment) {
87
- writer.put(MODE.ECI, 3);
88
- if (assignment <= 127) writer.put(assignment, 8);
89
- else if (assignment <= 16383) writer.put(0x8000 | assignment, 16);
90
- else if (assignment <= 999999) writer.put(0xc00000 | assignment, 24);
91
- else throw new EncodeError(`rMQR: invalid ECI assignment ${assignment}`);
120
+ writer.put(MODE.ECI, 3);
121
+ if (assignment <= 127)
122
+ writer.put(assignment, 8);
123
+ else if (assignment <= 16383)
124
+ writer.put(0x8000 | assignment, 16);
125
+ else if (assignment <= 999999)
126
+ writer.put(0xc00000 | assignment, 24);
127
+ else
128
+ throw new EncodeError(`rMQR: invalid ECI assignment ${assignment}`);
92
129
  }
93
-
94
130
  function makeData(text, v, ecc, options) {
95
- const requested = options.mode;
96
- const mode = chooseMode(text, requested);
97
- const charset = options.charset || (mode === 'byte' && Array.from(text).every((ch) => ch.charCodeAt(0) <= 255) ? 'iso-8859-1' : 'utf-8');
98
- const bytes = mode === 'byte' ? (charset === 'iso-8859-1' ? latin1Bytes(text) : utf8Bytes(text)) : new Uint8Array();
99
- const countBits = v.countBits(mode);
100
- if (!countBits) throw new EncodeError(`rMQR: unsupported mode ${mode}`);
101
- const writer = new BitWriter();
102
- if (options.eci !== undefined) putEci(writer, options.eci);
103
- else if (mode === 'byte' && charset === 'utf-8') putEci(writer, 26);
104
- writer.put(modeBits(mode), 3); writer.put(charCount(mode, text, bytes), countBits); // header
105
- if (mode === 'numeric') for (let i = 0; i < text.length; i += 3) { const s = text.slice(i, i + 3); writer.put(Number(s), s.length === 3 ? 10 : s.length === 2 ? 7 : 4); }
106
- else if (mode === 'alphanumeric') for (let i = 0; i < text.length; i += 2) { const a = ALPHANUMERIC_CHARS.indexOf(text[i]); const b = i + 1 < text.length ? ALPHANUMERIC_CHARS.indexOf(text[i + 1]) : -1; if (a < 0 || (b < 0 && i + 1 < text.length)) throw new EncodeError('rMQR: invalid alphanumeric character'); writer.put(b < 0 ? a : a * 45 + b, b < 0 ? 6 : 11); }
107
- else if (mode === 'kanji') for (const ch of Array.from(text)) { const value = kanjiValue(ch); if (value < 0) throw new EncodeError(`rMQR: character ${ch} is not encodable in Kanji mode`); writer.put(value, 13); }
108
- else writer.putBytes(bytes);
109
- const capacity = dataBitCapacity(v.version, ecc);
110
- if (writer.length > capacity) throw new EncodeError(`rMQR: payload does not fit ${v.name}-${ecc}`);
111
- if (writer.length + 3 <= capacity) writer.put(0, 3);
112
- while (writer.length & 7) writer.putBit(false);
113
- const dataBytes = v.blockLayout(ecc).totalDataCodewords;
114
- let pad = 0xec; while (writer.toBytes().length < dataBytes) { writer.put(pad, 8); pad = pad === 0xec ? 0x11 : 0xec; }
115
- return writer.toBytes();
131
+ const requested = options.mode;
132
+ const mode = chooseMode(text, requested);
133
+ const charset = options.charset || (mode === 'byte' && Array.from(text).every((ch) => ch.charCodeAt(0) <= 255) ? 'iso-8859-1' : 'utf-8');
134
+ const bytes = mode === 'byte' ? (charset === 'iso-8859-1' ? latin1Bytes(text) : utf8Bytes(text)) : new Uint8Array();
135
+ const countBits = v.countBits(mode);
136
+ if (!countBits)
137
+ throw new EncodeError(`rMQR: unsupported mode ${mode}`);
138
+ const writer = new BitWriter();
139
+ if (options.eci !== undefined)
140
+ putEci(writer, options.eci);
141
+ else if (mode === 'byte' && charset === 'utf-8')
142
+ putEci(writer, 26);
143
+ writer.put(modeBits(mode), 3);
144
+ writer.put(charCount(mode, text, bytes), countBits); // header
145
+ if (mode === 'numeric')
146
+ for (let i = 0; i < text.length; i += 3) {
147
+ const s = text.slice(i, i + 3);
148
+ writer.put(Number(s), s.length === 3 ? 10 : s.length === 2 ? 7 : 4);
149
+ }
150
+ else if (mode === 'alphanumeric')
151
+ for (let i = 0; i < text.length; i += 2) {
152
+ const a = ALPHANUMERIC_CHARS.indexOf(text[i]);
153
+ const b = i + 1 < text.length ? ALPHANUMERIC_CHARS.indexOf(text[i + 1]) : -1;
154
+ if (a < 0 || (b < 0 && i + 1 < text.length))
155
+ throw new EncodeError('rMQR: invalid alphanumeric character');
156
+ writer.put(b < 0 ? a : a * 45 + b, b < 0 ? 6 : 11);
157
+ }
158
+ else if (mode === 'kanji')
159
+ for (const ch of Array.from(text)) {
160
+ const value = kanjiValue(ch);
161
+ if (value < 0)
162
+ throw new EncodeError(`rMQR: character ${ch} is not encodable in Kanji mode`);
163
+ writer.put(value, 13);
164
+ }
165
+ else
166
+ writer.putBytes(bytes);
167
+ const capacity = dataBitCapacity(v.version, ecc);
168
+ if (writer.length > capacity)
169
+ throw new EncodeError(`rMQR: payload does not fit ${v.name}-${ecc}`);
170
+ if (writer.length + 3 <= capacity)
171
+ writer.put(0, 3);
172
+ while (writer.length & 7)
173
+ writer.putBit(false);
174
+ const dataBytes = v.blockLayout(ecc).totalDataCodewords;
175
+ let pad = 0xec;
176
+ while (writer.toBytes().length < dataBytes) {
177
+ writer.put(pad, 8);
178
+ pad = pad === 0xec ? 0x11 : 0xec;
179
+ }
180
+ return writer.toBytes();
116
181
  }
117
-
118
182
  function interleave(data, v, ecc) {
119
- const layout = v.blockLayout(ecc); const blocks = []; let offset = 0;
120
- for (const b of layout.blocks) { const d = Array.from(data.slice(offset, offset + b.data)); offset += b.data; blocks.push({ data: d, ecc: rsEncode(d, b.ecc, GF256_QR, 0) }); }
121
- const out = []; const maxData = Math.max(...blocks.map((b) => b.data.length)); const maxEcc = Math.max(...blocks.map((b) => b.ecc.length));
122
- for (let i = 0; i < maxData; i++) for (const b of blocks) if (i < b.data.length) out.push(b.data[i]);
123
- for (let i = 0; i < maxEcc; i++) for (const b of blocks) if (i < b.ecc.length) out.push(b.ecc[i]);
124
- return Uint8Array.from(out);
183
+ const layout = v.blockLayout(ecc);
184
+ const blocks = [];
185
+ let offset = 0;
186
+ for (const b of layout.blocks) {
187
+ const d = Array.from(data.slice(offset, offset + b.data));
188
+ offset += b.data;
189
+ blocks.push({ data: d, ecc: rsEncode(d, b.ecc, GF256_QR, 0) });
190
+ }
191
+ const out = [];
192
+ const maxData = Math.max(...blocks.map((b) => b.data.length));
193
+ const maxEcc = Math.max(...blocks.map((b) => b.ecc.length));
194
+ for (let i = 0; i < maxData; i++)
195
+ for (const b of blocks)
196
+ if (i < b.data.length)
197
+ out.push(b.data[i]);
198
+ for (let i = 0; i < maxEcc; i++)
199
+ for (const b of blocks)
200
+ if (i < b.ecc.length)
201
+ out.push(b.ecc[i]);
202
+ return Uint8Array.from(out);
125
203
  }
126
-
127
204
  function drawFunctions(m, version) {
128
- const v = versionInfo(version); const fn = functionModules(version); const { width: w, height: h } = v;
129
- const setIfData = (x, y, on) => { if (!fn.get(x, y)) m.setValue(x, y, on); };
130
- for (let x = 0; x < w; x++) { m.setValue(x, 0, (x & 1) === 0); m.setValue(x, h - 1, (x & 1) === 0); }
131
- for (const x of [0, w - 1, ...new Set([...(awaitableAlignment(version))])]) for (let y = 0; y < h; y++) setIfData(x, y, (y & 1) === 0);
132
- for (const cx of awaitableAlignment(version)) for (const y of [0, 1, h - 2, h - 1]) m.setValue(cx + (y === 0 || y === h - 1 ? 0 : 0), y, false);
133
- // Alignment patterns (top and bottom).
134
- for (const cx of awaitableAlignment(version)) for (let i = 0; i < 3; i++) for (let j = 0; j < 3; j++) { const on = i === 0 || i === 2 || j === 0 || j === 2; m.setValue(cx + j - 1, i, on); m.setValue(cx + j - 1, h - 1 - i, on); }
135
- // Finder and separator.
136
- for (let i = 0; i < 7; i++) for (let j = 0; j < 7; j++) m.setValue(j, i, i === 0 || i === 6 || j === 0 || j === 6 || (i >= 2 && i <= 4 && j >= 2 && j <= 4));
137
- for (let n = 0; n < 8; n++) { if (n < h) m.setValue(7, n, false); if (h >= 9) m.setValue(n, 7, false); }
138
- for (let i = 0; i < 5; i++) for (let j = 0; j < 5; j++) m.setValue(w - j - 1, h - i - 1, i === 0 || i === 4 || j === 0 || j === 4 || (i === 2 && j === 2));
139
- m.set(w - 1, 0); m.set(w - 2, 0); m.set(w - 1, 1); if (h >= 11) { m.set(0, h - 1); m.set(1, h - 1); m.set(2, h - 1); m.set(0, h - 2); }
205
+ const v = versionInfo(version);
206
+ const fn = functionModules(version);
207
+ const { width: w, height: h } = v;
208
+ const setIfData = (x, y, on) => { if (!fn.get(x, y))
209
+ m.setValue(x, y, on); };
210
+ for (let x = 0; x < w; x++) {
211
+ m.setValue(x, 0, (x & 1) === 0);
212
+ m.setValue(x, h - 1, (x & 1) === 0);
213
+ }
214
+ for (const x of [0, w - 1, ...new Set([...(awaitableAlignment(version))])])
215
+ for (let y = 0; y < h; y++)
216
+ setIfData(x, y, (y & 1) === 0);
217
+ for (const cx of awaitableAlignment(version))
218
+ for (const y of [0, 1, h - 2, h - 1])
219
+ m.setValue(cx + (y === 0 || y === h - 1 ? 0 : 0), y, false);
220
+ // Alignment patterns (top and bottom).
221
+ for (const cx of awaitableAlignment(version))
222
+ for (let i = 0; i < 3; i++)
223
+ for (let j = 0; j < 3; j++) {
224
+ const on = i === 0 || i === 2 || j === 0 || j === 2;
225
+ m.setValue(cx + j - 1, i, on);
226
+ m.setValue(cx + j - 1, h - 1 - i, on);
227
+ }
228
+ // Finder and separator.
229
+ for (let i = 0; i < 7; i++)
230
+ for (let j = 0; j < 7; j++)
231
+ m.setValue(j, i, i === 0 || i === 6 || j === 0 || j === 6 || (i >= 2 && i <= 4 && j >= 2 && j <= 4));
232
+ for (let n = 0; n < 8; n++) {
233
+ if (n < h)
234
+ m.setValue(7, n, false);
235
+ if (h >= 9)
236
+ m.setValue(n, 7, false);
237
+ }
238
+ for (let i = 0; i < 5; i++)
239
+ for (let j = 0; j < 5; j++)
240
+ m.setValue(w - j - 1, h - i - 1, i === 0 || i === 4 || j === 0 || j === 4 || (i === 2 && j === 2));
241
+ m.set(w - 1, 0);
242
+ m.set(w - 2, 0);
243
+ m.set(w - 1, 1);
244
+ if (h >= 11) {
245
+ m.set(0, h - 1);
246
+ m.set(1, h - 1);
247
+ m.set(2, h - 1);
248
+ m.set(0, h - 2);
249
+ }
140
250
  }
141
-
142
251
  // Kept as a local helper so drawFunctions stays independent of mutable tables.
143
252
  function awaitableAlignment(version) { return ({ 27: [], 43: [21], 59: [19, 39], 77: [25, 51], 99: [23, 49, 75], 139: [27, 55, 83, 111] })[versionInfo(version).width] || []; }
144
-
145
253
  function drawFormat(m, version, ecc) {
146
- const v = versionInfo(version); let bits = formatBits(version, ecc) ^ FORMAT_MASK_FINDER;
147
- for (let n = 0; n < 18; n++) m.setValue(8 + Math.floor(n / 5), 1 + (n % 5), ((bits >>> n) & 1) !== 0);
148
- bits = formatBits(version, ecc) ^ FORMAT_MASK_SUB;
149
- for (let n = 0; n < 15; n++) m.setValue(v.width - 8 + Math.floor(n / 5), v.height - 6 + (n % 5), ((bits >>> n) & 1) !== 0);
150
- for (let n = 15; n < 18; n++) m.setValue(v.width - 5 + (n - 15), v.height - 6, ((bits >>> n) & 1) !== 0);
254
+ const v = versionInfo(version);
255
+ let bits = formatBits(version, ecc) ^ FORMAT_MASK_FINDER;
256
+ for (let n = 0; n < 18; n++)
257
+ m.setValue(8 + Math.floor(n / 5), 1 + (n % 5), ((bits >>> n) & 1) !== 0);
258
+ bits = formatBits(version, ecc) ^ FORMAT_MASK_SUB;
259
+ for (let n = 0; n < 15; n++)
260
+ m.setValue(v.width - 8 + Math.floor(n / 5), v.height - 6 + (n % 5), ((bits >>> n) & 1) !== 0);
261
+ for (let n = 15; n < 18; n++)
262
+ m.setValue(v.width - 5 + (n - 15), v.height - 6, ((bits >>> n) & 1) !== 0);
151
263
  }
152
-
153
264
  function buildMatrix(version, ecc, codewords) {
154
- const v = versionInfo(version); const m = new BitMatrix(v.width, v.height); drawFunctions(m, version); drawFormat(m, version, ecc);
155
- const fn = functionModules(version); const order = dataModuleOrder(version); let bit = 0; for (const [x, y] of order) { let on = bit < codewords.length * 8 && ((codewords[bit >>> 3] >>> (7 - (bit & 7))) & 1) !== 0; if (maskBit(x, y)) on = !on; m.setValue(x, y, on); bit++; }
156
- return m;
265
+ const v = versionInfo(version);
266
+ const m = new BitMatrix(v.width, v.height);
267
+ drawFunctions(m, version);
268
+ drawFormat(m, version, ecc);
269
+ const fn = functionModules(version);
270
+ const order = dataModuleOrder(version);
271
+ let bit = 0;
272
+ for (const [x, y] of order) {
273
+ let on = bit < codewords.length * 8 && ((codewords[bit >>> 3] >>> (7 - (bit & 7))) & 1) !== 0;
274
+ if (maskBit(x, y))
275
+ on = !on;
276
+ m.setValue(x, y, on);
277
+ bit++;
278
+ }
279
+ return m;
157
280
  }
158
-
159
281
  /** Encode text into a rMQR module matrix. */
160
282
  export function encodeRMQR(text, options = {}) {
161
- if (typeof text !== 'string' || text.length === 0) throw new EncodeError('rMQR: text must be a non-empty string');
162
- const ecc = options.ecc || 'M'; if (ecc !== 'M' && ecc !== 'H') throw new EncodeError('rMQR: ECC must be M or H');
163
- let forced = options.version; if (typeof forced === 'string') { const match = /^R(\d+)x(\d+)$/i.exec(forced); if (!match) throw new EncodeError(`rMQR: invalid version ${forced}`); const info = versionForSize(Number(match[2]), Number(match[1])); if (!info) throw new EncodeError(`rMQR: unsupported version ${forced}`); forced = info.version; }
164
- if (forced !== undefined && (!Number.isInteger(forced) || forced < 1 || forced > 32)) throw new EncodeError('rMQR: version must be 1-32');
165
- const versions = forced ? [forced] : Array.from({ length: 32 }, (_, i) => i + 1);
166
- let selected = null;
167
- for (const n of versions) { const v = versionInfo(n); try { const data = makeData(text, v, ecc, options); selected = { v, data }; break; } catch (error) { if (forced) throw error; } }
168
- if (!selected) throw new EncodeError(`rMQR: text is too long for ECC ${ecc}`);
169
- const codewords = interleave(selected.data, selected.v, ecc); const matrix = buildMatrix(selected.v.version, ecc, codewords); matrix.rmqr = { version: selected.v.version, name: selected.v.name, ecc }; return matrix;
283
+ if (typeof text !== 'string' || text.length === 0)
284
+ throw new EncodeError('rMQR: text must be a non-empty string');
285
+ const ecc = options.ecc || 'M';
286
+ if (ecc !== 'M' && ecc !== 'H')
287
+ throw new EncodeError('rMQR: ECC must be M or H');
288
+ let forced = options.version;
289
+ if (typeof forced === 'string') {
290
+ const match = /^R(\d+)x(\d+)$/i.exec(forced);
291
+ if (!match)
292
+ throw new EncodeError(`rMQR: invalid version ${forced}`);
293
+ const info = versionForSize(Number(match[2]), Number(match[1]));
294
+ if (!info)
295
+ throw new EncodeError(`rMQR: unsupported version ${forced}`);
296
+ forced = info.version;
297
+ }
298
+ if (forced !== undefined && (!Number.isInteger(forced) || forced < 1 || forced > 32))
299
+ throw new EncodeError('rMQR: version must be 1-32');
300
+ const versions = forced ? [forced] : Array.from({ length: 32 }, (_, i) => i + 1);
301
+ let selected = null;
302
+ for (const n of versions) {
303
+ const v = versionInfo(n);
304
+ try {
305
+ const data = makeData(text, v, ecc, options);
306
+ selected = { v, data };
307
+ break;
308
+ }
309
+ catch (error) {
310
+ if (forced)
311
+ throw error;
312
+ }
313
+ }
314
+ if (!selected)
315
+ throw new EncodeError(`rMQR: text is too long for ECC ${ecc}`);
316
+ const codewords = interleave(selected.data, selected.v, ecc);
317
+ const matrix = buildMatrix(selected.v.version, ecc, codewords);
318
+ matrix.rmqr = { version: selected.v.version, name: selected.v.name, ecc };
319
+ return matrix;
170
320
  }
171
-
172
321
  export { MODE };
@@ -27,11 +27,7 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  export { encodeRMQR, ALPHANUMERIC_CHARS } from './encoder.js';
32
31
  export { decodeRMQR } from './decoder.js';
33
32
  export { detectRMQR, detectAndDecodeRMQR } from './detector.js';
34
- export {
35
- RMQR_SIZES, versionInfo, versionForSize, alignmentCoordinates, dataModuleOrder,
36
- functionModules, dataBitCapacity, formatBits, maskBit, validateTables,
37
- } from './tables.js';
33
+ export { RMQR_SIZES, versionInfo, versionForSize, alignmentCoordinates, dataModuleOrder, functionModules, dataBitCapacity, formatBits, maskBit, validateTables, } from './tables.js';