UNPKG

@syncfusion/ej2-barcode-generator

Version:

Barcode generator component is a pure JavaScript library which will convert a string to Barcode and show it to the user. This supports major 1D and 2D barcodes including coda bar, code 128, QR Code.

223 lines (204 loc) 8.94 kB
import { OneDimension } from '../one-dimension'; import { EncodingResult } from '../rendering/canvas-interface'; /** * code128 used to calculate the barcode of type 128 */ export class Code128 extends OneDimension { /** * Validate the given input. * * @returns {string} Validate the given input. * @param {string} char - provide the input values . * @private */ public validateInput(char: string): string { //if (char.search('/[a-zA-Z0-9]*/') === -1) { // eslint-disable-next-line if (char.search(/^[0-9A-Za-z\-\.\ \@\$\/\+\%\!\@\#\$\%\&\*\^\(\)\_\+\=\<\>\?\{\}\[\]\~\-\Ê]+$/) === -1) { return 'Supports only 128 characters of ASCII.'; } else { return undefined; } } private getCodeValue(): number[] { const codes: number[] = [11011001100, 11001101100, 11001100110, 10010011000, 10010001100, 10001001100, 10011001000, 10011000100, 10001100100, 11001001000, 11001000100, 11000100100, 10110011100, 10011011100, 10011001110, 10111001100, 10011101100, 10011100110, 11001110010, 11001011100, 11001001110, 11011100100, 11001110100, 11101101110, 11101001100, 11100101100, 11100100110, 11101100100, 11100110100, 11100110010, 11011011000, 11011000110, 11000110110, 10100011000, 10001011000, 10001000110, 10110001000, 10001101000, 10001100010, 11010001000, 11000101000, 11000100010, 10110111000, 10110001110, 10001101110, 10111011000, 10111000110, 10001110110, 11101110110, 11010001110, 11000101110, 11011101000, 11011100010, 11011101110, 11101011000, 11101000110, 11100010110, 11101101000, 11101100010, 11100011010, 11101111010, 11001000010, 11110001010, 10100110000, 10100001100, 10010110000, 10010000110, 10000101100, 10000100110, 10110010000, 10110000100, 10011010000, 10011000010, 10000110100, 10000110010, 11000010010, 11001010000, 11110111010, 11000010100, 10001111010, 10100111100, 10010111100, 10010011110, 10111100100, 10011110100, 10011110010, 11110100100, 11110010100, 11110010010, 11011011110, 11011110110, 11110110110, 10101111000, 10100011110, 10001011110, 10111101000, 10111100010, 11110101000, 11110100010, 10111011110, 10111101110, 11101011110, 11110101110, 11010000100, 11010010000, 11010011100, 1100011101011]; return codes; } private getBytes(givenWord: string): number[] { const bytes: number[] = []; for (let i: number = 0; i < givenWord.length; i++) { bytes.push(givenWord[parseInt(i.toString(), 10)].charCodeAt(0)); } return bytes; } private appendStartStopCharacters(char: string): string { let startChararcter: string; if (this.type === 'Code128A') { startChararcter = String.fromCharCode(208); } else if (this.type === 'Code128B') { startChararcter = String.fromCharCode(209); } else if (this.type === 'Code128C') { startChararcter = String.fromCharCode(210); } return startChararcter + char; } private check128C(value: string): string { return value.match(new RegExp('^' + '(\xCF*[0-9]{2}\xCF*)' + '*'))[0]; } private check128A(value: string): string { return value.match(new RegExp('^' + '[\x00-\x5F\xC8-\xCF]' + '*'))[0]; } private check128B(value: string): string { return value.match(new RegExp('^' + '[\x20-\x7F\xC8-\xCF]' + '*'))[0]; } private clipAB(value: string, code128A: boolean): string { const ranges: string = code128A ? '[\x00-\x5F\xC8-\xCF]' : '[\x20-\x7F\xC8-\xCF]'; // eslint-disable-next-line const untilC: object = value.match(new RegExp('^(' + ranges + '+?)(([0-9]{2}){2,})([^0-9]|$)')); if (untilC) { return untilC[1] + String.fromCharCode(204) + this.clipC(value.substring(untilC[1].length)); } // eslint-disable-next-line const chars: string = value.match(new RegExp('^' + ranges + '+'))[0]; if (chars.length === value.length) { return value; } return value; } private code128Clip(): string { let newString: string; const check128C: number = this.check128C(this.value).length; if (check128C >= 2) { return newString = String.fromCharCode(210) + this.clipC(this.value); } else { const code128A: boolean = this.check128A(this.value) > this.check128B(this.value); // eslint-disable-next-line return newString = (code128A ? String.fromCharCode(208) : String.fromCharCode(209)) + this.clipAB(this.value, code128A); } } private clipC(string: string): string { const cMatch: string = this.check128C(string); const length: number = cMatch.length; if (length === string.length) { return string; } string = string.substring(length); const code128A: boolean = this.check128A(string) >= this.check128B(string); return cMatch + String.fromCharCode(code128A ? 206 : 205) + this.clipAB(string, code128A); } /** * Draw the barcode SVG.\ * * @returns {void} Draw the barcode SVG . * @param {HTMLElement} canvas - Provide the canvas element . * @private */ public draw(canvas: HTMLElement): void { this.code128(canvas); } /** * Draw the barcode SVG.\ * * @returns {void} Draw the barcode SVG . * @param {HTMLElement} canvas - Provide the canvas element . * @private */ public code128(canvas: HTMLElement): void { let givenCharacter: string = this.value; givenCharacter = this.type !== 'Code128' ? this.appendStartStopCharacters(givenCharacter) : this.code128Clip() as string; const bytes: number[] = this.getBytes(givenCharacter); const startCharacterValue: number = bytes.shift() - 105; let set: string; if (startCharacterValue === 103) { set = '0'; } else if (startCharacterValue === 104) { set = '1'; } else { set = '2'; } const encodingResult: EncodingResult = this.encodeData(bytes, 1, set); const encodedData: string = this.encode(startCharacterValue, encodingResult); const code: string[] = []; code.push(encodedData); this.calculateBarCodeAttributes(code, canvas); } private encodeData(byteValue: number[], textPosition: number, set: string): EncodingResult { if (!byteValue.length) { return { result: '', checksum: 0 }; } let nextCode: EncodingResult; let index: number; if (byteValue[0] >= 200) { index = byteValue.shift() - 105; const nextSet: string = this.swap(index); if (nextSet !== undefined) { nextCode = this.encodeData(byteValue, textPosition + 1, nextSet); } } else { index = this.correctIndex(byteValue, set); nextCode = this.encodeData(byteValue, textPosition + 1, set); } const encodingValues: string = this.getCodes(index); const weight: number = index * textPosition; return { result: encodingValues + nextCode.result, checksum: weight + nextCode.checksum }; } private swap(index: number): string { if (index === 99) { return '2'; } else if (index === 100) { return '1'; } else { return '0'; } } private encode(startIndex: number, encodingResult: EncodingResult): string { const moduloValue: number = 103; const stopvalue: number = 106; let encodeValue: string = this.getCodes(startIndex) + encodingResult.result; if (this.enableCheckSum) { encodeValue += this.getCodes((encodingResult.checksum + startIndex) % moduloValue); } encodeValue += this.getCodes(stopvalue); return encodeValue; } // Correct an index by a set and shift it from the bytes array private correctIndex(bytes: number[], set?: string): number { if (set === '0') { const charCode: number = bytes.shift(); return charCode < 32 ? charCode + 64 : charCode - 32; } else if (set === '1') { return bytes.shift() - 32; } else { return (bytes.shift() - 48) * 10 + bytes.shift() - 48; } } // Get a bar symbol by index private getCodes(index: number): string { const codes: number[] = this.getCodeValue(); return codes[parseInt(index.toString(), 10)] ? codes[parseInt(index.toString(), 10)].toString() : ''; } }