fix: render reversed fields and code128 barcodes

This commit is contained in:
Eduardo Dorado
2026-05-22 00:34:29 -03:00
parent b0ec79507d
commit ddc81d482e
+63 -1
View File
@@ -167,6 +167,7 @@ function createInitialState() {
font: { name: "0", orientation: "N", height: 30, width: 30 },
block: null,
fieldHex: false,
fieldReverse: false,
barcode: null,
barcodeDefaults: { moduleWidth: 2, ratio: 3, height: 10 },
};
@@ -194,6 +195,10 @@ function estimateGraphicHeight(operation) {
return operation.size;
}
if (operation.type === "code128") {
return operation.height;
}
return estimateTextHeight(operation);
}
@@ -211,10 +216,12 @@ function parseZpl(zpl, renderContext) {
case "^XZ":
case "^FS":
case "^CI":
case "^FX":
case "^MC":
if (token.code === "^FS") {
state.block = null;
state.fieldHex = false;
state.fieldReverse = false;
state.barcode = null;
}
break;
@@ -257,6 +264,9 @@ function parseZpl(zpl, renderContext) {
case "^FH":
state.fieldHex = true;
break;
case "^FR":
state.fieldReverse = true;
break;
case "^BY": {
const [moduleWidth, ratio, height] = splitParams(params);
state.barcodeDefaults = {
@@ -275,6 +285,18 @@ function parseZpl(zpl, renderContext) {
};
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": {
const data = decodeFieldData(params, state.fieldHex);
@@ -289,6 +311,17 @@ function parseZpl(zpl, renderContext) {
scale: state.barcode.magnification,
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 {
addOperation(operations, {
type: "text",
@@ -297,10 +330,12 @@ function parseZpl(zpl, renderContext) {
text: data,
font: { ...state.font },
block: state.block ? { ...state.block } : null,
reverse: state.fieldReverse,
});
}
state.fieldHex = false;
state.fieldReverse = false;
state.block = null;
state.barcode = null;
break;
@@ -483,9 +518,11 @@ function fillScaledText(ctx, text, x, y, font, renderContext) {
function drawText(ctx, operation, renderContext) {
configureTextContext(ctx, operation.font);
ctx.fillStyle = operation.reverse ? "#FFFFFF" : "#000000";
if (!operation.block) {
fillScaledText(ctx, operation.text, operation.x, operation.y, operation.font, renderContext);
ctx.fillStyle = "#000000";
return;
}
@@ -505,6 +542,8 @@ function drawText(ctx, operation, renderContext) {
fillScaledText(ctx, line, x, operation.y + (index * lineHeight), operation.font, renderContext);
});
ctx.fillStyle = "#000000";
}
function drawBox(ctx, operation) {
@@ -520,7 +559,7 @@ function drawBox(ctx, operation) {
return;
}
if (operation.width === operation.thickness && operation.height === operation.thickness) {
if (operation.thickness >= Math.min(operation.width, operation.height)) {
ctx.fillRect(operation.x, operation.y, operation.width, operation.height);
return;
}
@@ -569,6 +608,27 @@ async function drawQr(ctx, operation) {
ctx.drawImage(qrCanvas, operation.x, operation.y, operation.size, operation.size);
}
async function drawCode128(ctx, operation) {
const bwip = await loadBwip();
const targetWidth = Math.max(260, operation.text.length * operation.moduleWidth * 11);
const targetHeight = operation.height;
const barcodeCanvas = createCanvas(targetWidth, targetHeight);
bwip.render({
bcid: "code128",
text: operation.text,
scaleX: Math.max(1, operation.moduleWidth),
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, targetWidth, targetHeight);
}
async function renderZplToCanvas(zpl, options = {}) {
const renderContext = createRenderContext(options);
const { operations, warnings } = parseZpl(zpl, renderContext);
@@ -588,6 +648,8 @@ async function renderZplToCanvas(zpl, options = {}) {
drawGraphic(ctx, operation);
} else if (operation.type === "qr") {
await drawQr(ctx, operation);
} else if (operation.type === "code128") {
await drawCode128(ctx, operation);
}
}