feat: increase font scaling and add inline product name rendering for improved thermal printer legibility

This commit is contained in:
Suherdy Yacob 2026-06-01 14:54:05 +07:00
parent 71b7461f41
commit e667ef3bac

View File

@ -41,7 +41,7 @@ export class HtmlToImageConverter {
clone.style.backgroundColor = 'white';
clone.style.color = 'black';
clone.style.fontFamily = 'monospace, Courier, "Courier New"';
clone.style.fontSize = '12px';
clone.style.fontSize = '15px';
clone.style.lineHeight = '1.4';
// Create a temporary container to measure height
@ -113,15 +113,15 @@ export class HtmlToImageConverter {
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = 'black';
ctx.textBaseline = 'top';
ctx.font = '12px monospace';
ctx.font = '16px monospace';
const padding = 10;
const lineHeight = 16;
const maxWidth = width - (padding * 2);
let y = padding;
// Helper function to wrap text
const wrapText = (text, maxWidth) => {
const wrapText = (text, maxWidth, fontSize) => {
ctx.font = `${ctx.font.includes('bold') ? 'bold' : 'normal'} ${fontSize}px monospace`;
const words = text.split(' ');
const lines = [];
let currentLine = '';
@ -146,11 +146,12 @@ export class HtmlToImageConverter {
};
// Helper to draw text with alignment
const drawText = (text, align = 'left', bold = false) => {
const drawText = (text, align = 'left', bold = false, fontSize = 16) => {
if (!text || !text.trim()) return;
ctx.font = `${bold ? 'bold' : 'normal'} 12px monospace`;
const lines = wrapText(text, maxWidth);
ctx.font = `${bold ? 'bold' : 'normal'} ${fontSize}px monospace`;
const localLineHeight = Math.round(fontSize * 1.3);
const lines = wrapText(text, maxWidth, fontSize);
for (const line of lines) {
let x = padding;
@ -163,7 +164,7 @@ export class HtmlToImageConverter {
}
ctx.fillText(line, x, y);
y += lineHeight;
y += localLineHeight;
}
};
@ -175,7 +176,7 @@ export class HtmlToImageConverter {
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
y += lineHeight;
y += 8;
};
// Extract and render content recursively
@ -195,9 +196,20 @@ export class HtmlToImageConverter {
const fontWeight = style.fontWeight;
const isBold = fontWeight === 'bold' || parseInt(fontWeight) >= 600;
// Get font size and scale it up for high legibility on thermal printer
let fontSize = 16;
const fontSizeStr = style.fontSize;
if (fontSizeStr) {
const parsed = parseFloat(fontSizeStr);
if (!isNaN(parsed) && parsed > 0) {
fontSize = Math.max(12, Math.round(parsed * 1.35));
}
}
const localLineHeight = Math.round(fontSize * 1.3);
// Handle special elements
if (tagName === 'BR') {
y += lineHeight;
y += localLineHeight;
return;
}
@ -206,6 +218,22 @@ export class HtmlToImageConverter {
return;
}
// Special optimization: If the element is a product-name, print quantity and name inline
if (el.classList && el.classList.contains('product-name')) {
const qtyEl = el.querySelector('.qty') || el.querySelector('span:first-child');
const nameEl = el.querySelector('.text-wrap') || el.querySelector('span:nth-child(2)') || el.querySelector('span:last-child');
const qtyText = qtyEl ? qtyEl.textContent.trim() : '';
let nameText = nameEl ? nameEl.textContent.trim() : '';
if (!nameText && !qtyEl && el.textContent) {
nameText = el.textContent.trim();
}
if (qtyText || nameText) {
const combined = qtyText ? `${qtyText} ${nameText}` : nameText;
drawText(combined, textAlign, isBold, fontSize);
return;
}
}
// Check if element has only text content (no child elements)
const hasOnlyText = Array.from(el.childNodes).every(
node => node.nodeType === Node.TEXT_NODE
@ -214,7 +242,7 @@ export class HtmlToImageConverter {
if (hasOnlyText) {
const text = el.textContent.trim();
if (text) {
drawText(text, textAlign, isBold);
drawText(text, textAlign, isBold, fontSize);
}
} else {
// Process children
@ -222,7 +250,7 @@ export class HtmlToImageConverter {
if (child.nodeType === Node.TEXT_NODE) {
const text = child.textContent.trim();
if (text) {
drawText(text, textAlign, isBold);
drawText(text, textAlign, isBold, fontSize);
}
} else if (child.nodeType === Node.ELEMENT_NODE) {
processElement(child);
@ -232,7 +260,7 @@ export class HtmlToImageConverter {
// Add spacing after block elements
if (display === 'block' || tagName === 'DIV' || tagName === 'P' || tagName === 'TABLE') {
y += lineHeight / 2;
y += localLineHeight / 2;
}
};
@ -247,7 +275,7 @@ export class HtmlToImageConverter {
const lines = allText.split('\n').filter(l => l.trim());
y = padding;
for (const line of lines) {
drawText(line.trim());
drawText(line.trim(), 'left', false, 16);
}
}
}