@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.
- package/LICENSE +5 -4
- package/NOTICE.md +2 -2
- package/README.md +17 -13
- package/bundle/sythos-barcode.esm.js +11658 -11244
- package/bundle/sythos-barcode.js +11658 -11244
- package/package.json +10 -3
- package/src/index.d.ts +1 -1
- package/src/index.js +508 -516
- package/src/js/aztec/decoder.js +208 -199
- package/src/js/aztec/detector.js +153 -126
- package/src/js/aztec/encoder.js +172 -153
- package/src/js/aztec/high-level.js +106 -101
- package/src/js/aztec/index.js +1 -12
- package/src/js/aztec/tables.js +106 -120
- package/src/js/aztecrune/decoder.js +76 -85
- package/src/js/aztecrune/detector.js +107 -93
- package/src/js/aztecrune/encoder.js +50 -68
- package/src/js/aztecrune/index.js +1 -16
- package/src/js/aztecrune/tables.js +59 -54
- package/src/js/compactpdf417/decoder.js +69 -74
- package/src/js/compactpdf417/detector.js +74 -75
- package/src/js/compactpdf417/encoder.js +68 -81
- package/src/js/compactpdf417/index.js +1 -13
- package/src/js/compactpdf417/tables.js +71 -80
- package/src/js/core/bit-buffer.js +106 -122
- package/src/js/core/bit-matrix.js +196 -194
- package/src/js/core/errors.js +13 -15
- package/src/js/core/galois-field.js +119 -133
- package/src/js/core/index.js +2 -19
- package/src/js/core/reed-solomon.js +195 -204
- package/src/js/databar/codec.js +93 -108
- package/src/js/databar/decoder.js +149 -140
- package/src/js/databar/encoder.js +47 -55
- package/src/js/databar/gs1.js +122 -123
- package/src/js/databar/index.js +4 -36
- package/src/js/databar/patterns.js +81 -85
- package/src/js/databar/tables.js +51 -52
- package/src/js/datamatrix/decoder.js +216 -182
- package/src/js/datamatrix/detector.js +161 -132
- package/src/js/datamatrix/encoder.js +192 -133
- package/src/js/datamatrix/index.js +1 -9
- package/src/js/datamatrix/tables.js +68 -69
- package/src/js/frameqr/decoder.js +102 -125
- package/src/js/frameqr/detector.js +101 -94
- package/src/js/frameqr/encoder.js +67 -80
- package/src/js/frameqr/index.js +1 -10
- package/src/js/frameqr/tables.js +145 -163
- package/src/js/image/binarizer.js +146 -162
- package/src/js/image/grid-sampler.js +63 -79
- package/src/js/image/index.js +0 -2
- package/src/js/image/luminance.js +129 -140
- package/src/js/image/perspective.js +112 -149
- package/src/js/micropdf417/compaction.js +64 -65
- package/src/js/micropdf417/decoder.js +106 -109
- package/src/js/micropdf417/detector.js +73 -70
- package/src/js/micropdf417/encoder.js +129 -154
- package/src/js/micropdf417/error-correction.js +6 -11
- package/src/js/micropdf417/index.js +2 -16
- package/src/js/micropdf417/tables.js +112 -99
- package/src/js/microqr/decoder.js +177 -182
- package/src/js/microqr/detector.js +240 -256
- package/src/js/microqr/encoder.js +239 -194
- package/src/js/microqr/index.js +0 -2
- package/src/js/microqr/tables.js +208 -200
- package/src/js/oned/addons.js +167 -191
- package/src/js/oned/index.js +27 -58
- package/src/js/oned/patterns.js +194 -213
- package/src/js/oned/reader.js +1003 -984
- package/src/js/oned/writers.js +411 -466
- package/src/js/pdf417/compaction.js +315 -222
- package/src/js/pdf417/decoder.js +71 -36
- package/src/js/pdf417/detector.js +377 -361
- package/src/js/pdf417/encoder.js +57 -46
- package/src/js/pdf417/error-correction.js +5 -8
- package/src/js/pdf417/tables.js +248 -250
- package/src/js/qr/decoder.js +311 -347
- package/src/js/qr/detector.js +378 -395
- package/src/js/qr/encoder.js +514 -599
- package/src/js/qr/index.js +0 -2
- package/src/js/qr/tables.js +375 -422
- package/src/js/render/image-data.js +57 -62
- package/src/js/render/index.js +21 -23
- package/src/js/render/options.js +82 -90
- package/src/js/render/png.js +144 -169
- package/src/js/render/svg.js +41 -44
- package/src/js/render/webgl.js +103 -109
- package/src/js/render/webgpu.js +205 -217
- package/src/js/rmqr/decoder.js +161 -53
- package/src/js/rmqr/detector.js +73 -41
- package/src/js/rmqr/encoder.js +253 -104
- package/src/js/rmqr/index.js +1 -5
- package/src/js/rmqr/tables.js +108 -85
- package/src/ts/aztec/decoder.ts +317 -0
- package/src/ts/aztec/detector.ts +224 -0
- package/src/ts/aztec/encoder.ts +257 -0
- package/src/ts/aztec/high-level.ts +211 -0
- package/src/ts/aztec/index.ts +45 -0
- package/src/ts/aztec/tables.ts +210 -0
- package/src/ts/aztecrune/decoder.ts +155 -0
- package/src/ts/aztecrune/detector.ts +166 -0
- package/src/ts/aztecrune/encoder.ts +121 -0
- package/src/ts/aztecrune/index.ts +49 -0
- package/src/ts/aztecrune/tables.ts +137 -0
- package/src/ts/compactpdf417/decoder.ts +128 -0
- package/src/ts/compactpdf417/detector.ts +139 -0
- package/src/ts/compactpdf417/encoder.ts +140 -0
- package/src/ts/compactpdf417/index.ts +17 -0
- package/src/ts/compactpdf417/tables.ts +173 -0
- package/src/ts/core/bit-buffer.ts +174 -0
- package/src/ts/core/bit-matrix.ts +241 -0
- package/src/ts/core/errors.ts +61 -0
- package/src/ts/core/galois-field.ts +207 -0
- package/src/ts/core/index.ts +56 -0
- package/src/ts/core/reed-solomon.ts +327 -0
- package/src/ts/databar/codec.ts +181 -0
- package/src/ts/databar/decoder.ts +215 -0
- package/src/ts/databar/encoder.ts +96 -0
- package/src/ts/databar/gs1.ts +177 -0
- package/src/ts/databar/index.ts +68 -0
- package/src/ts/databar/patterns.ts +143 -0
- package/src/ts/databar/tables.ts +124 -0
- package/src/ts/datamatrix/decoder.ts +262 -0
- package/src/ts/datamatrix/detector.ts +225 -0
- package/src/ts/datamatrix/encoder.ts +191 -0
- package/src/ts/datamatrix/index.ts +42 -0
- package/src/ts/datamatrix/tables.ts +123 -0
- package/src/ts/frameqr/decoder.ts +239 -0
- package/src/ts/frameqr/detector.ts +192 -0
- package/src/ts/frameqr/encoder.ts +156 -0
- package/src/ts/frameqr/index.ts +42 -0
- package/src/ts/frameqr/tables.ts +270 -0
- package/src/ts/image/binarizer.ts +270 -0
- package/src/ts/image/grid-sampler.ts +164 -0
- package/src/ts/image/index.ts +40 -0
- package/src/ts/image/luminance.ts +196 -0
- package/src/ts/image/perspective.ts +195 -0
- package/src/ts/index.d.ts +1 -1
- package/src/ts/index.ts +790 -0
- package/src/ts/micropdf417/compaction.ts +116 -0
- package/src/ts/micropdf417/decoder.ts +183 -0
- package/src/ts/micropdf417/detector.ts +149 -0
- package/src/ts/micropdf417/encoder.ts +209 -0
- package/src/ts/micropdf417/error-correction.ts +55 -0
- package/src/ts/micropdf417/index.ts +49 -0
- package/src/ts/micropdf417/tables.ts +184 -0
- package/src/ts/microqr/decoder.ts +245 -0
- package/src/ts/microqr/detector.ts +355 -0
- package/src/ts/microqr/encoder.ts +269 -0
- package/src/ts/microqr/index.ts +36 -0
- package/src/ts/microqr/tables.ts +316 -0
- package/src/ts/oned/addons.ts +420 -0
- package/src/ts/oned/index.ts +106 -0
- package/src/ts/oned/patterns.ts +384 -0
- package/src/ts/oned/reader.ts +1364 -0
- package/src/ts/oned/writers.ts +746 -0
- package/src/ts/pdf417/compaction.ts +298 -0
- package/src/ts/pdf417/decoder.ts +75 -0
- package/src/ts/pdf417/detector.ts +468 -0
- package/src/ts/pdf417/encoder.ts +91 -0
- package/src/ts/pdf417/error-correction.ts +47 -0
- package/src/ts/pdf417/index.ts +6 -0
- package/src/ts/pdf417/tables.ts +317 -0
- package/src/ts/qr/decoder.ts +575 -0
- package/src/ts/qr/detector.ts +630 -0
- package/src/ts/qr/encoder.ts +958 -0
- package/src/ts/qr/index.ts +44 -0
- package/src/ts/qr/tables.ts +737 -0
- package/src/ts/render/image-data.ts +125 -0
- package/src/ts/render/index.ts +130 -0
- package/src/ts/render/options.ts +160 -0
- package/src/ts/render/png.ts +295 -0
- package/src/ts/render/svg.ts +120 -0
- package/src/ts/render/webgl.ts +206 -0
- package/src/ts/render/webgpu.ts +369 -0
- package/src/ts/rmqr/decoder.ts +101 -0
- package/src/ts/rmqr/detector.ts +90 -0
- package/src/ts/rmqr/encoder.ts +172 -0
- package/src/ts/rmqr/index.ts +37 -0
- package/src/ts/rmqr/tables.ts +154 -0
package/src/js/render/webgpu.js
CHANGED
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/**
|
|
32
31
|
* WebGPU drawing.
|
|
33
32
|
*
|
|
@@ -45,9 +44,7 @@
|
|
|
45
44
|
*
|
|
46
45
|
* @module render/webgpu
|
|
47
46
|
*/
|
|
48
|
-
|
|
49
47
|
import { normalizeOptions, parseColor } from './options.js';
|
|
50
|
-
|
|
51
48
|
/**
|
|
52
49
|
* Vertex and fragment stages in one module, mirroring the WebGL2 pair.
|
|
53
50
|
*
|
|
@@ -92,7 +89,6 @@ fn fragmentMain(@location(0) quadUV : vec2<f32>) -> @location(0) vec4<f32> {
|
|
|
92
89
|
return select(style.light, style.dark, v > 0.5);
|
|
93
90
|
}
|
|
94
91
|
`;
|
|
95
|
-
|
|
96
92
|
/**
|
|
97
93
|
* The adapter and device are per-page, not per-barcode.
|
|
98
94
|
*
|
|
@@ -105,7 +101,6 @@ fn fragmentMain(@location(0) quadUV : vec2<f32>) -> @location(0) vec4<f32> {
|
|
|
105
101
|
* @type {Promise<any> | null}
|
|
106
102
|
*/
|
|
107
103
|
let sharedDevice = null;
|
|
108
|
-
|
|
109
104
|
/**
|
|
110
105
|
* Get the shared device, requesting one on first use.
|
|
111
106
|
*
|
|
@@ -114,43 +109,43 @@ let sharedDevice = null;
|
|
|
114
109
|
* @returns {Promise<any>} The device, or null.
|
|
115
110
|
*/
|
|
116
111
|
function acquireDevice() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const pending = (async () => {
|
|
126
|
-
try {
|
|
127
|
-
if (typeof navigator === 'undefined' || !navigator.gpu) return null;
|
|
128
|
-
const adapter = await navigator.gpu.requestAdapter();
|
|
129
|
-
if (!adapter) {
|
|
130
|
-
forget();
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
const device = await adapter.requestDevice();
|
|
134
|
-
if (!device) {
|
|
135
|
-
forget();
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
// A lost device can never be revived, so drop it and let the next
|
|
139
|
-
// render ask for a fresh one instead of failing forever.
|
|
140
|
-
if (device.lost && typeof device.lost.then === 'function') {
|
|
141
|
-
device.lost.then(forget, forget);
|
|
142
|
-
}
|
|
143
|
-
return device;
|
|
144
|
-
} catch {
|
|
145
|
-
forget();
|
|
146
|
-
return null;
|
|
112
|
+
if (sharedDevice)
|
|
113
|
+
return sharedDevice;
|
|
114
|
+
// Hoisted so the `lost` handler below can compare against this exact
|
|
115
|
+
// promise, and never clear a newer one that has replaced it.
|
|
116
|
+
function forget() {
|
|
117
|
+
if (sharedDevice === pending)
|
|
118
|
+
sharedDevice = null;
|
|
147
119
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
120
|
+
const pending = (async () => {
|
|
121
|
+
try {
|
|
122
|
+
if (typeof navigator === 'undefined' || !navigator.gpu)
|
|
123
|
+
return null;
|
|
124
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
125
|
+
if (!adapter) {
|
|
126
|
+
forget();
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const device = await adapter.requestDevice();
|
|
130
|
+
if (!device) {
|
|
131
|
+
forget();
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
// A lost device can never be revived, so drop it and let the next
|
|
135
|
+
// render ask for a fresh one instead of failing forever.
|
|
136
|
+
if (device.lost && typeof device.lost.then === 'function') {
|
|
137
|
+
device.lost.then(forget, forget);
|
|
138
|
+
}
|
|
139
|
+
return device;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
forget();
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
})();
|
|
146
|
+
sharedDevice = pending;
|
|
147
|
+
return pending;
|
|
152
148
|
}
|
|
153
|
-
|
|
154
149
|
/**
|
|
155
150
|
* Is WebGPU usable here?
|
|
156
151
|
*
|
|
@@ -160,18 +155,20 @@ function acquireDevice() {
|
|
|
160
155
|
* @returns {Promise<boolean>}
|
|
161
156
|
*/
|
|
162
157
|
export async function isWebGPUAvailable() {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
158
|
+
try {
|
|
159
|
+
if (typeof navigator === 'undefined')
|
|
160
|
+
return false;
|
|
161
|
+
if (!navigator.gpu || typeof navigator.gpu.requestAdapter !== 'function')
|
|
162
|
+
return false;
|
|
163
|
+
// An adapter is the real test: `navigator.gpu` exists on machines whose
|
|
164
|
+
// GPU is blocklisted, where every request still comes back null.
|
|
165
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
166
|
+
return Boolean(adapter);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
173
171
|
}
|
|
174
|
-
|
|
175
172
|
/**
|
|
176
173
|
* Did the shader compile?
|
|
177
174
|
*
|
|
@@ -183,20 +180,23 @@ export async function isWebGPUAvailable() {
|
|
|
183
180
|
* @returns {Promise<boolean>}
|
|
184
181
|
*/
|
|
185
182
|
async function compiles(module) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
183
|
+
try {
|
|
184
|
+
const query = module.getCompilationInfo ?? module.compilationInfo;
|
|
185
|
+
if (typeof query !== 'function')
|
|
186
|
+
return true;
|
|
187
|
+
const info = await query.call(module);
|
|
188
|
+
if (!info || !info.messages)
|
|
189
|
+
return true;
|
|
190
|
+
for (let i = 0; i < info.messages.length; i++) {
|
|
191
|
+
if (info.messages[i].type === 'error')
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return true;
|
|
193
198
|
}
|
|
194
|
-
return true;
|
|
195
|
-
} catch {
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
199
|
}
|
|
199
|
-
|
|
200
200
|
/**
|
|
201
201
|
* Draw a matrix into a canvas with WebGPU.
|
|
202
202
|
*
|
|
@@ -209,161 +209,149 @@ async function compiles(module) {
|
|
|
209
209
|
* availability before committing a canvas to this path.
|
|
210
210
|
*/
|
|
211
211
|
export async function renderToCanvasWebGPU(matrix, canvas, options = {}) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
212
|
+
let device = null;
|
|
213
|
+
let texture = null;
|
|
214
|
+
let uniforms = null;
|
|
215
|
+
try {
|
|
216
|
+
if (typeof navigator === 'undefined' || !navigator.gpu)
|
|
217
|
+
return false;
|
|
218
|
+
const opts = normalizeOptions(matrix, options);
|
|
219
|
+
const { source, pixelWidth, pixelHeight } = opts;
|
|
220
|
+
device = await acquireDevice();
|
|
221
|
+
if (!device)
|
|
222
|
+
return false;
|
|
223
|
+
// Oversized symbols are a legitimate failure, not a crash: say so and let
|
|
224
|
+
// the caller fall back to a path with no texture ceiling.
|
|
225
|
+
// 8192 is the floor the specification guarantees, so it is the right
|
|
226
|
+
// assumption when an implementation does not report its limits.
|
|
227
|
+
const maxDimension = (device.limits && device.limits.maxTextureDimension2D) || 8192;
|
|
228
|
+
if (source.width > maxDimension || source.height > maxDimension)
|
|
229
|
+
return false;
|
|
230
|
+
const context = canvas.getContext('webgpu');
|
|
231
|
+
if (!context)
|
|
232
|
+
return false;
|
|
233
|
+
canvas.width = pixelWidth;
|
|
234
|
+
canvas.height = pixelHeight;
|
|
235
|
+
const format = navigator.gpu.getPreferredCanvasFormat();
|
|
236
|
+
context.configure({ device, format, alphaMode: 'premultiplied' });
|
|
237
|
+
// One byte per module. r8unorm is the narrowest format every WebGPU
|
|
238
|
+
// implementation is required to support as a sampled texture.
|
|
239
|
+
const pixels = new Uint8Array(source.width * source.height);
|
|
240
|
+
for (let y = 0; y < source.height; y++) {
|
|
241
|
+
for (let x = 0; x < source.width; x++) {
|
|
242
|
+
pixels[y * source.width + x] = source.get(x, y) ? 255 : 0;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
texture = device.createTexture({
|
|
246
|
+
size: { width: source.width, height: source.height, depthOrArrayLayers: 1 },
|
|
247
|
+
format: 'r8unorm',
|
|
248
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
|
249
|
+
});
|
|
250
|
+
// `bytesPerRow` needs no 256-byte alignment here — that rule belongs to
|
|
251
|
+
// buffer-to-texture copies, not to writeTexture's linear source data.
|
|
252
|
+
device.queue.writeTexture({ texture }, pixels, { offset: 0, bytesPerRow: source.width, rowsPerImage: source.height }, { width: source.width, height: source.height, depthOrArrayLayers: 1 });
|
|
253
|
+
const sampler = device.createSampler({
|
|
254
|
+
magFilter: 'nearest',
|
|
255
|
+
minFilter: 'nearest',
|
|
256
|
+
addressModeU: 'clamp-to-edge',
|
|
257
|
+
addressModeV: 'clamp-to-edge',
|
|
258
|
+
});
|
|
259
|
+
// The canvas is configured as premultiplied, so the colours have to be
|
|
260
|
+
// too — otherwise a translucent `light` would come out too bright and a
|
|
261
|
+
// fully transparent one would tint the page behind it.
|
|
262
|
+
const dark = parseColor(opts.dark);
|
|
263
|
+
const light = parseColor(opts.light);
|
|
264
|
+
const premultiplied = (c) => {
|
|
265
|
+
const a = c[3] / 255;
|
|
266
|
+
return [(c[0] / 255) * a, (c[1] / 255) * a, (c[2] / 255) * a, a];
|
|
267
|
+
};
|
|
268
|
+
const darkF = premultiplied(dark);
|
|
269
|
+
const lightF = premultiplied(light);
|
|
270
|
+
// std140-style layout: two vec4 then a vec2, rounded up to the struct's
|
|
271
|
+
// 16-byte alignment. 48 bytes, of which the last 8 are padding.
|
|
272
|
+
const style = new Float32Array(12);
|
|
273
|
+
style.set(darkF, 0);
|
|
274
|
+
style.set(lightF, 4);
|
|
275
|
+
style[8] = source.width;
|
|
276
|
+
style[9] = source.height;
|
|
277
|
+
uniforms = device.createBuffer({
|
|
278
|
+
size: style.byteLength,
|
|
279
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
280
|
+
});
|
|
281
|
+
device.queue.writeBuffer(uniforms, 0, style);
|
|
282
|
+
const shader = device.createShaderModule({ code: SHADER });
|
|
283
|
+
if (!(await compiles(shader)))
|
|
284
|
+
return false;
|
|
285
|
+
// An error scope is the WGSL analogue of checking LINK_STATUS: a rejected
|
|
286
|
+
// pipeline is reported here instead of surfacing later as a lost device.
|
|
287
|
+
let pipeline = null;
|
|
288
|
+
if (typeof device.pushErrorScope === 'function') {
|
|
289
|
+
device.pushErrorScope('validation');
|
|
290
|
+
pipeline = device.createRenderPipeline({
|
|
291
|
+
layout: 'auto',
|
|
292
|
+
vertex: { module: shader, entryPoint: 'vertexMain' },
|
|
293
|
+
fragment: { module: shader, entryPoint: 'fragmentMain', targets: [{ format }] },
|
|
294
|
+
primitive: { topology: 'triangle-list' },
|
|
295
|
+
});
|
|
296
|
+
const failure = await device.popErrorScope();
|
|
297
|
+
if (failure)
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
pipeline = device.createRenderPipeline({
|
|
302
|
+
layout: 'auto',
|
|
303
|
+
vertex: { module: shader, entryPoint: 'vertexMain' },
|
|
304
|
+
fragment: { module: shader, entryPoint: 'fragmentMain', targets: [{ format }] },
|
|
305
|
+
primitive: { topology: 'triangle-list' },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
if (!pipeline)
|
|
309
|
+
return false;
|
|
310
|
+
const bindGroup = device.createBindGroup({
|
|
311
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
312
|
+
entries: [
|
|
313
|
+
{ binding: 0, resource: texture.createView() },
|
|
314
|
+
{ binding: 1, resource: sampler },
|
|
315
|
+
{ binding: 2, resource: { buffer: uniforms } },
|
|
316
|
+
],
|
|
317
|
+
});
|
|
318
|
+
const encoder = device.createCommandEncoder();
|
|
319
|
+
const pass = encoder.beginRenderPass({
|
|
320
|
+
colorAttachments: [{
|
|
321
|
+
view: context.getCurrentTexture().createView(),
|
|
322
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
323
|
+
loadOp: 'clear',
|
|
324
|
+
storeOp: 'store',
|
|
325
|
+
}],
|
|
326
|
+
});
|
|
327
|
+
pass.setPipeline(pipeline);
|
|
328
|
+
pass.setBindGroup(0, bindGroup);
|
|
329
|
+
pass.draw(3);
|
|
330
|
+
pass.end();
|
|
331
|
+
device.queue.submit([encoder.finish()]);
|
|
332
|
+
// Wait for the draw before the `finally` below frees its inputs, so
|
|
333
|
+
// returning true genuinely means the pixels are there.
|
|
334
|
+
if (device.queue && typeof device.queue.onSubmittedWorkDone === 'function') {
|
|
335
|
+
await device.queue.onSubmittedWorkDone();
|
|
336
|
+
}
|
|
337
|
+
return true;
|
|
321
338
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const bindGroup = device.createBindGroup({
|
|
325
|
-
layout: pipeline.getBindGroupLayout(0),
|
|
326
|
-
entries: [
|
|
327
|
-
{ binding: 0, resource: texture.createView() },
|
|
328
|
-
{ binding: 1, resource: sampler },
|
|
329
|
-
{ binding: 2, resource: { buffer: uniforms } },
|
|
330
|
-
],
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
const encoder = device.createCommandEncoder();
|
|
334
|
-
const pass = encoder.beginRenderPass({
|
|
335
|
-
colorAttachments: [{
|
|
336
|
-
view: context.getCurrentTexture().createView(),
|
|
337
|
-
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
338
|
-
loadOp: 'clear',
|
|
339
|
-
storeOp: 'store',
|
|
340
|
-
}],
|
|
341
|
-
});
|
|
342
|
-
pass.setPipeline(pipeline);
|
|
343
|
-
pass.setBindGroup(0, bindGroup);
|
|
344
|
-
pass.draw(3);
|
|
345
|
-
pass.end();
|
|
346
|
-
device.queue.submit([encoder.finish()]);
|
|
347
|
-
|
|
348
|
-
// Wait for the draw before the `finally` below frees its inputs, so
|
|
349
|
-
// returning true genuinely means the pixels are there.
|
|
350
|
-
if (device.queue && typeof device.queue.onSubmittedWorkDone === 'function') {
|
|
351
|
-
await device.queue.onSubmittedWorkDone();
|
|
339
|
+
catch {
|
|
340
|
+
return false;
|
|
352
341
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
342
|
+
finally {
|
|
343
|
+
// Release eagerly: a page generating many barcodes would otherwise hold
|
|
344
|
+
// every texture until GC caught up, and GPU memory is not GC's priority.
|
|
345
|
+
// The device itself is deliberately kept — it is shared, and destroying it
|
|
346
|
+
// would blank every canvas already configured with it.
|
|
347
|
+
try {
|
|
348
|
+
if (texture && typeof texture.destroy === 'function')
|
|
349
|
+
texture.destroy();
|
|
350
|
+
if (uniforms && typeof uniforms.destroy === 'function')
|
|
351
|
+
uniforms.destroy();
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
/* device already gone */
|
|
355
|
+
}
|
|
367
356
|
}
|
|
368
|
-
}
|
|
369
357
|
}
|