|
|
@@ -14,7 +14,10 @@ const DEFAULT_RENDER_OPTIONS = {
|
|
|
|
dpi: 203,
|
|
|
|
dpi: 203,
|
|
|
|
sourceDpi: 203,
|
|
|
|
sourceDpi: 203,
|
|
|
|
fontWidthScale: 0.82,
|
|
|
|
fontWidthScale: 0.82,
|
|
|
|
|
|
|
|
code128WidthScale: 1.42,
|
|
|
|
|
|
|
|
qrSizeScale: 0.5,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const RENDERER_VERSION = "2026-05-22-fixed-reverse-baseline";
|
|
|
|
|
|
|
|
|
|
|
|
let bwipPromise;
|
|
|
|
let bwipPromise;
|
|
|
|
|
|
|
|
|
|
|
@@ -103,6 +106,8 @@ function normalizeRenderOptions(options = {}) {
|
|
|
|
const dpi = Number(options.dpi ?? DEFAULT_RENDER_OPTIONS.dpi);
|
|
|
|
const dpi = Number(options.dpi ?? DEFAULT_RENDER_OPTIONS.dpi);
|
|
|
|
const sourceDpi = Number(options.sourceDpi ?? DEFAULT_RENDER_OPTIONS.sourceDpi);
|
|
|
|
const sourceDpi = Number(options.sourceDpi ?? DEFAULT_RENDER_OPTIONS.sourceDpi);
|
|
|
|
const fontWidthScale = Number(options.fontWidthScale ?? DEFAULT_RENDER_OPTIONS.fontWidthScale);
|
|
|
|
const fontWidthScale = Number(options.fontWidthScale ?? DEFAULT_RENDER_OPTIONS.fontWidthScale);
|
|
|
|
|
|
|
|
const code128WidthScale = Number(options.code128WidthScale ?? DEFAULT_RENDER_OPTIONS.code128WidthScale);
|
|
|
|
|
|
|
|
const qrSizeScale = Number(options.qrSizeScale ?? DEFAULT_RENDER_OPTIONS.qrSizeScale);
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
width: Number.isFinite(width) && width > 0 ? width : DEFAULT_RENDER_OPTIONS.width,
|
|
|
|
width: Number.isFinite(width) && width > 0 ? width : DEFAULT_RENDER_OPTIONS.width,
|
|
|
@@ -112,6 +117,12 @@ function normalizeRenderOptions(options = {}) {
|
|
|
|
fontWidthScale: Number.isFinite(fontWidthScale) && fontWidthScale > 0
|
|
|
|
fontWidthScale: Number.isFinite(fontWidthScale) && fontWidthScale > 0
|
|
|
|
? fontWidthScale
|
|
|
|
? fontWidthScale
|
|
|
|
: DEFAULT_RENDER_OPTIONS.fontWidthScale,
|
|
|
|
: DEFAULT_RENDER_OPTIONS.fontWidthScale,
|
|
|
|
|
|
|
|
code128WidthScale: Number.isFinite(code128WidthScale) && code128WidthScale > 0
|
|
|
|
|
|
|
|
? code128WidthScale
|
|
|
|
|
|
|
|
: DEFAULT_RENDER_OPTIONS.code128WidthScale,
|
|
|
|
|
|
|
|
qrSizeScale: Number.isFinite(qrSizeScale) && qrSizeScale > 0
|
|
|
|
|
|
|
|
? qrSizeScale
|
|
|
|
|
|
|
|
: DEFAULT_RENDER_OPTIONS.qrSizeScale,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -167,6 +178,7 @@ function createInitialState() {
|
|
|
|
font: { name: "0", orientation: "N", height: 30, width: 30 },
|
|
|
|
font: { name: "0", orientation: "N", height: 30, width: 30 },
|
|
|
|
block: null,
|
|
|
|
block: null,
|
|
|
|
fieldHex: false,
|
|
|
|
fieldHex: false,
|
|
|
|
|
|
|
|
fieldReverse: false,
|
|
|
|
barcode: null,
|
|
|
|
barcode: null,
|
|
|
|
barcodeDefaults: { moduleWidth: 2, ratio: 3, height: 10 },
|
|
|
|
barcodeDefaults: { moduleWidth: 2, ratio: 3, height: 10 },
|
|
|
|
};
|
|
|
|
};
|
|
|
@@ -194,6 +206,10 @@ function estimateGraphicHeight(operation) {
|
|
|
|
return operation.size;
|
|
|
|
return operation.size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (operation.type === "code128") {
|
|
|
|
|
|
|
|
return operation.height;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return estimateTextHeight(operation);
|
|
|
|
return estimateTextHeight(operation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -211,10 +227,12 @@ function parseZpl(zpl, renderContext) {
|
|
|
|
case "^XZ":
|
|
|
|
case "^XZ":
|
|
|
|
case "^FS":
|
|
|
|
case "^FS":
|
|
|
|
case "^CI":
|
|
|
|
case "^CI":
|
|
|
|
|
|
|
|
case "^FX":
|
|
|
|
case "^MC":
|
|
|
|
case "^MC":
|
|
|
|
if (token.code === "^FS") {
|
|
|
|
if (token.code === "^FS") {
|
|
|
|
state.block = null;
|
|
|
|
state.block = null;
|
|
|
|
state.fieldHex = false;
|
|
|
|
state.fieldHex = false;
|
|
|
|
|
|
|
|
state.fieldReverse = false;
|
|
|
|
state.barcode = null;
|
|
|
|
state.barcode = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@@ -257,6 +275,9 @@ function parseZpl(zpl, renderContext) {
|
|
|
|
case "^FH":
|
|
|
|
case "^FH":
|
|
|
|
state.fieldHex = true;
|
|
|
|
state.fieldHex = true;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "^FR":
|
|
|
|
|
|
|
|
state.fieldReverse = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case "^BY": {
|
|
|
|
case "^BY": {
|
|
|
|
const [moduleWidth, ratio, height] = splitParams(params);
|
|
|
|
const [moduleWidth, ratio, height] = splitParams(params);
|
|
|
|
state.barcodeDefaults = {
|
|
|
|
state.barcodeDefaults = {
|
|
|
@@ -275,12 +296,24 @@ function parseZpl(zpl, renderContext) {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case "^BC": {
|
|
|
|
|
|
|
|
const [, height, printText, textAbove, checkDigit] = splitParams(params);
|
|
|
|
|
|
|
|
state.barcode = {
|
|
|
|
|
|
|
|
type: "code128",
|
|
|
|
|
|
|
|
height: parseInteger(height, 120),
|
|
|
|
|
|
|
|
printText: String(printText || "Y").toUpperCase() === "Y",
|
|
|
|
|
|
|
|
textAbove: String(textAbove || "N").toUpperCase() === "Y",
|
|
|
|
|
|
|
|
checkDigit: String(checkDigit || "N").toUpperCase() === "Y",
|
|
|
|
|
|
|
|
moduleWidth: state.barcodeDefaults.moduleWidth,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
case "^FD": {
|
|
|
|
case "^FD": {
|
|
|
|
const data = decodeFieldData(params, state.fieldHex);
|
|
|
|
const data = decodeFieldData(params, state.fieldHex);
|
|
|
|
|
|
|
|
|
|
|
|
if (state.barcode && state.barcode.type === "qrcode") {
|
|
|
|
if (state.barcode && state.barcode.type === "qrcode") {
|
|
|
|
const qrText = data.replace(/^LA,/, "");
|
|
|
|
const qrText = data.replace(/^LA,/, "");
|
|
|
|
const size = Math.max(120, state.barcode.magnification * 38);
|
|
|
|
const size = Math.max(80, state.barcode.magnification * 25);
|
|
|
|
addOperation(operations, {
|
|
|
|
addOperation(operations, {
|
|
|
|
type: "qr",
|
|
|
|
type: "qr",
|
|
|
|
x: state.x,
|
|
|
|
x: state.x,
|
|
|
@@ -289,6 +322,17 @@ function parseZpl(zpl, renderContext) {
|
|
|
|
scale: state.barcode.magnification,
|
|
|
|
scale: state.barcode.magnification,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
} else if (state.barcode && state.barcode.type === "code128") {
|
|
|
|
|
|
|
|
addOperation(operations, {
|
|
|
|
|
|
|
|
type: "code128",
|
|
|
|
|
|
|
|
x: state.x,
|
|
|
|
|
|
|
|
y: state.y,
|
|
|
|
|
|
|
|
text: data.replace(/^>[:;>]?/, ""),
|
|
|
|
|
|
|
|
height: state.barcode.height,
|
|
|
|
|
|
|
|
printText: state.barcode.printText,
|
|
|
|
|
|
|
|
textAbove: state.barcode.textAbove,
|
|
|
|
|
|
|
|
moduleWidth: state.barcode.moduleWidth,
|
|
|
|
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
addOperation(operations, {
|
|
|
|
addOperation(operations, {
|
|
|
|
type: "text",
|
|
|
|
type: "text",
|
|
|
@@ -297,10 +341,12 @@ function parseZpl(zpl, renderContext) {
|
|
|
|
text: data,
|
|
|
|
text: data,
|
|
|
|
font: { ...state.font },
|
|
|
|
font: { ...state.font },
|
|
|
|
block: state.block ? { ...state.block } : null,
|
|
|
|
block: state.block ? { ...state.block } : null,
|
|
|
|
|
|
|
|
reverse: state.fieldReverse,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
state.fieldHex = false;
|
|
|
|
state.fieldHex = false;
|
|
|
|
|
|
|
|
state.fieldReverse = false;
|
|
|
|
state.block = null;
|
|
|
|
state.block = null;
|
|
|
|
state.barcode = null;
|
|
|
|
state.barcode = null;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@@ -481,11 +527,52 @@ function fillScaledText(ctx, text, x, y, font, renderContext) {
|
|
|
|
ctx.restore();
|
|
|
|
ctx.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function drawText(ctx, operation, renderContext) {
|
|
|
|
function rectanglesIntersect(a, b) {
|
|
|
|
|
|
|
|
return a.x < b.x + b.width
|
|
|
|
|
|
|
|
&& a.x + a.width > b.x
|
|
|
|
|
|
|
|
&& a.y < b.y + b.height
|
|
|
|
|
|
|
|
&& a.y + a.height > b.y;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isFilledBox(operation) {
|
|
|
|
|
|
|
|
return operation.width > 0
|
|
|
|
|
|
|
|
&& operation.height > 0
|
|
|
|
|
|
|
|
&& (operation.thickness * 2) >= Math.min(operation.width, operation.height);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function hasSolidBackground(operation, filledBoxes) {
|
|
|
|
|
|
|
|
return Boolean(findSolidBackground(operation, filledBoxes));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function findSolidBackground(operation, filledBoxes) {
|
|
|
|
|
|
|
|
const height = operation.block
|
|
|
|
|
|
|
|
? Math.max(operation.font.height, operation.font.height * operation.block.maxLines)
|
|
|
|
|
|
|
|
: operation.font.height;
|
|
|
|
|
|
|
|
const width = operation.block
|
|
|
|
|
|
|
|
? operation.block.width
|
|
|
|
|
|
|
|
: Math.max(1, operation.text.length * operation.font.width);
|
|
|
|
|
|
|
|
const textBox = {
|
|
|
|
|
|
|
|
x: operation.x,
|
|
|
|
|
|
|
|
y: operation.y,
|
|
|
|
|
|
|
|
width,
|
|
|
|
|
|
|
|
height,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return filledBoxes.find((box) => rectanglesIntersect(textBox, box));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function drawText(ctx, operation, renderContext, filledBoxes = []) {
|
|
|
|
configureTextContext(ctx, operation.font);
|
|
|
|
configureTextContext(ctx, operation.font);
|
|
|
|
|
|
|
|
const solidBackground = operation.reverse ? findSolidBackground(operation, filledBoxes) : null;
|
|
|
|
|
|
|
|
ctx.fillStyle = solidBackground ? "#FFFFFF" : "#000000";
|
|
|
|
|
|
|
|
|
|
|
|
if (!operation.block) {
|
|
|
|
if (!operation.block) {
|
|
|
|
fillScaledText(ctx, operation.text, operation.x, operation.y, operation.font, renderContext);
|
|
|
|
if (solidBackground) {
|
|
|
|
|
|
|
|
fillReverseTextInBox(ctx, operation.text, operation.x, solidBackground, operation.font, renderContext);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fillScaledText(ctx, operation.text, operation.x, operation.y, operation.font, renderContext);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.fillStyle = "#000000";
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -503,8 +590,30 @@ function drawText(ctx, operation, renderContext) {
|
|
|
|
x += Math.max(0, operation.block.width - width);
|
|
|
|
x += Math.max(0, operation.block.width - width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fillScaledText(ctx, line, x, operation.y + (index * lineHeight), operation.font, renderContext);
|
|
|
|
if (solidBackground && lines.length === 1) {
|
|
|
|
|
|
|
|
fillReverseTextInBox(ctx, line, x, solidBackground, operation.font, renderContext);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fillScaledText(ctx, line, x, operation.y + (index * lineHeight), operation.font, renderContext);
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ctx.fillStyle = "#000000";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fillReverseTextInBox(ctx, text, x, box, font, renderContext) {
|
|
|
|
|
|
|
|
ctx.save();
|
|
|
|
|
|
|
|
ctx.textBaseline = "alphabetic";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const metrics = ctx.measureText(text);
|
|
|
|
|
|
|
|
const ascent = Math.max(0, metrics.actualBoundingBoxAscent || (font.height * 0.75));
|
|
|
|
|
|
|
|
const descent = Math.max(0, metrics.actualBoundingBoxDescent || (font.height * 0.2));
|
|
|
|
|
|
|
|
const baselineY = box.y + ((box.height - ascent - descent) / 2) + ascent;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ctx.translate(x, baselineY);
|
|
|
|
|
|
|
|
ctx.scale(textScaleX(font, renderContext), 1);
|
|
|
|
|
|
|
|
ctx.fillText(text, 0, 0);
|
|
|
|
|
|
|
|
ctx.restore();
|
|
|
|
|
|
|
|
ctx.textBaseline = "top";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function drawBox(ctx, operation) {
|
|
|
|
function drawBox(ctx, operation) {
|
|
|
@@ -520,14 +629,15 @@ function drawBox(ctx, operation) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (operation.width === operation.thickness && operation.height === operation.thickness) {
|
|
|
|
if ((operation.thickness * 2) >= Math.min(operation.width, operation.height)) {
|
|
|
|
ctx.fillRect(operation.x, operation.y, operation.width, operation.height);
|
|
|
|
ctx.fillRect(operation.x, operation.y, operation.width, operation.height);
|
|
|
|
return;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctx.lineWidth = operation.thickness;
|
|
|
|
ctx.lineWidth = operation.thickness;
|
|
|
|
ctx.strokeStyle = "#000000";
|
|
|
|
ctx.strokeStyle = "#000000";
|
|
|
|
ctx.strokeRect(operation.x, operation.y, operation.width, operation.height);
|
|
|
|
ctx.strokeRect(operation.x, operation.y, operation.width, operation.height);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function drawGraphic(ctx, operation) {
|
|
|
|
function drawGraphic(ctx, operation) {
|
|
|
@@ -555,9 +665,9 @@ async function loadBwip() {
|
|
|
|
return bwipPromise;
|
|
|
|
return bwipPromise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function drawQr(ctx, operation) {
|
|
|
|
async function drawQr(ctx, operation, renderContext) {
|
|
|
|
const bwip = await loadBwip();
|
|
|
|
const bwip = await loadBwip();
|
|
|
|
const qrCanvas = createCanvas(operation.size, operation.size);
|
|
|
|
const qrCanvas = createCanvas(10, 10);
|
|
|
|
|
|
|
|
|
|
|
|
bwip.render({
|
|
|
|
bwip.render({
|
|
|
|
bcid: "qrcode",
|
|
|
|
bcid: "qrcode",
|
|
|
@@ -566,7 +676,33 @@ async function drawQr(ctx, operation) {
|
|
|
|
backgroundcolor: "FFFFFF",
|
|
|
|
backgroundcolor: "FFFFFF",
|
|
|
|
}, bwip.drawingCanvas(qrCanvas));
|
|
|
|
}, bwip.drawingCanvas(qrCanvas));
|
|
|
|
|
|
|
|
|
|
|
|
ctx.drawImage(qrCanvas, operation.x, operation.y, operation.size, operation.size);
|
|
|
|
const targetSize = Math.max(80, Math.round(qrCanvas.width * renderContext.qrSizeScale));
|
|
|
|
|
|
|
|
const availableWidth = renderContext.sourceWidthDots - operation.x;
|
|
|
|
|
|
|
|
const clippedSize = Math.max(20, Math.min(targetSize, availableWidth));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ctx.drawImage(qrCanvas, operation.x, operation.y, clippedSize, clippedSize);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function drawCode128(ctx, operation, renderContext) {
|
|
|
|
|
|
|
|
const bwip = await loadBwip();
|
|
|
|
|
|
|
|
const naturalWidth = Math.max(260, operation.text.length * operation.moduleWidth * 11);
|
|
|
|
|
|
|
|
const targetWidth = Math.round(naturalWidth * renderContext.code128WidthScale);
|
|
|
|
|
|
|
|
const targetHeight = operation.height;
|
|
|
|
|
|
|
|
const barcodeCanvas = createCanvas(targetWidth, targetHeight);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bwip.render({
|
|
|
|
|
|
|
|
bcid: "code128",
|
|
|
|
|
|
|
|
text: operation.text,
|
|
|
|
|
|
|
|
scaleX: Math.max(1, operation.moduleWidth * renderContext.code128WidthScale),
|
|
|
|
|
|
|
|
scaleY: 2,
|
|
|
|
|
|
|
|
height: Math.max(8, operation.height / 12),
|
|
|
|
|
|
|
|
includetext: operation.printText,
|
|
|
|
|
|
|
|
paddingwidth: 0,
|
|
|
|
|
|
|
|
paddingheight: 0,
|
|
|
|
|
|
|
|
textxalign: "center",
|
|
|
|
|
|
|
|
}, bwip.drawingCanvas(barcodeCanvas));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ctx.drawImage(barcodeCanvas, operation.x, operation.y, barcodeCanvas.width || targetWidth, targetHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function renderZplToCanvas(zpl, options = {}) {
|
|
|
|
async function renderZplToCanvas(zpl, options = {}) {
|
|
|
@@ -578,16 +714,26 @@ async function renderZplToCanvas(zpl, options = {}) {
|
|
|
|
ctx.fillStyle = "#FFFFFF";
|
|
|
|
ctx.fillStyle = "#FFFFFF";
|
|
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
ctx.scale(renderContext.scale, renderContext.scale);
|
|
|
|
ctx.scale(renderContext.scale, renderContext.scale);
|
|
|
|
|
|
|
|
const filledBoxes = [];
|
|
|
|
|
|
|
|
|
|
|
|
for (const operation of operations) {
|
|
|
|
for (const operation of operations) {
|
|
|
|
if (operation.type === "text") {
|
|
|
|
if (operation.type === "text") {
|
|
|
|
drawText(ctx, operation, renderContext);
|
|
|
|
drawText(ctx, operation, renderContext, filledBoxes);
|
|
|
|
} else if (operation.type === "box") {
|
|
|
|
} else if (operation.type === "box") {
|
|
|
|
drawBox(ctx, operation);
|
|
|
|
if (drawBox(ctx, operation) && isFilledBox(operation)) {
|
|
|
|
|
|
|
|
filledBoxes.push({
|
|
|
|
|
|
|
|
x: operation.x,
|
|
|
|
|
|
|
|
y: operation.y,
|
|
|
|
|
|
|
|
width: operation.width,
|
|
|
|
|
|
|
|
height: operation.height,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
} else if (operation.type === "graphic") {
|
|
|
|
} else if (operation.type === "graphic") {
|
|
|
|
drawGraphic(ctx, operation);
|
|
|
|
drawGraphic(ctx, operation);
|
|
|
|
} else if (operation.type === "qr") {
|
|
|
|
} else if (operation.type === "qr") {
|
|
|
|
await drawQr(ctx, operation);
|
|
|
|
await drawQr(ctx, operation, renderContext);
|
|
|
|
|
|
|
|
} else if (operation.type === "code128") {
|
|
|
|
|
|
|
|
await drawCode128(ctx, operation, renderContext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -632,6 +778,11 @@ function buildServer() {
|
|
|
|
bodyLimit: 5 * 1024 * 1024,
|
|
|
|
bodyLimit: 5 * 1024 * 1024,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.get("/health", async () => ({
|
|
|
|
|
|
|
|
ok: true,
|
|
|
|
|
|
|
|
rendererVersion: RENDERER_VERSION,
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
app.post("/convert", async (request, reply) => {
|
|
|
|
app.post("/convert", async (request, reply) => {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const zpl = request.body && request.body.zpl;
|
|
|
|
const zpl = request.body && request.body.zpl;
|
|
|
@@ -649,6 +800,8 @@ function buildServer() {
|
|
|
|
dpi: request.body.dpi,
|
|
|
|
dpi: request.body.dpi,
|
|
|
|
sourceDpi: request.body.sourceDpi,
|
|
|
|
sourceDpi: request.body.sourceDpi,
|
|
|
|
fontWidthScale: request.body.fontWidthScale,
|
|
|
|
fontWidthScale: request.body.fontWidthScale,
|
|
|
|
|
|
|
|
code128WidthScale: request.body.code128WidthScale,
|
|
|
|
|
|
|
|
qrSizeScale: request.body.qrSizeScale,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (warnings.length > 0) {
|
|
|
|
if (warnings.length > 0) {
|
|
|
@@ -658,6 +811,7 @@ function buildServer() {
|
|
|
|
return reply
|
|
|
|
return reply
|
|
|
|
.code(200)
|
|
|
|
.code(200)
|
|
|
|
.header("Content-Type", "application/pdf")
|
|
|
|
.header("Content-Type", "application/pdf")
|
|
|
|
|
|
|
|
.header("X-ZPL-Renderer-Version", RENDERER_VERSION)
|
|
|
|
.header("Content-Disposition", 'inline; filename="etiqueta.pdf"')
|
|
|
|
.header("Content-Disposition", 'inline; filename="etiqueta.pdf"')
|
|
|
|
.send(buffer);
|
|
|
|
.send(buffer);
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
@@ -694,4 +848,5 @@ module.exports = {
|
|
|
|
buildServer,
|
|
|
|
buildServer,
|
|
|
|
convertZplToPdf,
|
|
|
|
convertZplToPdf,
|
|
|
|
getServerConfig,
|
|
|
|
getServerConfig,
|
|
|
|
|
|
|
|
RENDERER_VERSION,
|
|
|
|
};
|
|
|
|
};
|
|
|
|