From fc544a144ba14cda691fc37fc90da6a978377b50 Mon Sep 17 00:00:00 2001 From: Knee Cola Date: Sat, 20 Dec 2025 08:49:11 +0100 Subject: [PATCH] chore: remove legacy PDF417 generation implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete custom PDF417 generator and renderer now that all components use zxing-wasm/writer. Removes Pdf417Barcode component, generateBarcode, and renderBarcode utilities. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- app/lib/pdf/pdf417.ts | 1053 ---------------------------------- app/lib/pdf/renderBarcode.ts | 51 -- app/ui/Pdf417Barcode.tsx | 29 - 3 files changed, 1133 deletions(-) delete mode 100644 app/lib/pdf/pdf417.ts delete mode 100644 app/lib/pdf/renderBarcode.ts delete mode 100644 app/ui/Pdf417Barcode.tsx diff --git a/app/lib/pdf/pdf417.ts b/app/lib/pdf/pdf417.ts deleted file mode 100644 index 95f5d40..0000000 --- a/app/lib/pdf/pdf417.ts +++ /dev/null @@ -1,1053 +0,0 @@ -import { bcadd, bcdiv, bcmul } from "./bcmath"; -import { - textsubmodes, - textlatch, - clusters, - rsfactors, - TextLatchKeys -} from "./pdf417LookupTables"; - -/** - * PDF417 - 2D Barcode generator (LGPLv3) - * - * Ported from PHP - PDF417 class, version 1.0.005, from TCPDF library (http://www.tcpdf.org/) - */ - -export interface BarcodeArray { - num_rows: number; - num_cols: number; - bcode: number[][]; -} - -const ROWHEIGHT = 4; -const QUIETH = 2; -const QUIETV = 2; -const start_pattern = "11111111010101000"; -const stop_pattern = "111111101000101001"; - -function getInputSequences(code: string): [number, string][] { - var sequence_array: [number, string][] = []; // array to be returned - var numseq: [string, number][] = []; - // get numeric sequences - var numseqMatch = code.match(/([0-9]{13,44})/g); - if (numseqMatch == null) { - numseq = []; - } else { - // add offset to each matched line - for (var n = 0, offset = 0; n < numseqMatch.length; n++) { - offset = code.indexOf(numseqMatch[n], offset); - numseq.push([numseqMatch[n], offset]); - offset += numseqMatch[n].length; - } - } - numseq.push(["", code.length]); - var offset = 0; - for (var i = 0; i < numseq.length; i++) { - var seq = numseq[i]; - var seqlen = seq[0].length; - if (seq[1] > 0) { - // extract text sequence before the number sequence - var prevseq = code.substr(offset, seq[1] - offset); - var textseq: [string, number][] = []; - // get text sequences - var textseqMatch = prevseq.match(/([\x09\x0a\x0d\x20-\x7e]{5,})/g); - if (textseqMatch == null) { - textseq = []; - } else { - // add offset to each matched line - for (var n = 0; n < textseqMatch.length; n++) { - var txtOffset = prevseq.indexOf(textseqMatch[n]); - textseq.push([textseqMatch[n], txtOffset]); - } - } - textseq.push(["", prevseq.length]); - var txtoffset = 0; - for (var j = 0; j < textseq.length; j++) { - var txtseq = textseq[j]; - var txtseqlen = txtseq[0].length; - if (txtseq[1] > 0) { - // extract byte sequence before the text sequence - var prevtxtseq = prevseq.substr(txtoffset, txtseq[1] - txtoffset); - if (prevtxtseq.length > 0) { - // add BYTE sequence - if ( - prevtxtseq.length == 1 && - sequence_array.length > 0 && - sequence_array[sequence_array.length - 1][0] == 900 - ) { - sequence_array.push([913, prevtxtseq]); - } else if (prevtxtseq.length % 6 == 0) { - sequence_array.push([924, prevtxtseq]); - } else { - sequence_array.push([901, prevtxtseq]); - } - } - } - if (txtseqlen > 0) { - // add numeric sequence - sequence_array.push([900, txtseq[0]]); - } - txtoffset = txtseq[1] + txtseqlen; - } - } - if (seqlen > 0) { - // add numeric sequence - sequence_array.push([902, seq[0]]); - } - offset = seq[1] + seqlen; - } - return sequence_array; -}; - -function getCompaction(mode: number, code: string, addmode?: boolean): number[] { - addmode = addmode ?? true; - var cw: number[] = []; // array of codewords to return - switch (mode) { - case 900: { - // Text Compaction mode latch - var submode = 0; // default Alpha sub-mode - var txtarr: number[] = []; // array of characters and sub-mode switching characters - var codelen = code.length; - for (var i = 0; i < codelen; ++i) { - var chval = _ord(code.charAt(i)); - var k: number | string | false; - if ( - (k = _array_search(chval, textsubmodes[submode])) !== - false - ) { - // we are on the same sub-mode - txtarr.push(k as number); - } else { - // the sub-mode is changed - for (var s = 0; s < 4; ++s) { - // search new sub-mode - if ( - s != submode && - (k = _array_search(chval, textsubmodes[s])) !== - false - ) { - // s is the new submode - if ( - (i + 1 == codelen || - (i + 1 < codelen && - _array_search( - _ord(code.charAt(i + 1)), - textsubmodes[submode] - ) !== false)) && - (s == 3 || (s == 0 && submode == 1)) - ) { - // shift (temporary change only for this char) - if (s == 3) { - // shift to puntuaction - txtarr.push(29); - } else { - // shift from lower to alpha - txtarr.push(27); - } - } else { - // latch - txtarr = txtarr.concat(textlatch[("" + submode + s) as TextLatchKeys]); - // set new submode - submode = s; - } - // add characted code to array - txtarr.push(k as number); - break; - } - } - } - } - var txtarrlen = txtarr.length; - if (txtarrlen % 2 != 0) { - // add padding - txtarr.push(29); - ++txtarrlen; - } - // calculate codewords - for (var i = 0; i < txtarrlen; i += 2) { - cw.push(30 * parseInt(String(txtarr[i])) + parseInt(String(txtarr[i + 1]))); - } - break; - } - case 901: - case 924: { - // Byte Compaction mode latch - var rest: string; - var sublen: number; - var codelen: number; - while ((codelen = code.length) > 0) { - if (codelen > 6) { - rest = code.substring(6); - code = code.substring(0, 6); - sublen = 6; - } else { - rest = ""; - sublen = code.length; - } - if (sublen == 6) { - var t = bcmul("" + _ord(code.charAt(0)), "1099511627776"); - t = bcadd(t, bcmul("" + _ord(code.charAt(1)), "4294967296")); - t = bcadd(t, bcmul("" + _ord(code.charAt(2)), "16777216")); - t = bcadd(t, bcmul("" + _ord(code.charAt(3)), "65536")); - t = bcadd(t, bcmul("" + _ord(code.charAt(4)), "256")); - t = bcadd(t, "" + _ord(code.charAt(5))); - // tmp array for the 6 bytes block - var cw6: number[] = []; - do { - var d = _my_bcmod(t, "900"); - t = bcdiv(t, "900"); - // prepend the value to the beginning of the array - cw6.unshift(d); - } while (t != "0"); - // append the result array at the end - cw = cw.concat(cw6); - } else { - for (var i = 0; i < sublen; ++i) { - cw.push(_ord(code.charAt(i))); - } - } - code = rest; - } - break; - } - case 902: { - // Numeric Compaction mode latch - var rest: string; - var codelen: number; - while ((codelen = code.length) > 0) { - if (codelen > 44) { - rest = code.substring(44); - code = code.substring(0, 44); - } else { - rest = ""; - } - var t = "1" + code; - do { - var d = _my_bcmod(t, "900"); - t = bcdiv(t, "900"); - cw.unshift(d); - } while (t != "0"); - code = rest; - } - break; - } - case 913: { - // Byte Compaction mode shift - cw.push(_ord(code)); - break; - } - } - if (addmode) { - // add the compaction mode codeword at the beginning - cw.unshift(mode); - } - return cw; -}; - -function getErrorCorrectionLevel(ecl: number, numcw: number): number { - // get maximum correction level - var maxecl = 8; // starting error level - var maxerrsize = 928 - numcw; // available codewords for error - while (maxecl > 0) { - var errsize = 2 << ecl; - if (maxerrsize >= errsize) { - break; - } - --maxecl; - } - // check for automatic levels - if (ecl < 0 || ecl > 8) { - if (numcw < 41) { - ecl = 2; - } else if (numcw < 161) { - ecl = 3; - } else if (numcw < 321) { - ecl = 4; - } else if (numcw < 864) { - ecl = 5; - } else { - ecl = maxecl; - } - } - if (ecl > maxecl) { - ecl = maxecl; - } - return ecl; -}; - -function getErrorCorrection(cw: number[], ecl: number): number[] { - // get error correction coefficients - var ecc = rsfactors[ecl]; - // number of error correction factors - var eclsize = 2 << ecl; - // maximum index for rsfactors[ecl] - var eclmaxid = eclsize - 1; - // initialize array of error correction codewords - var ecw = _array_fill(0, eclsize, 0) as number[]; - // for each data codeword - for (var k = 0; k < cw.length; k++) { - var t1 = (cw[k] + ecw[eclmaxid]) % 929; - for (var j = eclmaxid; j > 0; --j) { - var t2 = t1 * ecc[j] % 929; - var t3 = 929 - t2; - ecw[j] = (ecw[j - 1] + t3) % 929; - } - t2 = t1 * ecc[0] % 929; - t3 = 929 - t2; - ecw[0] = t3 % 929; - } - for (var j = 0; j < ecw.length; j++) { - if (ecw[j] != 0) { - ecw[j] = 929 - ecw[j]; - } - } - ecw = ecw.reverse(); - return ecw; -}; - -/** - * - * Functions from phpjs.org - * - */ -function _array_fill(start_index: number, num: number, mixed_val: number): number[] | Record { - var key: number, - tmp_arr: Record = {}; - - if (start_index == 0) { - var tmpArray: number[] = []; - for (var i = 0; i < num; i++) { - tmpArray.push(mixed_val); - } - return tmpArray; - } - - if (!isNaN(start_index) && !isNaN(num)) { - for (key = 0; key < num; key++) { - tmp_arr[key + start_index] = mixed_val; - } - } - - return tmp_arr; -}; - -function _str_repeat(input: string, multiplier: number): string { - // http://kevin.vanzonneveld.net - // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + improved by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) - // + improved by: Ian Carter (http://euona.com/) - // * example 1: str_repeat('-=', 10); - // * returns 1: '-=-=-=-=-=-=-=-=-=-=' - var y = ""; - while (true) { - if (multiplier & 1) { - y += input; - } - multiplier >>= 1; - if (multiplier) { - input += input; - } else { - break; - } - } - return y; -}; - -function _intval(mixed_var: any, base?: number): number { - // http://kevin.vanzonneveld.net - // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + improved by: stensi - // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Matteo - // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: Rafał Kukawski (http://kukawski.pl) - // * example 1: intval('Kevin van Zonneveld'); - // * returns 1: 0 - // * example 2: intval(4.2); - // * returns 2: 4 - // * example 3: intval(42, 8); - // * returns 3: 42 - // * example 4: intval('09'); - // * returns 4: 9 - // * example 5: intval('1e', 16); - // * returns 5: 30 - var tmp: number; - - var type = typeof mixed_var; - - if (type === "boolean") { - return +mixed_var; - } else if (type === "string") { - tmp = parseInt(mixed_var, base || 10); - return isNaN(tmp) || !isFinite(tmp) ? 0 : tmp; - } else if (type === "number" && isFinite(mixed_var)) { - return mixed_var | 0; - } else { - return 0; - } -}; - -function _sprintf(format: string, ...args: any[]): string { - // http://kevin.vanzonneveld.net - // + original by: Ash Searle (http://hexmen.com/blog/) - // + namespaced by: Michael White (http://getsprink.com) - // + tweaked by: Jack - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Paulo Freitas - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Brett Zamir (http://brett-zamir.me) - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + improved by: Dj - // + improved by: Allidylls - // * example 1: sprintf("%01.2f", 123.1); - // * returns 1: 123.10 - // * example 2: sprintf("[%10s]", 'monkey'); - // * returns 2: '[ monkey]' - // * example 3: sprintf("[%'#10s]", 'monkey'); - // * returns 3: '[####monkey]' - // * example 4: sprintf("%d", 123456789012345); - // * returns 4: '123456789012345' - var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgG])/g; - var a = [format, ...args], - i = 0; - format = a[i++]; - - // pad() - var pad = function (str: string, len: number, chr?: string, leftJustify?: boolean): string { - if (!chr) { - chr = " "; - } - var padding = str.length >= len - ? "" - : Array((1 + len - str.length) >>> 0).join(chr); - return leftJustify ? str + padding : padding + str; - }; - - // justify() - var justify = function ( - value: string, - prefix: string, - leftJustify: boolean, - minWidth: number, - zeroPad: boolean, - customPadChar?: string - ): string { - var diff = minWidth - value.length; - if (diff > 0) { - if (leftJustify || !zeroPad) { - value = pad(value, minWidth, customPadChar, leftJustify); - } else { - value = - value.slice(0, prefix.length) + - pad("", diff, "0", true) + - value.slice(prefix.length); - } - } - return value; - }; - - // formatBaseX() - var formatBaseX = function ( - value: number, - base: number, - prefix: string | boolean, - leftJustify: boolean, - minWidth: number, - precision: number, - zeroPad: boolean - ): string { - // Note: casts negative numbers to positive ones - var number = value >>> 0; - var prefixStr = - (prefix && - number && - ({ - "2": "0b", - "8": "0", - "16": "0x" - } as Record)[String(base)]) || - ""; - value = number; - var valueStr = prefixStr + pad(number.toString(base), precision || 0, "0", false); - return justify(valueStr, prefixStr, leftJustify, minWidth, zeroPad); - }; - - // formatString() - var formatString = function ( - value: string, - leftJustify: boolean, - minWidth: number, - precision: number | null, - zeroPad: boolean, - customPadChar?: string - ): string { - if (precision != null) { - value = value.slice(0, precision); - } - return justify( - value, - "", - leftJustify, - minWidth, - zeroPad, - customPadChar - ); - }; - - // doFormat() - var doFormat = function ( - substring: string, - valueIndex: string | undefined, - flags: string, - minWidth: string, - _: any, - precision: string, - type: string - ): string { - var number: number; - var prefix: string; - var method: string; - var textTransform: string; - var value: any; - - if (substring == "%%") { - return "%"; - } - - // parse flags - var leftJustify = false, - positivePrefix = "", - zeroPad = false, - prefixBaseX: string | boolean = false, - customPadChar = " "; - var flagsl = flags.length; - for (var j = 0; flags && j < flagsl; j++) { - switch (flags.charAt(j)) { - case " ": - positivePrefix = " "; - break; - case "+": - positivePrefix = "+"; - break; - case "-": - leftJustify = true; - break; - case "'": - customPadChar = flags.charAt(j + 1); - break; - case "0": - zeroPad = true; - break; - case "#": - prefixBaseX = true; - break; - } - } - - // parameters may be null, undefined, empty-string or real valued - // we want to ignore null, undefined and empty-string values - var minWidthNum = 0; - if (!minWidth) { - minWidthNum = 0; - } else if (minWidth == "*") { - minWidthNum = +a[i++]; - } else if (minWidth.charAt(0) == "*") { - minWidthNum = +a[parseInt(minWidth.slice(1, -1))]; - } else { - minWidthNum = +minWidth; - } - - // Note: undocumented perl feature: - if (minWidthNum < 0) { - minWidthNum = -minWidthNum; - leftJustify = true; - } - - if (!isFinite(minWidthNum)) { - throw new Error("sprintf: (minimum-)width must be finite"); - } - - var precisionNum: number | undefined; - if (!precision) { - precisionNum = "fFeE".indexOf(type) > -1 - ? 6 - : type == "d" ? 0 : undefined; - } else if (precision == "*") { - precisionNum = +a[i++]; - } else if (precision.charAt(0) == "*") { - precisionNum = +a[parseInt(precision.slice(1, -1))]; - } else { - precisionNum = +precision; - } - - // grab value using valueIndex if required? - value = valueIndex ? a[parseInt(valueIndex.slice(0, -1))] : a[i++]; - - switch (type) { - case "s": - return formatString( - String(value), - leftJustify, - minWidthNum, - precisionNum === undefined ? null : precisionNum, - zeroPad, - customPadChar - ); - case "c": - return formatString( - String.fromCharCode(+value), - leftJustify, - minWidthNum, - precisionNum === undefined ? null : precisionNum, - zeroPad - ); - case "b": - return formatBaseX( - value, - 2, - prefixBaseX, - leftJustify, - minWidthNum, - precisionNum || 0, - zeroPad - ); - case "o": - return formatBaseX( - value, - 8, - prefixBaseX, - leftJustify, - minWidthNum, - precisionNum || 0, - zeroPad - ); - case "x": - return formatBaseX( - value, - 16, - prefixBaseX, - leftJustify, - minWidthNum, - precisionNum || 0, - zeroPad - ); - case "X": - return formatBaseX( - value, - 16, - prefixBaseX, - leftJustify, - minWidthNum, - precisionNum || 0, - zeroPad - ).toUpperCase(); - case "u": - return formatBaseX( - value, - 10, - prefixBaseX, - leftJustify, - minWidthNum, - precisionNum || 0, - zeroPad - ); - case "i": - case "d": - number = +value || 0; - number = Math.round(number - number % 1); // Plain Math.round doesn't just truncate - prefix = number < 0 ? "-" : positivePrefix; - value = - prefix + pad(String(Math.abs(number)), precisionNum || 0, "0", false); - return justify(value, prefix, leftJustify, minWidthNum, zeroPad); - case "e": - case "E": - case "f": // Should handle locales (as per setlocale) - case "F": - case "g": - case "G": - number = +value; - prefix = number < 0 ? "-" : positivePrefix; - method = ["toExponential", "toFixed", "toPrecision"][ - "efg".indexOf(type.toLowerCase()) - ]; - textTransform = ["toString", "toUpperCase"][ - "eEfFgG".indexOf(type) % 2 - ]; - value = prefix + Math.abs(number)[method as 'toExponential' | 'toFixed' | 'toPrecision'](precisionNum); - return justify(value, prefix, leftJustify, minWidthNum, zeroPad)[ - textTransform as 'toString' | 'toUpperCase' - ](); - default: - return substring; - } - }; - - return format.replace(regex, doFormat as any); -}; - -// function _preg_split(pattern: RegExp | string, subject: string, limit?: number, flags?: string | number): (string | [string, number])[] { -// // http://kevin.vanzonneveld.net -// // + original by: Marco Marchiò -// // * example 1: preg_split(/[\s,]+/, 'hypertext language, programming'); -// // * returns 1: ['hypertext', 'language', 'programming'] -// // * example 2: preg_split('//', 'string', -1, 'PREG_SPLIT_NO_EMPTY'); -// // * returns 2: ['s', 't', 'r', 'i', 'n', 'g'] -// // * example 3: var str = 'hypertext language programming'; -// // * example 3: preg_split('/ /', str, -1, 'PREG_SPLIT_OFFSET_CAPTURE'); -// // * returns 3: [['hypertext', 0], ['language', 10], ['programming', 19]] -// // * example 4: preg_split('/( )/', '1 2 3 4 5 6 7 8', 4, 'PREG_SPLIT_DELIM_CAPTURE'); -// // * returns 4: ['1', ' ', '2', ' ', '3', ' ', '4 5 6 7 8'] -// // * example 5: preg_split('/( )/', '1 2 3 4 5 6 7 8', 4, (2 | 4)); -// // * returns 5: [['1', 0], [' ', 1], ['2', 2], [' ', 3], ['3', 4], [' ', 5], ['4 5 6 7 8', 6]] - -// limit = limit || 0; -// flags = flags || ""; // Limit and flags are optional - -// var result: RegExpExecArray | null, -// ret: (string | [string, number])[] = [], -// index = 0, -// i = 0, -// noEmpty = false, -// delim = false, -// offset = false, -// OPTS: Record = {}, -// optTemp = 0; - -// var patternRegex: RegExp; -// if (typeof pattern === 'string') { -// var regexpBody = /^\/(.*)\/\w*$/.exec(pattern)?.[1] || pattern; -// var regexpFlags = /^\/.*\/(\w*)$/.exec(pattern)?.[1] || ''; -// patternRegex = new RegExp(regexpBody, regexpFlags + (regexpFlags.indexOf("g") !== -1 ? "" : "g")); -// } else { -// var regexpBody = pattern.source; -// var regexpFlags = pattern.flags || ''; -// // Non-global regexp causes an infinite loop when executing the while, -// // so if it's not global, copy the regexp and add the "g" modifier. -// patternRegex = pattern.global -// ? pattern -// : new RegExp( -// regexpBody, -// regexpFlags + (regexpFlags.indexOf("g") !== -1 ? "" : "g") -// ); -// } - -// OPTS = { -// PREG_SPLIT_NO_EMPTY: 1, -// PREG_SPLIT_DELIM_CAPTURE: 2, -// PREG_SPLIT_OFFSET_CAPTURE: 4 -// }; -// if (typeof flags !== "number") { -// // Allow for a single string or an array of string flags -// var flagsArr = [].concat(flags as any); -// for (i = 0; i < flagsArr.length; i++) { -// // Resolve string input to bitwise e.g. 'PREG_SPLIT_OFFSET_CAPTURE' becomes 4 -// if (OPTS[flagsArr[i]]) { -// optTemp = optTemp | OPTS[flagsArr[i]]; -// } -// } -// flags = optTemp; -// } -// noEmpty = !!((flags as number) & OPTS.PREG_SPLIT_NO_EMPTY); -// delim = !!((flags as number) & OPTS.PREG_SPLIT_DELIM_CAPTURE); -// offset = !!((flags as number) & OPTS.PREG_SPLIT_OFFSET_CAPTURE); - -// var _filter = function (str: string, strindex: number): void { -// // If the match is empty and the PREG_SPLIT_NO_EMPTY flag is set don't add it -// if (noEmpty && !str.length) { -// return; -// } -// // If the PREG_SPLIT_OFFSET_CAPTURE flag is set -// // transform the match into an array and add the index at position 1 -// if (offset) { -// ret.push([str, strindex]); -// } else { -// ret.push(str); -// } -// }; -// // Special case for empty regexp -// if (!regexpBody) { -// var resultSplit = subject.split(""); -// for (i = 0; i < resultSplit.length; i++) { -// _filter(resultSplit[i], i); -// } -// return ret; -// } -// // Exec the pattern and get the result -// while ((result = patternRegex.exec(subject))) { -// // Stop if the limit is 1 -// if (limit === 1) { -// break; -// } -// // Take the correct portion of the string and filter the match -// _filter(subject.slice(index, result.index), index); -// index = result.index + result[0].length; -// // If the PREG_SPLIT_DELIM_CAPTURE flag is set, every capture match must be included in the results array -// if (delim) { -// // Convert the regexp result into a normal array -// var resarr = Array.prototype.slice.call(result); -// for (i = 1; i < resarr.length; i++) { -// if (result[i] !== undefined) { -// _filter(result[i], result.index + result[0].indexOf(result[i])); -// } -// } -// } -// limit--; -// } -// // Filter last match -// _filter(subject.slice(index, subject.length), index); -// return ret; -// }; - -function _ord(string: string): number { - return string.charCodeAt(0); -}; - -function _array_search(needle: any, haystack: any, argStrict?: boolean): string | number | false { - // http://kevin.vanzonneveld.net - // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // * example 1: array_search('zonneveld', {firstname: 'kevin', middle: 'van', surname: 'zonneveld'}); - // * returns 1: 'surname' - // * example 2: ini_set('phpjs.return_phpjs_arrays', 'on'); - // * example 2: var ordered_arr = array({3:'value'}, {2:'value'}, {'a':'value'}, {'b':'value'}); - // * example 2: var key = array_search(/val/g, ordered_arr); // or var key = ordered_arr.search(/val/g); - // * returns 2: '3' - - var strict = !!argStrict, - key: string | number = ""; - - if ( - haystack && - typeof haystack === "object" && - (haystack as any).change_key_case - ) { - // Duck-type check for our own array()-created PHPJS_Array - return (haystack as any).search(needle, argStrict); - } - if (typeof needle === "object" && (needle as RegExp).exec) { - // Duck-type for RegExp - if (!strict) { - // Let's consider case sensitive searches as strict - var needleRegex = needle as RegExp; - var flags = - "i" + - (needleRegex.global ? "g" : "") + - (needleRegex.multiline ? "m" : "") + - ((needleRegex as any).sticky ? "y" : ""); // sticky is FF only - needle = new RegExp(needleRegex.source, flags); - } - for (key in haystack) { - if ((needle as RegExp).test(haystack[key])) { - return key; - } - } - return false; - } - - for (key in haystack) { - if ( - (strict && haystack[key] === needle) || - (!strict && haystack[key] == needle) - ) { - return key; - } - } - - return false; -}; - -function _my_bcmod(x: string, y: string): number { - // how many numbers to take at once? carefull not to exceed (int) - var take = 5; - var mod = ""; - do { - var a = parseInt(mod + "" + x.substring(0, take)); - x = x.substring(take); - mod = String(a % parseInt(y)); - } while (x.length); - - return parseInt(mod); -} - -/** - * Creates a PDF417 object - * @param code (string) code to represent using PDF417 - * @param ecl (int) error correction level (0-8); default -1 = automatic correction level - * @param aspectratio (float) the width to height of the symbol (excluding quiet zones) - */ -export function generateBarcode(code: string, ecl?: number, aspectratio?: number) { - - code = unescape(encodeURIComponent(code)); // covert UTF-8 to ISO-8859-1 - ecl = ecl || -1; - aspectratio = aspectratio || 2; - if (code === "") { - throw new Error("PDF417 init: empty input code"); - } - // get the input sequence array - let sequence = getInputSequences(code); - let codewords: number[] = []; // array of code-words - for (var i = 0; i < sequence.length; i++) { - var cw = getCompaction(sequence[i][0], sequence[i][1], true); - codewords = codewords.concat(cw); - } - if (codewords[0] == 900) { - // Text Alpha is the default mode, so remove the first code - codewords.shift(); - } - // count number of codewords - var numcw = codewords.length; - if (numcw > 925) { - // reached maximum data codeword capacity - throw new Error("PDF417 init: maximum data codeword capacity exceeded"); - } - - // set error correction level - ecl = getErrorCorrectionLevel(ecl, numcw); - // number of codewords for error correction - var errsize = 2 << ecl; - // calculate number of columns (number of codewords per row) and rows - var nce = numcw + errsize + 1; - var cols = Math.round( - (Math.sqrt(4761 + 68 * aspectratio * ROWHEIGHT * nce) - 69) / 34 - ); - // adjust cols - if (cols < 1) { - cols = 1; - } else if (cols > 30) { - cols = 30; - } - var rows = Math.ceil(nce / cols); - var size = cols * rows; - // adjust rows - if (rows < 3 || rows > 90) { - if (rows < 3) { - rows = 3; - } else if (rows > 90) { - rows = 90; - } - cols = Math.ceil(size / rows); - size = cols * rows; - } - if (size > 928) { - // set dimensions to get maximum capacity - if ( - Math.abs(aspectratio - 17 * 29 / 32) < - Math.abs(aspectratio - 17 * 16 / 58) - ) { - cols = 29; - rows = 32; - } else { - cols = 16; - rows = 58; - } - size = 928; - } - // calculate padding - var pad = size - nce; - if (pad > 0) { - if (size - rows == nce) { - --rows; - size -= rows; - } else { - // add pading - codewords = codewords.concat(_array_fill(0, pad, 900) as number[]); - } - } - - // Symbol Length Descriptor (number of data codewords including Symbol Length Descriptor and pad codewords) - var sld = size - errsize; - // add symbol length description - codewords.unshift(sld); - // calculate error correction - var ecw = getErrorCorrection(codewords, ecl); - // add error correction codewords - codewords = codewords.concat(ecw); - // add horizontal quiet zones to start and stop patterns - var pstart = _str_repeat("0", QUIETH) + start_pattern; - var pstop = stop_pattern + "" + _str_repeat("0", QUIETH); - - const barcode_array: BarcodeArray = { - num_rows: rows * ROWHEIGHT + 2 * QUIETV, - num_cols: (cols + 2) * 17 + 35 + 2 * QUIETH, - bcode: [] - }; - - var empty_row: number[] = []; - // build rows for vertical quiet zone - if (QUIETV > 0) { - empty_row = _array_fill(0, barcode_array.num_cols, 0) as number[]; - for (var i = 0; i < QUIETV; ++i) { - // add vertical quiet rows - barcode_array.bcode.push(empty_row); - } - } - - var L: number = 0; - var k = 0; // codeword index - var cid = 0; // initial cluster - // for each row - for (var r = 0; r < rows; ++r) { - // row start code - var row = pstart; - switch (cid) { - case 0: { - L = 30 * _intval(r / 3) + _intval((rows - 1) / 3); - break; - } - case 1: { - L = 30 * _intval(r / 3) + ecl * 3 + (rows - 1) % 3; - break; - } - case 2: { - L = 30 * _intval(r / 3) + (cols - 1); - break; - } - } - // left row indicator - row += _sprintf("%17b", clusters[cid][L]); - // for each column - for (var c = 0; c < cols; ++c) { - row += _sprintf("%17b", clusters[cid][codewords[k]]); - ++k; - } - switch (cid) { - case 0: { - L = 30 * _intval(r / 3) + (cols - 1); - break; - } - case 1: { - L = 30 * _intval(r / 3) + _intval((rows - 1) / 3); - break; - } - case 2: { - L = 30 * _intval(r / 3) + ecl * 3 + (rows - 1) % 3; - break; - } - } - // right row indicator - row += _sprintf("%17b", clusters[cid][L]); - // row stop code - row += pstop; - // convert the string to array - const arow = row.split(''); - // duplicate row to get the desired height - for (var h = 0; h < ROWHEIGHT; ++h) { - barcode_array.bcode.push(arow.map(x => parseInt(x))); - } - ++cid; - if (cid > 2) { - cid = 0; - } - } - if (QUIETV > 0) { - for (var i = 0; i < QUIETV; ++i) { - // add vertical quiet rows - barcode_array.bcode.push(empty_row); - } - } - - return (barcode_array); -}; - - diff --git a/app/lib/pdf/renderBarcode.ts b/app/lib/pdf/renderBarcode.ts deleted file mode 100644 index f614fd6..0000000 --- a/app/lib/pdf/renderBarcode.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { BarcodeArray } from './pdf417'; - -/** - * Renders a PDF417 barcode matrix to a canvas and returns it as a data URL. - * - * This function creates an HTML canvas element, draws the barcode by iterating through - * the barcode matrix, and converts the canvas to a base64-encoded PNG data URL that - * can be used as an image source. - * - * @param barcodeMatrix - The barcode array generated by the PDF417 encoder containing - * the barcode matrix data with dimensions and binary code values - * @param blockWidth - The width in pixels of each individual barcode module (bar/space unit) - * @param blockHeight - The height in pixels of each individual barcode module (bar/space unit) - * - * @returns A data URL string (base64-encoded PNG) representing the rendered barcode image, - * suitable for use in an HTML img src attribute - * - * @example - * ```typescript - * const pdf417 = createPDF417(); - * pdf417.init("Hello World", 2, 2); - * const barcodeArray = pdf417.getBarcodeArray(); - * const dataUrl = renderBarcode(barcodeArray, 2, 4); - * // dataUrl can now be used: - * ``` - */ -export function renderBarcode(barcodeMatrix: BarcodeArray, blockWidth: number, blockHeight: number) { - - const canvas = document.createElement('canvas'); - canvas.width = barcodeMatrix.num_cols * blockWidth; - canvas.height = barcodeMatrix.num_rows * blockHeight; - const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; - - let positionY = 0; - for (let row = 0; row < barcodeMatrix.num_rows; row += 1) { - let positionX = 0; - - for (let col = 0; col < barcodeMatrix.num_cols; col += 1) { - if (barcodeMatrix.bcode[row][col] === 1) { - ctx.fillStyle = '#000'; - } else { - ctx.fillStyle = '#FFF'; - } - ctx.fillRect(positionX, positionY, blockWidth, blockHeight); - positionX += blockWidth; - } - positionY += blockHeight; - } - - return canvas.toDataURL(); -} \ No newline at end of file diff --git a/app/ui/Pdf417Barcode.tsx b/app/ui/Pdf417Barcode.tsx deleted file mode 100644 index 9a5d6b4..0000000 --- a/app/ui/Pdf417Barcode.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client'; - -import { useState, useEffect, FC } from 'react'; -import { generateBarcode } from '../lib/pdf/pdf417'; -import { renderBarcode } from '../lib/pdf/renderBarcode'; - -export const Pdf417Barcode:FC<{hub3aText:string, className?: string}> = ({hub3aText: hub3a_text, className}) => { - const [bitmapData, setBitmapData] = useState(undefined); - - useEffect(() => { - const barcodeMatrix = generateBarcode(hub3a_text); - const bitmap = renderBarcode(barcodeMatrix, 2, 2); - setBitmapData(bitmap); - }, [hub3a_text]); - - // Don't render until bitmap is generated (prevents hydration mismatch) - if (!bitmapData) { - return ( -
- -
- ); - } - - return ( - // eslint-disable-next-line @next/next/no-img-element - PDF417 Barcode - ); -} \ No newline at end of file