bwip-js
Version:
JavaScript barcode generator supporting over 100 types and standards.
1,555 lines (1,471 loc) • 2.27 MB
JavaScript
// 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";
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
root.bwipjs = factory();
}
}(typeof self !== 'undefined' ? self : this, function () {
// exports.js
const BWIPJS_VERSION = '4.11.1 (2026-05-28)';
// Context insensitive canvas element test.
function IsCanvas(elt) {
return elt && /HTMLCanvasElement|OffscreenCanvas/.test(Object.getPrototypeOf(elt).constructor.name);
}
// bwipjs.toCanvas(canvas, options)
// bwipjs.toCanvas(options, canvas)
//
// Uses the built-in canvas drawing.
//
// `canvas` can be an HTMLCanvasElement|OffscreenCanvas or
// an ID string or unique selector string.
// `options` are a bwip-js/BWIPP options object.
//
// This function is synchronous and throws on error.
//
// Returns the canvas element.
function ToCanvas(cvs, opts) {
if (typeof opts == 'string' || IsCanvas(opts)) {
let tmp = cvs;
cvs = opts;
opts = tmp;
}
return _ToAny(bwipp_lookup(opts.bcid), opts, cvs);
}
// Entry point for the symbol-specific exports
//
// Polymorphic internal interface
// _ToAny(encoder, string, opts) : HTMLCanvasElement
// _ToAny(encoder, HTMLCanvasElement, opts) : HTMLCanvasElement
// _ToAny(encoder, OffscreenCanvas, opts) : OffscreenCanvas
// _ToAny(encoder, opts, string) : HTMLCanvasElement
// _ToAny(encoder, opts, OffscreenCanvas) : OffscreenCanvas
// _ToAny(encoder, opts, drawing) : any
//
// 'string` can be either an `id` or query selector returning a single canvas element.
function _ToAny(encoder, opts, drawing) {
if (typeof opts == 'string') {
var canvas = document.getElementById(opts) || document.querySelector(opts);
if (!IsCanvas(canvas)) {
throw new Error('bwipjs: `' + opts + '`: not a canvas');
}
opts = drawing;
drawing = DrawingCanvas(canvas);
} else if (IsCanvas(opts)) {
var canvas = opts;
opts = drawing;
drawing = DrawingCanvas(canvas);
} else if (typeof drawing == 'string') {
var canvas = document.getElementById(drawing) || document.querySelector(drawing);
if (!IsCanvas(canvas)) {
throw new Error('bwipjs: `' + drawing + '`: not a canvas');
}
drawing = DrawingCanvas(canvas);
} else if (IsCanvas(drawing)) {
drawing = DrawingCanvas(drawing);
} else if (!drawing || typeof drawing != 'object' || !drawing.init) {
throw new Error('bwipjs: not a canvas or drawing object');
}
return _Render(encoder, opts, drawing);
}
// 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],
["max", 20],
["opt", false],
["linters", $a([])]
]); //#684
var _c = new Map([
["parts", $a([_T])],
["req", $a([$a([$a(["01"]), $a(["02"]), $a(["03"]), $a(["8006"]), $a(["8026"])])])]
]); //#686
var _e = new Map([
["cset", 'N'],