UNPKG

red-agate-barcode

Version:

red-agate barcode tag library.

248 lines 9.01 kB
// Copyright (c) 2017, Shellyl_N and Authors // license: ISC // https://github.com/shellyln import * as RedAgate from 'red-agate/modules/red-agate'; import { SvgCanvas } from 'red-agate-svg-canvas/modules/drawing/canvas/SvgCanvas'; import { shapePropsDefault, Shape, renderSvgCanvas, toImgTag, toElementStyle, toDataUrl, toSvg, CONTEXT_SVG_CANVAS } from 'red-agate/modules/red-agate/tags/Shape'; export const barcodeBasePropsDefault = Object.assign({}, shapePropsDefault, { fillColor: "black", font: "normal 3.5px 'OCRB'", rotation: 0, height: 6.35, quietWidth: 2.54, quietHeight: 0.66, unit: "mm", drawText: true, useRawDataAsText: false, textHeight: 3.55 }); export class BarcodeBase extends Shape { constructor(props, charactersMap) { super(Object.assign({}, barcodeBasePropsDefault, props)); this.charactersMap = charactersMap; } toImgTag() { return toImgTag(this); } toElementStyle() { return toElementStyle(this); } toDataUrl() { return toDataUrl(this); } toSvg() { return toSvg(this); } toRendered() { return RedAgate.renderAsHtml_noDefer(this); } render(contexts, children) { let canvas = this.getContext(contexts, CONTEXT_SVG_CANVAS); const contextHasCanvas = Boolean(canvas); if (!contextHasCanvas) { canvas = new SvgCanvas(); this.setContext(contexts, CONTEXT_SVG_CANVAS, canvas); super.beforeRender(contexts); } let data = this.props.data || ""; let text = this.props.text; const originalData = data; let heightData, labelText, startChar, stopChar; ({ data, heightData, labelText, startChar, stopChar } = this.encodeData(data)); const cdChar = this.calcCheckDigit(data); // tw: total width (quiet + data + start + stop + cd) // th: total height (quiet + bar + text) const { tw, th } = this.calcSymbolSize(data, startChar, stopChar, cdChar); data = `${startChar}${data}${cdChar}${stopChar}`; if (labelText !== void 0) { text = labelText; } else { if (text === void 0 || text === null) text = this.props.text; if (text === void 0 || text === null) text = originalData; } let rotation = (this.props.rotation === void 0 || this.props.rotation === null) ? 0 : Math.floor(this.props.rotation / 90) % 4; if (rotation < 0) rotation += 4; switch (rotation) { case 1: canvas.rotate(Math.PI * 1.5); canvas.translate(-tw, 0); break; case 2: canvas.rotate(Math.PI); canvas.translate(-tw, -th); break; case 3: canvas.rotate(Math.PI * 0.5); canvas.translate(0, -th); break; } if (this.props.drawText) { canvas.beginGroup(); } if (this.isHeightModulated) { this.renderHeightModulatedBarData(canvas, tw, th, data, heightData, text); } else { this.renderBarData(canvas, tw, th, data, heightData, text); } this.renderAdditional(canvas, tw, th, data, text); if (this.props.drawText) { canvas.endGroup(); canvas.beginGroup(); } if (this.props.drawText) { if (this.props.font) canvas.font = this.props.font; this.renderText(canvas, tw, th, data, text); } if (this.props.drawText) { canvas.endGroup(); } if (contextHasCanvas) { return ``; } else { super.afterRender(contexts); this.unsetContext(contexts, CONTEXT_SVG_CANVAS); const imageWidth = tw + (this.props.x || 0); const imageHeight = th + (this.props.y || 0); return renderSvgCanvas(this.props, canvas, imageWidth, imageHeight); } } // total width (quiet + data + start + stop + cd) // total height (quiet + bar + text) calcSymbolSize(data, startChar, stopChar, cdChar) { return { // total width (quiet + data + start + stop + cd) tw: 0, // total height (quiet + bar + text) th: 0 }; } calcCheckDigit(data) { return ""; } encodeData(data) { return { data, startChar: "", stopChar: "" }; } getBarSpaceWidth() { return []; } getBarSpaceHeight() { const props = this.props; return [[{ offset: 0, height: props.height }]]; } getRenderStartCoodinate(data, text) { const props = this.props; return { rx: props.quietWidth, ry: props.quietHeight }; } get isHeightModulated() { return false; } renderBarData(canvas, tw, th, data, heightData, text) { const bw = this.getBarSpaceWidth(); const vseg = this.getBarSpaceHeight(); // tslint:disable-next-line:prefer-const let { rx, ry } = this.getRenderStartCoodinate(data, text); for (let i = 0; i < data.length; i++) { const cmap = this.charactersMap.get(data[i]); if (!cmap) { throw new Error("BarcodeBase#renderBarData: character is out of range."); } const pattern = cmap.pattern; let bar = true; let dx = 0; for (let j = 0; j < pattern.length; j++) { const c = pattern[j]; switch (c) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": // "0" is character gap { const w = bw[Number.parseInt(c, 10)]; if (bar) { const ss = (heightData === void 0) ? vseg[0] : vseg[Number.parseInt(heightData[i], 10)]; for (const seg of ss) { canvas.rect(rx + dx, ry + seg.offset, w, seg.height); } } dx += w; bar = !bar; } break; case "+": bar = true; break; case "-": bar = false; break; } } rx += dx; } canvas.fill(); canvas.beginPath(); } renderHeightModulatedBarData(canvas, tw, th, data, heightData, text) { const bw = this.getBarSpaceWidth(); const w = bw[1]; const vseg = this.getBarSpaceHeight(); // tslint:disable-next-line:prefer-const let { rx, ry } = this.getRenderStartCoodinate(data, text); for (let i = 0; i < data.length; i++) { const pattern = this.charactersMap.get(data[i]).pattern; const bar = true; let dx = 0; for (let j = 0; j < pattern.length; j++) { const c = pattern[j]; switch (c) { case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": { const ss = vseg[Number.parseInt(c, 10)]; for (const seg of ss) { canvas.rect(rx + dx, ry + seg.offset, w, seg.height); } } // FALL THRU case "0": // "0" is space dx += w * 2; break; } } rx += dx; } canvas.fill(); canvas.beginPath(); } renderAdditional(canvas, tw, th, data, text) { } renderText(canvas, tw, th, data, text) { const props = this.props; canvas.textAlign = "center"; canvas.textBaseline = "alphabetic"; canvas.fillText(props.useRawDataAsText ? data : text, tw / 2, th - props.quietHeight); } } //# sourceMappingURL=BarcodeBase.js.map