tenta fix pdfservice.js
This commit is contained in:
1 parent
19f0187227
commit
db0c011b8b
1 file changed
+187
@@ -348,6 +348,193 @@ export class PdfService {
|
|||||||
.replace(/>/g, '>');
|
.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
|
// Processe o texto com as novas funções melhoradas
|
||||||
const textoLimpo = stripUnsupportedTags(
|
const textoLimpo = stripUnsupportedTags(
|
||||||
this.processarTemplate(conteudo, escritorio)
|
this.processarTemplate(conteudo, escritorio)
|
||||||
|
|||||||
Reference in new issue
Block a user