tenta fix pdfservice.js

This commit is contained in:
rodrigo committed 2025-04-22 12:02:12 -03:00
1 parent 19f0187227
commit db0c011b8b
1 file changed
+187
+187
View File
@@ -348,6 +348,193 @@ export class PdfService {
.replace(/>/g, '>');
}
/**
* Renderiza um parágrafo com formatação inline (negrito, itálico)
* @returns A posição Y após renderizar ou null se não coube na página
*/
function renderInlineFormattedParagraph(
page: any,
text: string,
x: number,
startY: number,
normalFont: any,
boldFont: any,
italicFont: any,
boldItalicFont: any,
fontSize: number,
color: any,
align: 'left' | 'center' | 'right' | 'justify',
maxWidth: number,
debug: boolean = false,
marginTop: number,
marginBottom: number,
pageHeight: number
): number | null {
const lineHeight = fontSize * 1.5;
let y = startY;
let currentX = x;
let words: Array<{text: string, font: any, width: number}> = [];
let currentLine: Array<{text: string, font: any, width: number}> = [];
let currentLineWidth = 0;
let textParts = [];
// Detectar formatação inline
let remainingText = text;
let currentFont = normalFont;
let boldActive = false;
let italicActive = false;
// Processa texto com formatação
while (remainingText.length > 0) {
if (remainingText.startsWith('<b>')) {
// Começa negrito
boldActive = true;
remainingText = remainingText.substring(3);
currentFont = italicActive ? boldItalicFont : boldFont;
} else if (remainingText.startsWith('</b>')) {
// Termina negrito
boldActive = false;
remainingText = remainingText.substring(4);
currentFont = italicActive ? italicFont : normalFont;
} else if (remainingText.startsWith('<i>')) {
// Começa itálico
italicActive = true;
remainingText = remainingText.substring(3);
currentFont = boldActive ? boldItalicFont : italicFont;
} else if (remainingText.startsWith('</i>')) {
// Termina itálico
italicActive = false;
remainingText = remainingText.substring(4);
currentFont = boldActive ? boldFont : normalFont;
} else {
// Texto normal - procura pela próxima tag de formatação
let nextTag = remainingText.search(/<\/?[bi]>/);
if (nextTag === -1) {
// Não há mais tags, adiciona todo o texto restante
textParts.push({
text: remainingText,
font: currentFont
});
remainingText = '';
} else {
// Adiciona texto até a próxima tag
textParts.push({
text: remainingText.substring(0, nextTag),
font: currentFont
});
remainingText = remainingText.substring(nextTag);
}
}
}
// Processa partes de texto em palavras para quebra de linha
for (const part of textParts) {
const partWords = part.text.split(/\s+/);
for (let i = 0; i < partWords.length; i++) {
if (partWords[i].length === 0) continue;
const wordText = i < partWords.length - 1 ? partWords[i] + ' ' : partWords[i];
const wordWidth = part.font.widthOfTextAtSize(wordText, fontSize);
words.push({
text: wordText,
font: part.font,
width: wordWidth
});
}
}
// Processa palavras em linhas
for (let i = 0; i < words.length; i++) {
const word = words[i];
if (currentLineWidth + word.width <= maxWidth) {
// A palavra cabe na linha atual
currentLine.push(word);
currentLineWidth += word.width;
} else {
// A palavra não cabe, desenha a linha atual e começa nova linha
// Primeiro verifica se há espaço vertical suficiente
if (y - lineHeight < marginBottom) {
return null; // Não há espaço suficiente na página
}
// Desenha a linha com o alinhamento apropriado
y = drawFormattedLine(page, currentLine, x, y, maxWidth, align, fontSize, color);
// Começa uma nova linha com a palavra atual
currentLine = [word];
currentLineWidth = word.width;
}
}
// Desenha a última linha se houver palavras restantes
if (currentLine.length > 0) {
if (y - lineHeight < marginBottom) {
return null; // Não há espaço suficiente na página
}
y = drawFormattedLine(page, currentLine, x, y, maxWidth, align, fontSize, color);
}
return y;
}
/**
* Desenha uma linha formatada com alinhamento específico
*/
function drawFormattedLine(
page: any,
line: Array<{text: string, font: any, width: number}>,
x: number,
y: number,
maxWidth: number,
align: 'left' | 'center' | 'right' | 'justify',
fontSize: number,
color: any
): number {
const lineHeight = fontSize * 1.5;
let currentX = x;
let totalWidth = line.reduce((sum, word) => sum + word.width, 0);
// Calcula o espaço adicional entre palavras para justificação
let extraSpacing = 0;
if (align === 'justify' && line.length > 1 && totalWidth < maxWidth * 0.8) {
extraSpacing = (maxWidth - totalWidth) / (line.length - 1);
}
// Ajusta a posição x inicial baseada no alinhamento
if (align === 'center') {
currentX = x + (maxWidth - totalWidth) / 2;
} else if (align === 'right') {
currentX = x + maxWidth - totalWidth;
}
// Desenha cada palavra
for (let i = 0; i < line.length; i++) {
const word = line[i];
page.drawText(word.text, {
x: currentX,
y: y,
font: word.font,
size: fontSize,
color: color
});
// Avança X para a próxima palavra
currentX += word.width;
// Adiciona espaço extra para justificação, exceto na última palavra
if (align === 'justify' && i < line.length - 1) {
currentX += extraSpacing;
}
}
// Retorna a nova posição Y após desenhar a linha
return y - lineHeight;
}
// Processe o texto com as novas funções melhoradas
const textoLimpo = stripUnsupportedTags(
this.processarTemplate(conteudo, escritorio)