UNPKG

bwip-js

Version:

JavaScript barcode generator supporting over 100 types and standards.

1,571 lines (1,481 loc) 2.27 MB
// This file is part of the bwip-js project available at: // // http://metafloor.github.io/bwip-js // // Copyright (c) 2011-2026 Mark Warren // // This file contains code automatically generated from: // Barcode Writer in Pure PostScript - Version 2026-05-28 // Copyright (c) 2004-2024 Terry Burton // // The MIT License // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // "use strict"; // exports.js const BWIPJS_VERSION = '4.11.1 (2026-05-28)'; var url = require('url'); var PNG_ZLIB = require('zlib'); require('stream'); // fix for https://github.com/nodejs/node/issues/37021 // bwipjs.request(req, res [, overrides]) // // Returns a PNG image from the query args of a node.js http request object. // // This function is asynchronous. function Request(req, res, extra) { try { var opts = url.parse(req.url, true).query; // Convert empty !parameters to false. // Convert empty parameters to true. for (var id in opts) { if (opts[id] === '') { if (id[0] == '!') { opts[id.substr(1)] = false; } else { opts[id] = true; } } } // Add in server options/overrides if (extra) { for (var id in extra) { opts[id] = extra[id]; } } ToBuffer(opts, function(err, png) { if (err) { res.writeHead(400, { 'Content-Type':'text/plain' }); res.end('' + err, 'utf-8'); } else { res.writeHead(200, { 'Content-Type':'image/png' }); res.end(png, 'binary'); } }); } catch (e) { res.writeHead(400, { 'Content-Type':'text/plain' }); res.end('' + e, 'utf-8'); } } // bwipjs.toBuffer(options[, callback]) // // Uses the built-in graphics drawing and zlib PNG encoding to return a // barcode image in a node.js Buffer. // // `options` are a bwip-js/BWIPP options object. // `callback` is an optional callback handler with prototype: // // function callback(err, png) // // `err` is an Error object or string. If `err` is set, `png` is null. // `png` is a node Buffer containing the PNG image. // // If `callback` is not provided, a Promise is returned. function ToBuffer(opts, callback) { return _ToAny(bwipp_lookup(opts.bcid), opts, callback); } // Entry point for the symbol-specific exports. // // Polymorphic internal interface // _ToAny(encoder, opts) : Promise<Buffer> // _ToAny(endoder, opts, drawing) : any !throws! // _ToAny(encoder, opts, callback) : void // // If `drawing` is not provided or `callback` is, the built-in DrawingZlibPng will be used. function _ToAny(encoder, opts, drawing) { var callback; if (typeof drawing == 'function') { callback = drawing; drawing = null } if (drawing) { return _Render(encoder, opts, drawing); } else if (callback) { try { _Render(encoder, opts, DrawingZlibPng(callback)); } catch (e) { callback(e); } } else { return new Promise(function (resolve, reject) { _Render(encoder, opts, DrawingZlibPng(function (err, buf) { err ? reject(err) : resolve(buf); })); }); } } // bwipjs.toSVG(options) // // Uses the built-in svg drawing interface. // // `options` are a bwip-js/BWIPP options object. // // This function is synchronous and throws on error. // // Returns a string containing a fully qualified SVG definition, // including the natural width and height of the image, in pixels: // // <svg viewBox="0 0 242 200" xmlns="http://www.w3.org/2000/svg"> // ... // </svg> // // Available on all platforms. function ToSVG(opts) { return _Render(bwipp_lookup(opts.bcid), opts, DrawingSVG()); } function FixupOptions(opts) { // Fix up scale[XY] var scale = opts.scale || 2; var scaleX = opts.scaleX || scale; var scaleY = opts.scaleY || scaleX; opts.scaleX = scaleX < 1 ? 2 : scaleX; opts.scaleY = scaleY < 1 ? opts.scaleX : scaleY; // Fix up padding. opts.paddingleft = padding(opts.paddingleft, opts.paddingwidth, opts.padding, scaleX); opts.paddingright = padding(opts.paddingright, opts.paddingwidth, opts.padding, scaleX); opts.paddingtop = padding(opts.paddingtop, opts.paddingheight, opts.padding, scaleY); opts.paddingbottom = padding(opts.paddingbottom, opts.paddingheight, opts.padding, scaleY); // We override BWIPP's background color functionality. If in CMYK, convert to RRGGBB so // the drawing interface is consistent. Likewise, if in CSS-style #rgb or #rrggbb. if (opts.backgroundcolor) { var bgc = ''+opts.backgroundcolor; if (/^[0-9a-fA-F]{8}$/.test(bgc)) { var c = parseInt(bgc.substr(0,2), 16) / 255; var m = parseInt(bgc.substr(2,2), 16) / 255; var y = parseInt(bgc.substr(4,2), 16) / 255; var k = parseInt(bgc.substr(6,2), 16) / 255; var r = Math.floor((1-c) * (1-k) * 255).toString(16); var g = Math.floor((1-m) * (1-k) * 255).toString(16); var b = Math.floor((1-y) * (1-k) * 255).toString(16); opts.backgroundcolor = (r.length == 1 ? '0' : '') + r + (g.length == 1 ? '0' : '') + g + (b.length == 1 ? '0' : '') + b; } else { if (bgc[0] == '#') { bgc = bgc.substr(1); } if (/^[0-9a-fA-F]{6}$/.test(bgc)) { opts.backgroundcolor = bgc; } else if (/^[0-9a-fA-F]{3}$/.test(bgc)) { opts.backgroundcolor = bgc[0] + bgc[0] + bgc[1] + bgc[1] + bgc[2] + bgc[2]; } else { throw new Error('bwip-js: invalid backgroundcolor: ' + opts.backgroundcolor); } } } return opts; // a is the most specific padding value, e.g. paddingleft // b is the next most specific value, e.g. paddingwidth // c is the general padding value. // s is the scale, either scalex or scaley function padding(a, b, c, s) { var p; if (a != null) { p = a|0; } else if (b != null) { p = b|0; } else { p = c|0; } // Keep the padding value reasonable p = p < 0 ? 0 : (p > 999 ? 999 : p); return p*s|0; } } var BWIPJS_OPTIONS = { bcid:1, text:1, scale:1, scaleX:1, scaleY:1, rotate:1, padding:1, paddingwidth:1, paddingheight:1, paddingtop:1, paddingleft:1, paddingright:1, paddingbottom:1, backgroundcolor:1, }; // bwipjs.render(options, drawing) // // Renders a barcode using the provided drawing object. // // This function is synchronous and throws on error. // // Browser and nodejs usage. function Render(options, drawing) { return _Render(bwipp_lookup(options.bcid), options, drawing); } // Called by the public exports function _Render(encoder, options, drawing) { var text = options.text; if (!text) { throw new ReferenceError('bwip-js: bar code text not specified.'); } // setopts() is optional on the drawing object. FixupOptions(options); drawing.setopts && drawing.setopts(options); // Set the bwip-js defaults var scaleX = options.scaleX; var scaleY = options.scaleY; var rotate = options.rotate || 'N'; // Create a barcode writer object. This is the interface between // the low-level BWIPP code, the bwip-js graphics context, and the // drawing interface. var bw = new BWIPJS(drawing); // Set the BWIPP options var bwippopts = {}; for (var id in options) { if (!BWIPJS_OPTIONS[id]) { bwippopts[id] = options[id]; } } // Fix a disconnect in the BWIPP rendering logic if (bwippopts.alttext) { bwippopts.includetext = true; } // We use mm rather than inches for height - except pharmacode2 height // which is already in mm. if (+bwippopts.height && encoder != bwipp_pharmacode2) { bwippopts.height = bwippopts.height / 25.4 || 0.5; } // Likewise, width if (+bwippopts.width) { bwippopts.width = bwippopts.width / 25.4 || 0; } // Scale the image bw.scale(scaleX, scaleY); // Call into the BWIPP cross-compiled code and render the image. bwipp_encode(bw, encoder, text, bwippopts); // Returns whatever drawing.end() returns, or `false` if nothing rendered. return bw.render(); } // bwipjs.raw(options) // bwipjs.raw(bcid, text, opts-string) // // Invokes the low level BWIPP code and returns the raw encoding data. // // This function is synchronous and throws on error. // // Browser and nodejs usage. function ToRaw(bcid, text, options) { if (arguments.length == 1) { options = bcid; bcid = options.bcid; text = options.text; } // The drawing interface is just needed for the pre-init() calls. // Don't need to fixup the drawing specific options. var drawing = DrawingBuiltin(); drawing.setopts(options); var bw = new BWIPJS(drawing); var stack = bwipp_encode(bw, bwipp_lookup(bcid), text, options, true); // bwip-js uses Maps to emulate PostScript dictionary objects; but Maps // are not a typical/expected return value. Convert to plain-old-objects. var ids = { pixs:1, pixx:1, pixy:1, sbs:1, bbs:1, bhs:1, txt:1, width:1, height:1 }; for (var i = 0; i < stack.length; i++) { var elt = stack[i]; if (elt instanceof Map) { var obj = {}; for (var keys = elt.keys(), size = elt.size, k = 0; k < size; k++) { var id = keys.next().value; if (ids[id]) { obj[id] = pod(elt.get(id)); } } stack[i] = obj; } else { // This should never exec... stack.splice(i--, 1); } } return stack; function pod(val) { if (val instanceof Array) { // The postscript arrays have extra named properties // to emulate array views. Return cleaned up arrays. val = val.b.slice(val.o, val.o + val.length); // Walk the array and convert each element for (let j = 0, l = val.length; j < l; j++) { val[j] = pod(val[j]); } } else if (val instanceof Uint8Array) { val = String.fromCharCode.apply(null, val); } return val; } } // bwip-js // Barcode Writer in Pure JavaScript // https://github.com/metafloor/bwip-js // // This code was automatically generated from: // Barcode Writer in Pure PostScript - Version 2026-05-28 // // Copyright (c) 2011-2026 Mark Warren // Copyright (c) 2004-2024 Terry Burton // // Licensed MIT. See the LICENSE file in the bwip-js root directory. // bwip-js/barcode-hdr.js // // This code is injected above the cross-compiled barcode.js. var $$ = null; // The BWIPJS object (graphics interface) var $j = 0; // stack pointer var $k = []; // operand stack var $_ = {}; // base of the dictionary stack // If you add a global variable here, add it to bwippdefs in psc.js replacing the // bwipp_ prefix with $-sign. // All globals must be referenced with $-sign prefix in the ps code. They are handled // special in the cross-compiler. var bwipp_enabledontdraw = false; // Used by the BWIPP pstests - always false in production var bwipp_error = new Map; // The postscript system error dict // Aliases from Math ops const $abs = Math.abs; const $ceil = Math.ceil; const $flr = Math.floor; const $log = Math.log; const $pow = Math.pow const $rnd = Math.round; const $sqrt = Math.sqrt; // Code instrumenting const $metrics = {}; // Array ctor // $a() : Build a new array up to the Infinity-marker on the stack. // $a(arr) : Convert native array to a "view" of the array. // $a(len) : Create a new array of length `len` function $a(a) { if (!arguments.length) { for (var i = $j - 1; i >= 0 && $k[i] !== Infinity; i--); if (i < 0) { throw new Error('array-marker-not-found'); } a = $k.splice(i + 1, $j - 1 - i); $j = i; } else if (!(a instanceof Array)) { var len = arguments[0] | 0; if (len >= 1 << 24) { throw new Error('array-size-limit'); } a = new Array(len); for (var i = 0; i < len; i++) { a[i] = null; } } a.b = a; // base array a.o = 0; // offset into base return a; } // dict ctor // $d() : look for the Infinity marker on the stack function $d() { // Build the dictionary in the order the keys/values were pushed so enumeration // occurs in the correct sequence. for (var mark = $j - 1; mark >= 0 && $k[mark] !== Infinity; mark -= 2) { if ($k[mark - 1] === Infinity) { throw new Error('dict-malformed-stack'); } } if (mark < 0) { throw new Error('dict-marker-not-found'); } var d = new Map; for (var i = mark + 1; i < $j; i += 2) { // Unlike javascript, postscript dict keys differentiate between // numbers and the string representation of a number. var k = $k[i]; // "key" into the dict entry var t = typeof k; if (t == 'number' || t == 'string') { d.set(k, $k[i + 1]); } else if (k instanceof Uint8Array) { d.set($z(k), $k[i + 1]); } else { throw new Error('dict-not-a-valid-key(' + k + ')'); } } $j = mark; return d; } // string ctor // s(number) : create zero-filled string of number-length // s(string) : make a copy of the string // s(uint8[]) : make a copy of the string // // Returns a Uint8Array-string. function $s(v) { var t = typeof v; if (t === 'number') { return new Uint8Array(v); } if (t !== 'string') { v = '' + v; } var s = new Uint8Array(v.length); for (var i = 0, l = v.length; i < l; i++) { s[i] = v.charCodeAt(i); } return s; } // ... n c roll function $r(n, c) { if ($j < n) { throw new Error('roll: --stack-underflow--'); } if (!c) { return; } if (c < 0) { var t = $k.splice($j - n, -c); } else { var t = $k.splice($j - n, n - c); } $k.splice.apply($k, [$j - t.length, 0].concat(t)); } // Primarily designed to convert uint8-string to string, but will call the // the toString() method on any value. function $z(s) { if (s instanceof Uint8Array) { return String.fromCharCode.apply(null, s); } return '' + s; } // Copies source to dest and returns a view of just the copied characters function $strcpy(dst, src) { if (typeof dst === 'string') { dst = $s(dst); } if (src instanceof Uint8Array) { for (var i = 0, l = src.length; i < l; i++) { dst[i] = src[i]; } } else { for (var i = 0, l = src.length; i < l; i++) { dst[i] = src.charCodeAt(i); } } return src.length < dst.length ? dst.subarray(0, src.length) : dst; } // Copies source to dest and should (but doesn't) return a view of just the copied elements function $arrcpy(dst, src) { for (var i = 0, l = src.length; i < l; i++) { dst[i] = src[i]; } dst.length = src.length; return dst; } // cvs operator - convert a value to its string representation // s : string to store into // v : any value function $cvs(s, v) { var t = typeof v; if (t == 'number' || t == 'boolean' || v === null) { v = '' + v; } else if (t !== 'string') { v = '--nostringval--'; } for (var i = 0, l = v.length; i < l; i++) { s[i] = v.charCodeAt(i); } return i < s.length ? s.subarray(0, i) : s; } // cvi operator - converts a numeric string value to integer/real. function $cvi(s) { if (s instanceof Uint8Array) { // nul-chars on the end of a string are ignored by postscript but cause javascript // to return a zero result. return $flr(String.fromCharCode.apply(null, s).replace(/\0+$/, '')); } return $flr('' + s); } // cvrs operator - convert a number to a radix string // s : string to store into // n : number // r : radix function $cvrs(s, n, r) { return $strcpy(s, (~~n).toString(r).toUpperCase()); } // cvx operator // BWIPP uses this to bind a function to ...args // The operand must be an array with a function as its last element. // All other elements get pushed on the stack before invoking the // function. function $cvx(a) { if (!(a instanceof Array)) { throw new Error('cvx: not arraytype'); } if (typeof a[a.length - 1] !== 'function') { throw new Error('cvx: last array element not function'); } const last = a.length - 1; return function() { for (let i = 0; i < last; i++) { $k[$j++] = a[i]; } a[last](); }; } // get operator // s : source // k : key function $get(s, k) { if (s instanceof Uint8Array) { return s[k]; } if (typeof s === 'string') { return s.charCodeAt(k); } if (s instanceof Array) { return s.b[s.o + k]; } // Map or Object - need a string key if (k instanceof Uint8Array) { k = $z(k); } if (s instanceof Map) { return s.get(k); } return s[k]; } // known operator function $has(v, k) { if (v instanceof Uint8Array) { return k < v.length; } if (typeof v === 'string') { return k < v.length; } if (v instanceof Array) { return k < v.length; } // Map or Object - need a string key if (k instanceof Uint8Array) { k = $z(k); } if (v instanceof Map) { return v.has(k); } return k in v; } // undef operator // d : dict // k : key function $del(d, k) { if (d instanceof Map) { if (k instanceof Uint8Array) { d.delete($z(k)); } else { d.delete(k); } } else if (typeof d == 'object') { if (k instanceof Uint8Array) { delete d[$z(k)]; } else { delete d[k]; } } else { throw new Error('undef-not-a-dict-' + (typeof d)); } } // put operator // d : dest // k : key // v : value function $put(d, k, v) { if (d instanceof Uint8Array) { d[k] = v; } else if (d instanceof Array) { d.b[d.o + k] = v; } else if (d instanceof Map) { if (k instanceof Uint8Array) { d.set($z(k), v); } else { d.set(k, v); } } else if (typeof d == 'object') { if (k instanceof Uint8Array) { d[$z(k)] = v; } else { d[k] = v; } } else { throw new Error('put-not-writable-' + (typeof d)); } } // getinterval operator // s : src // o : offset // l : length function $geti(s, o, l) { if (s instanceof Uint8Array) { return s.subarray(o, o + l); } if (s instanceof Array) { var a = new Array(l); a.b = s.b; // base array a.o = s.o + o; // offset into base return a; } // Must be a string return s.substr(o, l); } // putinterval operator // d : dst // o : offset // s : src function $puti(d, o, s) { if (d instanceof Uint8Array) { if (typeof s == 'string') { for (var i = 0, l = s.length; i < l; i++) { d[o + i] = s.charCodeAt(i); } } else { // When both d and s are the same, we want to copy // backwards, which works for the general case as well. for (var i = s.length - 1; i >= 0; i--) { d[o + i] = s[i]; } } } else if (d instanceof Array) { // Operate on the base arrays var darr = d.b; var doff = o + d.o; var sarr = s.b; var soff = s.o; for (var i = 0, l = s.length; i < l; i++) { darr[doff + i] = sarr[soff + i]; } } else { throw new Error('putinterval-not-writable-' + (typeof d)); } } // see rendertext function $splay() { var map = $k[--$j]; for (var keys = map.keys(), i = 0, l = map.size; i < l; i++) { var id = keys.next().value; if (id && typeof id === 'string') { $_[id] = map.get(id); } } } // type operator function $type(v) { // null can be mis-typed - get it out of the way if (v == null) { return 'nulltype'; } var t = typeof v; if (t == 'number') { if (isFinite(v)) { return v % 1 ? 'realtype' : 'integertype'; } return 'marktype'; } if (t == 'boolean') { return 'booleantype'; } if (t == 'string' || v instanceof Uint8Array) { return 'stringtype'; } if (t == 'function') { return 'operatortype'; } if (v instanceof Array) { return 'arraytype'; } return 'dicttype'; // filetype // fonttype // gstatetype // nametype // savetype } // anchorsearch operator // string seek anchorsearch suffix seek true %if-found // string false %if-not-found function $anchorsearch(str, seek) { if (!(str instanceof Uint8Array)) { str = $s(str); } var i = 0, ls = str.length, lk = seek.length; // Optimize for single characters. if (lk == 1) { var cd = seek instanceof Uint8Array ? seek[0] : seek.charCodeAt(0); i = str[0] == cd ? 1 : ls; } else if (seek.length <= ls) { // Slow path, if (!(seek instanceof Uint8Array)) { seek = $s(seek); } for (; i < lk && str[i] == seek[i]; i++); } if (i == lk) { $k[$j++] = str.subarray(lk); $k[$j++] = str.subarray(0, lk); $k[$j++] = true; } else { $k[$j++] = str; $k[$j++] = false; } } // search operator // string seek search suffix match prefix true %if-found // string false %if-not-found function $search(str, seek) { if (!(str instanceof Uint8Array)) { str = $s(str); } var ls = str.length; // Virtually all uses of search in BWIPP are for single-characters. // Optimize for that case. if (seek.length == 1) { var lk = 1; var cd = seek instanceof Uint8Array ? seek[0] : seek.charCodeAt(0); for (var i = 0; i < ls && str[i] != cd; i++); } else { // Slow path, if (!(seek instanceof Uint8Array)) { seek = $s(seek); } var lk = seek.length; var cd = seek[0]; for (var i = 0; i < ls && str[i] != cd; i++); while (i < ls) { for (var j = 1; j < lk && str[i + j] === seek[j]; j++); if (j === lk) { break; } for (i++; i < ls && str[i] != cd; i++); } } if (i < ls) { $k[$j++] = str.subarray(i + lk); $k[$j++] = str.subarray(i, i + lk); $k[$j++] = str.subarray(0, i); $k[$j++] = true; } else { $k[$j++] = str; $k[$j++] = false; } } // The callback is omitted when forall is being used just to push onto the // stack. The callback normally returns undefined. A return of true means break. function $forall(o, cb) { if (o instanceof Uint8Array) { for (var i = 0, l = o.length; i < l; i++) { $k[$j++] = o[i]; if (cb && cb()) break; } } else if (o instanceof Array) { // The array may be a view. for (var a = o.b, i = o.o, l = o.o + o.length; i < l; i++) { $k[$j++] = a[i]; if (cb && cb()) break; } } else if (typeof o === 'string') { for (var i = 0, l = o.length; i < l; i++) { $k[$j++] = o.charCodeAt(i); if (cb && cb()) break; } } else if (o instanceof Map) { for (var keys = o.keys(), i = 0, l = o.size; i < l; i++) { var id = keys.next().value; $k[$j++] = id; $k[$j++] = o.get(id); if (cb && cb()) break; } } else { for (var id in o) { $k[$j++] = id; $k[$j++] = o[id]; if (cb && cb()) break; } } } function $cleartomark() { while ($j > 0 && $k[--$j] !== Infinity); } function $counttomark() { for (var i = $j - 1; i >= 0 && $k[i] !== Infinity; i--); return $j - i - 1; } function $aload(a) { for (var i = 0, l = a.length, b = a.b, o = a.o; i < l; i++) { $k[$j++] = b[o + i]; } // This push has been optimized out. See $.aload() in psc.js. //$k[$j++] = a; } function $astore(a) { for (var i = 0, l = a.length, b = a.b, o = a.o + l - 1; i < l; i++) { b[o - i] = $k[--$j]; } $k[$j++] = a; } function $eq(a, b) { if (typeof a === 'string' && typeof b === 'string') { return a == b; } if (a instanceof Uint8Array && b instanceof Uint8Array) { if (a.length != b.length) { return false; } for (var i = 0, l = a.length; i < l; i++) { if (a[i] != b[i]) { return false; } } return true; } if (a instanceof Uint8Array && typeof b === 'string' || b instanceof Uint8Array && typeof a === 'string') { if (a instanceof Uint8Array) { a = $z(a); } else { b = $z(b); } return a == b; } return a == b; } function $ne(a, b) { return !$eq(a, b); } function $lt(a, b) { if (a instanceof Uint8Array) { a = $z(a); } if (b instanceof Uint8Array) { b = $z(b); } return a < b; } function $le(a, b) { if (a instanceof Uint8Array) { a = $z(a); } if (b instanceof Uint8Array) { b = $z(b); } return a <= b; } function $gt(a, b) { if (a instanceof Uint8Array) { a = $z(a); } if (b instanceof Uint8Array) { b = $z(b); } return a > b; } function $ge(a, b) { if (a instanceof Uint8Array) { a = $z(a); } if (b instanceof Uint8Array) { b = $z(b); } return a >= b; } function $an(a, b) { // and return (typeof a === 'boolean') ? a && b : a & b; } function $or(a, b) { // or return (typeof a === 'boolean') ? a || b : a | b; } function $xo(a, b) { // xor return (typeof a === 'boolean') ? a != b : a ^ b; } function $nt(a) { return typeof a == 'boolean' ? !a : ~a; } function $bs(v, n) { // 64-bit shifts return n < 0 ? $flr(v / $pow(2, -n)) : v * $pow(2, n); } // emulate single-precision floating-point. This is not Math.fround(). // More like ffloor()... var $f = (function(fa) { return (v) => { //return Number.isInteger(v) ? v : (fa[0] = v, fa[0]); return (v | 0) == v ? v : (fa[0] = v, fa[0]); }; })(new Float32Array(1)); // This is a replacement for the BWIPP raiseerror function. function bwipp_raiseerror() { var info = $k[--$j]; var name = $k[--$j]; bwipp_error.set('errorname', name); bwipp_error.set('errorinfo', info); if (typeof info == 'string' || info instanceof Uint8Array) { throw new Error($z(name) + ": " + $z(info)); } else { throw $z(name); } } // This list was taken from BWIPP 2026-03-31 const _textOptions = new Map([ ['', ""], ['subspace', ""], ['split', ""], ['linegaps', 1.2], ['color', "unset"], ['xalign', "left"], ['yalign', "above"], ['direction', "forward"], ['font', "OCR-B"], ['size', 10.0], ['xoffset', 0.0], ['yoffset', 0.0], ['gaps', 0.0], ]); // processoptions.generate // The BWIPP code uses currentdict as a user dict, which we do not support. // It also pulls in render.groupoptions which is not visible due to the // code transforms. function bwipp_inittextoptions() { for (var grp = 1; grp <= 9; grp++) { var map = _textOptions; for (var keys = map.keys(), i = 0, l = map.size; i < l; i++) { var id = keys.next().value; $_['text' + grp + id] = map.get(id); } } } // processoptions.collectgroup function bwipp_grouptextoptions() { var a = $a(9); var map = _textOptions; for (var grp = 1; grp <= 9; grp++) { var dict = new Map; var pfx = 'text' + grp; for (var keys = map.keys(), i = 0, l = map.size; i < l; i++) { var id = keys.next().value; dict.set(id, $_[pfx + id]); } $put(a, grp - 1, dict); } $k[$j++] = a; } // This list was taken from BWIPP 2026-03-31 const _textAliases = { alttext: 'text1', alttextsubspace: 'text1subspace', alttextsplit: 'text1split', textsubspace: 'text1subspace', textsplit: 'text1split', textlinegaps: 'text1linegaps', textcolor: 'text1color', textxalign: 'text1xalign', textyalign: 'text1yalign', textdirection: 'text1direction', textfont: 'text1font', textsize: 'text1size', textxoffset: 'text1xoffset', textyoffset: 'text1yoffset', textgaps: 'text1gaps', extratext: 'text2', extratextsubspace: 'text2subspace', extratextsplit: 'text2split', extratextlinegaps: 'text2linegaps', extratextcolor: 'text2color', extratextxalign: 'text2xalign', extratextyalign: 'text2yalign', extratextdirection: 'text2direction', extratextfont: 'text2font', extratextsize: 'text2size', extratextxoffset: 'text2xoffset', extratextyoffset: 'text2yoffset', extratextgaps: 'text2gaps', }; // This is a replacement for the BWIPP processoptions function. // We cannot use the BWIPP version for several reasons: // - legacy code allows strings to be numbers and numbers to be strings // - in javascript, there is no way to tell the difference between a real // number that is an integer, and an actual integer. // - (alt|extra)text must be uint8array due to the bwipp option // (alt|extra)subspace, which requires the text to be writable. // // Invoked as: // options supaliases //processoptions exec -> options // // supaliases is often null function bwipp_processoptions() { var sups = $k[--$j]; var opts = $k[$j - 1]; if (opts instanceof Uint8Array) { opts = $z(opts); } if (typeof opts === 'string') { let vals = opts.trim().split(/ +/g) $k[$j - 1] = opts = new Map(); for (let i = 0; i < vals.length; i++) { let pair = vals[i].split('='); if (pair.length === 1) { opts.set(pair[0], true); } else { opts.set(pair[0], pair[1]); } } } // BWIPP does not raiseerror on these (text1* and text2* override alttext* and extratext*) if (opts.has('alttext') && opts.has('text1')) { throw new Error('bwipp.invalidTextOptions: alttext and text1 are mutually exclusive'); } if (opts.has('extratext') && opts.has('text2')) { throw new Error('bwipp.invalidTextOptions: extratext and text2 are mutually exclusive'); } // alttext* -> text1*, extratext* -> text2* for (var keys = opts.keys(), i = 0, l = opts.size; i < l; i++) { var id = keys.next().value; if (sups && sups[id]) { opts.set(sups[id], opts.get(id)); } else if (_textAliases[id]) { opts.set(_textAliases[id], opts.get(id)); if (/^(?:alt|extra)text/.test(id)) { opts.delete(id); } } } for (var id in $_) { if (!opts.has(id)) { continue; } var val = opts.get(id); var def = $_[id]; var typ = typeof def; // null is a placeholder for realtype if (def === null || typ == 'number') { // Allow numeric strings to be numbers if (!isFinite(+val)) { throw new Error('bwipp.invalidOptionType: ' + id + ': not a realtype: ' + val); } if (typeof val == 'string') { val = +val; opts.set(id, val); } } else if (typ == 'boolean') { if (val !== true && val !== false) { // In keeping with the ethos of javascript, allow a more relaxed // interpretation of boolean. if (val == null || (val | 0) === val) { val = !!val; } else if (val === 'true') { val = true; } else if (val === 'false') { val = false; } else { throw new Error('bwipp.invalidOptionType: ' + id + ': not a booleantype: ' + val); } opts.set(id, val); } } else if (typ == 'string' || def instanceof Uint8Array) { // Allow numbers to be strings if (typeof val == 'number') { val = '' + val; opts.set(id, val); } else if (/^text\d$/.test(id) && typeof val === 'string') { // BWIPP 2025-06-13 introduced textsubspace which allows replacing // a marker character with space. This requires the text to be a // uint8array otherwise we get // Error: put-not-writable-string val = $s(val); opts.set(id, val); } else if (typeof val != 'string' && !(val instanceof Uint8Array)) { throw new Error('bwipp.invalidOptionType: ' + id + ': not a stringtype: ' + val); } } else if (Object.prototype.toString.call(val) !== Object.prototype.toString.call(def)) { var m = /\[object (\w+)\]/.exec(Object.prototype.toString.call(def)) || [, 'unknown']; throw new Error('bwipp.invalidOptionType: ' + id + ': expected ' + m[1].toLowerCase() + 'type'); } // Set the option into the dictionary $_[id] = val; } } // Replacement for fifocache constructor. We can't use the postscript version // because it creates a user defined dict << ... >>> and fetch installs it as // the current dictionary... // /fifocache { // 8 dict begin // // /limit exch def // /max exch def // /cache max dict def // /fifo max array def // /state << /head 0 /cnt 0 /total 0 >> def // /fetch currentdict [ // exch { //fifocache.fetch exec } aload pop // ] cvx def // // currentdict % Leave this on the stack // end // } bind def function bwipp_fifocache() { var limit = $k[--$j]; var max = $k[--$j]; var dict = { limit: limit, max: max, cache: new Map(), fifo: [], state: { head: 0, cnt: 0, total: 0 }, fetch() { $k[$j++] = dict; bwipp_fifocache_fetch(); }, }; $k[$j++] = dict; } function bwipp_fifocache_fetch() { var self = $k[--$j]; var cardfn = $k[--$j]; var genfn = $k[--$j]; var key = $k[--$j]; if (key instanceof Uint8Array) { key = String.fromCharCode.apply(null, key); } var cache = self.cache; if (cache.has(key)) { $k[$j++] = cache.get(key); return; } var fifo = self.fifo; var max = self.max; var limit = self.limit; genfn(); var result = $k[$j - 1]; cardfn(); var card = $k[--$j]; var state = self.state; // { head:0, cnt:0, total:0 } if (card < limit) { for (;;) { if (state.total + card <= limit && state.cnt < max) { break; } var oldkey = fifo[state.head]; $k[$j++] = cache.get(oldkey); cardfn(); state.total = state.total - $k[--$j]; cache.delete(oldkey); state.head = (state.head + 1) % max; state.cnt--; } cache.set(key, result); fifo[(state.head + state.cnt) % max] = key; state.cnt++; state.total = state.total + card; } $k[$j++] = result; } function bwipp_parseinput() { if (!bwipp_parseinput.globals) { var $__ = $_; $_ = bwipp_parseinput.globals = {}; //#413 $k[$j++] = Infinity; //#425 var _0 = $a(['NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL', 'BS', 'TAB', 'LF', 'VT', 'FF', 'CR', "", "", 'DLE', 'DC1', 'DC2', 'DC3', 'DC4', 'NAK', 'SYN', 'ETB', 'CAN', 'EM', 'SUB', 'ESC', 'FS', 'GS', 'RS', 'US']); //#430 $k[$j++] = 0; //#434 for (var _1 = 0, _2 = _0.length; _1 < _2; _1++) { //#434 var _4 = $k[--$j]; //#433 $k[$j++] = $get(_0, _1); //#433 $k[$j++] = _4; //#433 $k[$j++] = _4 + 1; //#433 } //#433 $j--; //#434 $_.ctrl = $d(); //#434 $_ = $__; } //#451 var $__ = $_; //#453 $_ = Object.assign({}, $_, bwipp_parseinput.globals); //#453 var _5 = $k[--$j]; //#456 $_.fncvals = _5; //#456 var _6 = $k[--$j]; //#457 $_.barcode = _6; //#457 $_.parse = $get($_.fncvals, 'parse'); //#459 $del($_.fncvals, 'parse') //#459 $_.parsefnc = $get($_.fncvals, 'parsefnc'); //#460 $del($_.fncvals, 'parsefnc') //#460 $_.parseonly = $has($_.fncvals, 'parseonly'); //#461 $del($_.fncvals, 'parseonly') //#461 $_.eci = $has($_.fncvals, 'eci'); //#462 $del($_.fncvals, 'eci') //#462 $_.msg = $a($_.barcode.length); //#466 $_.j = 0; //#467 $k[$j++] = $_.barcode; //#590 for (;;) { //#590 var _M = $k[--$j]; //#469 $search(_M, "^"); //#469 var _N = $k[--$j]; //#469 var _O = $k[--$j]; //#469 var _X = _O.length; //#472 var _V = $_.msg; //#472 var _U = $_.j; //#472 $k[$j++] = Infinity; //#472 $forall(_O); //#472 var _T = $a(); //#472 $puti(_V, _U, _T); //#472 $_.j = $f(_X + $_.j) //#473 if (_N) { //#588 $j--; //#475 for (var _Z = 0; _Z < 1; _Z++) { //#586 if (!$_.parse && !$_.parsefnc) { //#482 $put($_.msg, $_.j, 94); //#479 $_.j = $_.j + 1; //#480 break; //#481 } //#481 $put($_.msg, $_.j, 94); //#485 $_.j = $_.j + 1; //#486 if ($_.parse) { //#529 var _j = $k[$j - 1]; //#490 if (_j.length >= 3) { //#501 var _k = $k[$j - 1]; //#491 var _l = $geti(_k, 0, 3); //#491 var _m = $_.ctrl; //#491 var _n = $has(_m, _l); //#492 $k[$j++] = _m; //#500 $k[$j++] = _l; //#500 if (_n) { //#499 $_.j = $_.j - 1; //#493 var _p = $k[--$j]; //#494 var _q = $k[--$j]; //#494 $put($_.msg, $_.j, $get(_q, _p)); //#494 $_.j = $_.j + 1; //#495 var _v = $k[--$j]; //#496 $k[$j++] = $geti(_v, 3, _v.length - 3); //#497 break; //#497 } else { //#499 $j -= 2; //#499 } //#499 } //#499 var _x = $k[$j - 1]; //#502 if (_x.length >= 2) { //#513 var _y = $k[$j - 1]; //#503 var _z = $geti(_y, 0, 2); //#503 var _10 = $_.ctrl; //#503 var _11 = $has(_10, _z); //#504 $k[$j++] = _10; //#512 $k[$j++] = _z; //#512 if (_11) { //#511 $_.j = $_.j - 1; //#505 var _13 = $k[--$j]; //#506 var _14 = $k[--$j]; //#506 $put($_.msg, $_.j, $get(_14, _13)); //#506 $_.j = $_.j + 1; //#507 var _19 = $k[--$j]; //#508 $k[$j++] = $geti(_19, 2, _19.length - 2); //#509 break; //#509 } else { //#511 $j -= 2; //#511 } //#511 } //#511 var _1B = $k[$j - 1]; //#514 if (_1B.length >= 3) { //#528 var _1C = $k[$j - 1]; //#515 var _1D = $geti(_1C, 0, 3); //#515 $k[$j++] = true; //#517 for (var _1E = 0, _1F = _1D.length; _1E < _1F; _1E++) { //#517 var _1G = $get(_1D, _1E); //#517 if ((_1G < 48) || (_1G > 57)) { //#516 $k[$j - 1] = false; //#516 } //#516 } //#516 var _1H = $k[--$j]; //#527 if (_1H) { //#527 var _1I = $k[$j - 1]; //#519 var _1K = $cvi($geti(_1I, 0, 3)); //#519 $k[$j++] = _1K; //#522 if (_1K > 255) { //#522 $j -= 2; //#520 $k[$j++] = "bwipp.invalidOrdinal#521"; //#521 $k[$j++] = "Ordinal must be 000 to 255"; //#521 bwipp_raiseerror(); //#521 } //#521 $_.j = $_.j - 1; //#523 var _1N = $k[--$j]; //#524 $put($_.msg, $_.j, _1N); //#524 $_.j = $_.j + 1; //#525 var _1Q = $k[--$j]; //#526 $k[$j++] = $geti(_1Q, 3, _1Q.length - 3); //#526 } //#526 } //#526 } //#526 if ($_.parseonly || !$_.parsefnc || $get($_.msg, $_.j - 1) != 94) { //#534 break; //#534 } //#534 $_.j = $_.j - 1; //#537 var _1Y = $k[$j - 1]; //#538 if (_1Y.length < 1) { //#541 $k[$j - 1] = "bwipp.truncatedCaret#540"; //#540 $k[$j++] = "Caret character truncated"; //#540 bwipp_raiseerror(); //#540 } //#540 var _1Z = $k[$j - 1]; //#542 if ($get(_1Z, 0) == 94) { //#547 $put($_.msg, $_.j, 94); //#543 $_.j = $_.j + 1; //#544 var _1e = $k[--$j]; //#545 $k[$j++] = $geti(_1e, 1, _1e.length - 1); //#546 break; //#546 } //#546 var _1g = $k[$j - 1]; //#548 if (_1g.length < 3) { //#551 $k[$j - 1] = "bwipp.truncatedFNC#550"; //#550 $k[$j++] = "Function character truncated"; //#550 bwipp_raiseerror(); //#550 } //#550 var _1h = $k[$j - 1]; //#552 if ($eq($geti(_1h, 0, 3), "ECI") && $_.eci) { //#569 var _1k = $k[$j - 1]; //#553 if (_1k.length < 9) { //#556 $k[$j - 1] = "bwipp.truncatedECI#555"; //#555 $k[$j++] = "ECI truncated"; //#555 bwipp_raiseerror(); //#555 } //#555 var _1l = $k[$j - 1]; //#557 var _1m = $geti(_1l, 3, 6); //#557 $k[$j++] = _1m; //#563 for (var _1n = 0, _1o = _1m.length; _1n < _1o; _1n++) { //#563 var _1p = $get(_1m, _1n); //#563 if ((_1p < 48) || (_1p > 57)) { //#562 $j -= 2; //#560 $k[$j++] = "bwipp.invalidECI#561"; //#561 $k[$j++] = "ECI must be 000000 to 999999"; //#561 bwipp_raiseerror(); //#561 } //#561 } //#561 var _1q = $k[--$j]; //#564 var _1t = 0; //#564 $forall(_1q, function() { //#564 var _1r = $k[--$j]; //#564 _1t = $f(_1t - (_1r - 48)) * 10 //#564 }); //#564 $put($_.msg, $_.j, (~~(_1t / 10)) - 1000000); //#565 $_.j = $_.j + 1; //#566 var _1x = $k[--$j]; //#567 $k[$j++] = $geti(_1x, 9, _1x.length - 9); //#568 break; //#568 } //#568 var _1z = $k[$j - 1]; //#570 if (_1z.length < 4) { //#573 $k[$j - 1] = "bwipp.truncatedFNC#572"; //#572 $k[$j++] = "Function character truncated"; //#572 bwipp_raiseerror(); //#572 } //#572 var _20 = $k[$j - 1]; //#574 var _21 = $geti(_20, 0, 4); //#574 var _23 = $has($_.fncvals, _21); //#574 $k[$j++] = _21; //#579 if (!_23) { //#579 var _24 = $k[--$j]; //#575 var _25 = $s(_24.length + 28); //#575 $puti(_25, 28, _24); //#575 $puti(_25, 0, "Unknown function character: "); //#576 $k[$j - 1] = "bwipp.unknownFNC#578"; //#578 $k[$j++] = _25; //#578 bwipp_raiseerror(); //#578 } //#578 var _29 = $k[--$j]; //#580 $put($_.msg, $_.j, $get($_.fncvals, _29)); //#581 $_.j = $_.j + 1; //#582 var _2E = $k[--$j]; //#583 $k[$j++] = $geti(_2E, 4, _2E.length - 4); //#584 break; //#584 } //#584 } else { //#588 break; //#588 } //#588 } //#588 if (!$_.parseonly) { //#596 $k[$j++] = $geti($_.msg, 0, $_.j); //#593 } else { //#596 $k[$j++] = $s($_.j); //#596 for (var _2O = 0, _2N = $_.j - 1; _2O <= _2N; _2O += 1) { //#596 var _2P = $k[$j - 1]; //#596 $put(_2P, _2O, $get($_.msg, _2O)); //#596 } //#596 } //#596 $_ = $__; //#600 } //bwipp_parseinput function bwipp_gs1process() { if (!bwipp_gs1process.globals) { var $__ = $_; $_ = bwipp_gs1process.globals = {}; //#623 $_.gs1process_primes = $a([2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83]); //#625 $_.gs1process_daysinmonth = $a([31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]); //#630 var _3 = new Map([ ["cset", 'N'], ["min", 18], ["max", 18], ["opt", false], ["linters", $a(['lintcsum', 'lintgcppos2'])] ]); //#645 var _6 = new Map([ ["parts", $a([_3])], ["dlpkey", $a([])] ]); //#647 var _8 = new Map([ ["cset", 'N'], ["min", 14], ["max", 14], ["opt", false], ["linters", $a(['lintcsum', 'lintgcppos2'])] ]); //#654 var _E = new Map([ ["parts", $a([_8])], ["ex", $a(["255", "37"])], ["dlpkey", $a([$a(["22", "10", "21"]), $a(["235"])])] ]); //#657 var _G = new Map([ ["cset", 'N'], ["min", 14], ["max", 14], ["opt", false], ["linters", $a(['lintcsum', 'lintgcppos2'])] ]); //#664 var _M = new Map([ ["parts", $a([_G])], ["ex", $a(["01", "03"])], ["req", $a([$a([$a(["37"])])])] ]); //#667 var _O = new Map([ ["cset", 'N'], ["min", 14], ["max", 14], ["opt", false], ["linters", $a(['lintcsum', 'lintgcppos2'])] ]); //#674 var _R = new Map([ ["parts", $a([_O])], ["ex", $a(["01", "02", "37"])], ["dlattr", false] ]); //#677 var _T = new Map([ ["cset", 'X'], ["min", 1],