fix: render reversed fields and code128 barcodes
This commit is contained in:
@@ -167,6 +167,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 +195,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 +216,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 +264,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,6 +285,18 @@ 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);
|
||||||
|
|
||||||
@@ -289,6 +311,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 +330,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;
|
||||||
@@ -483,9 +518,11 @@ function fillScaledText(ctx, text, x, y, font, renderContext) {
|
|||||||
|
|
||||||
function drawText(ctx, operation, renderContext) {
|
function drawText(ctx, operation, renderContext) {
|
||||||
configureTextContext(ctx, operation.font);
|
configureTextContext(ctx, operation.font);
|
||||||
|
ctx.fillStyle = operation.reverse ? "#FFFFFF" : "#000000";
|
||||||
|
|
||||||
if (!operation.block) {
|
if (!operation.block) {
|
||||||
fillScaledText(ctx, operation.text, operation.x, operation.y, operation.font, renderContext);
|
fillScaledText(ctx, operation.text, operation.x, operation.y, operation.font, renderContext);
|
||||||
|
ctx.fillStyle = "#000000";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,6 +542,8 @@ function drawText(ctx, operation, renderContext) {
|
|||||||
|
|
||||||
fillScaledText(ctx, line, x, operation.y + (index * lineHeight), operation.font, renderContext);
|
fillScaledText(ctx, line, x, operation.y + (index * lineHeight), operation.font, renderContext);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ctx.fillStyle = "#000000";
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawBox(ctx, operation) {
|
function drawBox(ctx, operation) {
|
||||||
@@ -520,7 +559,7 @@ function drawBox(ctx, operation) {
|
|||||||
return;
|
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);
|
ctx.fillRect(operation.x, operation.y, operation.width, operation.height);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -569,6 +608,27 @@ async function drawQr(ctx, operation) {
|
|||||||
ctx.drawImage(qrCanvas, operation.x, operation.y, operation.size, operation.size);
|
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 = {}) {
|
async function renderZplToCanvas(zpl, options = {}) {
|
||||||
const renderContext = createRenderContext(options);
|
const renderContext = createRenderContext(options);
|
||||||
const { operations, warnings } = parseZpl(zpl, renderContext);
|
const { operations, warnings } = parseZpl(zpl, renderContext);
|
||||||
@@ -588,6 +648,8 @@ async function renderZplToCanvas(zpl, options = {}) {
|
|||||||
drawGraphic(ctx, operation);
|
drawGraphic(ctx, operation);
|
||||||
} else if (operation.type === "qr") {
|
} else if (operation.type === "qr") {
|
||||||
await drawQr(ctx, operation);
|
await drawQr(ctx, operation);
|
||||||
|
} else if (operation.type === "code128") {
|
||||||
|
await drawCode128(ctx, operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user