tenta fix pdfservice.js
This commit is contained in:
1 parent
c485960759
commit
e21dea582c
1 file changed
+247
@@ -378,6 +378,253 @@ export class PdfService {
|
||||
return `§§ALIGN=${align}§§§§INDENT=${indent}§§${paragraph}`;
|
||||
}).filter(Boolean);
|
||||
|
||||
/**
|
||||
* Renderiza um parágrafo com formatação inline (negrito, itálico, sublinhado)
|
||||
*/
|
||||
const renderInlineFormattedParagraph = (
|
||||
page: any,
|
||||
text: string,
|
||||
x: number,
|
||||
y: number,
|
||||
normalFont: any,
|
||||
boldFont: any,
|
||||
italicFont: any,
|
||||
boldItalicFont: any,
|
||||
fontSize: number,
|
||||
color: any,
|
||||
align: 'left' | 'center' | 'justify' = 'left',
|
||||
maxWidth: number = MAX_WIDTH,
|
||||
isContinuation: boolean = false,
|
||||
marginTop: number = margens.top,
|
||||
marginBottom: number = margens.bottom,
|
||||
pageHeight: number = PAGE_HEIGHT
|
||||
): number | null => {
|
||||
// Se não houver espaço suficiente na página atual para pelo menos uma linha de texto
|
||||
if (y < marginBottom + fontSize) {
|
||||
return null; // Indica que precisa criar nova página
|
||||
}
|
||||
|
||||
const words = text.split(/\s+/);
|
||||
let currentLine = '';
|
||||
let currentX = x;
|
||||
let currentY = y;
|
||||
const lineHeight = fontSize * 1.2;
|
||||
|
||||
// Processamento de formatação inline básica
|
||||
let formattedChunks: { text: string, isItalic: boolean, isBold: boolean }[] = [];
|
||||
|
||||
// Pré-processamento do texto para detectar formatação
|
||||
let remaining = text;
|
||||
let inBold = false;
|
||||
let inItalic = false;
|
||||
let currentChunk = '';
|
||||
|
||||
while (remaining.length > 0) {
|
||||
if (remaining.startsWith('<b>') || remaining.startsWith('<strong>')) {
|
||||
// Adiciona o texto acumulado antes da tag
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic, isBold });
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
inBold = true;
|
||||
remaining = remaining.replace(/^<(b|strong)>/, '');
|
||||
}
|
||||
else if (remaining.startsWith('</b>') || remaining.startsWith('</strong>')) {
|
||||
// Adiciona o texto acumulado em negrito
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic, isBold: true });
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
inBold = false;
|
||||
remaining = remaining.replace(/^<\/(b|strong)>/, '');
|
||||
}
|
||||
else if (remaining.startsWith('<i>') || remaining.startsWith('<em>')) {
|
||||
// Adiciona o texto acumulado antes da tag
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic, isBold });
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
inItalic = true;
|
||||
remaining = remaining.replace(/^<(i|em)>/, '');
|
||||
}
|
||||
else if (remaining.startsWith('</i>') || remaining.startsWith('</em>')) {
|
||||
// Adiciona o texto acumulado em itálico
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic: true, isBold });
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
inItalic = false;
|
||||
remaining = remaining.replace(/^<\/(i|em)>/, '');
|
||||
}
|
||||
else if (remaining.startsWith('<br>') || remaining.startsWith('<br/>') || remaining.startsWith('<br />')) {
|
||||
// Adiciona o texto acumulado e então adiciona uma quebra de linha
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic, isBold });
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
formattedChunks.push({ text: '\n', isItalic: false, isBold: false });
|
||||
remaining = remaining.replace(/^<br\s*\/?>/i, '');
|
||||
}
|
||||
else {
|
||||
// Acumula caractere a caractere
|
||||
currentChunk += remaining[0];
|
||||
remaining = remaining.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Adiciona qualquer texto restante
|
||||
if (currentChunk) {
|
||||
formattedChunks.push({ text: currentChunk, isItalic, isBold });
|
||||
}
|
||||
|
||||
// Agora temos o texto dividido em chunks com formatação
|
||||
let lines: { chunks: { text: string, isItalic: boolean, isBold: boolean }[], width: number }[] = [{ chunks: [], width: 0 }];
|
||||
let currentLineIndex = 0;
|
||||
|
||||
for (const chunk of formattedChunks) {
|
||||
if (chunk.text === '\n') {
|
||||
// Forçar quebra de linha
|
||||
lines.push({ chunks: [], width: 0 });
|
||||
currentLineIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const words = chunk.text.split(/\s+/);
|
||||
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const word = words[i];
|
||||
if (!word) continue;
|
||||
|
||||
const font = chunk.isBold && chunk.isItalic ? boldItalicFont :
|
||||
chunk.isBold ? boldFont :
|
||||
chunk.isItalic ? italicFont : normalFont;
|
||||
|
||||
const wordWidth = font.widthOfTextAtSize(word, fontSize);
|
||||
const spaceWidth = font.widthOfTextAtSize(' ', fontSize);
|
||||
|
||||
// Verificar se precisamos adicionar espaço antes da palavra
|
||||
let wordWithSpace = word;
|
||||
let totalWidth = wordWidth;
|
||||
|
||||
// Adicionar espaço se não for a primeira palavra da linha e não estivermos após uma quebra forçada
|
||||
if (lines[currentLineIndex].chunks.length > 0) {
|
||||
wordWithSpace = ' ' + word;
|
||||
totalWidth = wordWidth + spaceWidth;
|
||||
}
|
||||
|
||||
// Verificar se a palavra cabe na linha atual
|
||||
if (lines[currentLineIndex].width + totalWidth <= maxWidth) {
|
||||
// Adicionar à linha atual
|
||||
lines[currentLineIndex].chunks.push({
|
||||
text: wordWithSpace,
|
||||
isItalic: chunk.isItalic,
|
||||
isBold: chunk.isBold
|
||||
});
|
||||
lines[currentLineIndex].width += totalWidth;
|
||||
} else {
|
||||
// Criar nova linha
|
||||
lines.push({
|
||||
chunks: [{ text: word, isItalic: chunk.isItalic, isBold: chunk.isBold }],
|
||||
width: wordWidth
|
||||
});
|
||||
currentLineIndex++;
|
||||
|
||||
// Verificar se temos espaço para mais uma linha
|
||||
if (currentY - lineHeight < marginBottom) {
|
||||
// Não há espaço suficiente para mais uma linha
|
||||
return null; // Indica que precisa criar nova página
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Desenhar as linhas com formatação
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
currentY -= lineHeight;
|
||||
|
||||
// Verificar se temos espaço para esta linha
|
||||
if (currentY < marginBottom) {
|
||||
return null; // Indica que precisa criar nova página
|
||||
}
|
||||
|
||||
// Ajustar posição X baseada no alinhamento
|
||||
let startX = x;
|
||||
|
||||
if (align === 'center') {
|
||||
startX = x + (maxWidth - line.width) / 2;
|
||||
} else if (align === 'justify' && i < lines.length - 1 && line.chunks.length > 1) {
|
||||
// Justificar texto (exceto última linha do parágrafo)
|
||||
let wordCount = 0;
|
||||
let textWidth = 0;
|
||||
|
||||
// Contar palavras e determinar largura total do texto
|
||||
for (const chunk of line.chunks) {
|
||||
const text = chunk.text.trim();
|
||||
if (text) {
|
||||
wordCount += text.split(/\s+/).length;
|
||||
const font = chunk.isBold && chunk.isItalic ? boldItalicFont :
|
||||
chunk.isBold ? boldFont :
|
||||
chunk.isItalic ? italicFont : normalFont;
|
||||
textWidth += font.widthOfTextAtSize(text, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Calcular espaçamento extra entre palavras para justificar
|
||||
const totalSpaces = wordCount - 1;
|
||||
const spaceWidth = totalSpaces > 0 ? (maxWidth - textWidth) / totalSpaces : 0;
|
||||
|
||||
// Desenhar cada chunk com espaçamento justificado
|
||||
let runningX = x;
|
||||
for (const chunk of line.chunks) {
|
||||
const font = chunk.isBold && chunk.isItalic ? boldItalicFont :
|
||||
chunk.isBold ? boldFont :
|
||||
chunk.isItalic ? italicFont : normalFont;
|
||||
|
||||
// Desenhar texto do chunk
|
||||
page.drawText(chunk.text, {
|
||||
x: runningX,
|
||||
y: currentY,
|
||||
size: fontSize,
|
||||
font: font,
|
||||
color: color
|
||||
});
|
||||
|
||||
// Avançar posição X
|
||||
runningX += font.widthOfTextAtSize(chunk.text, fontSize) + spaceWidth;
|
||||
}
|
||||
|
||||
// Pular para a próxima linha
|
||||
continue;
|
||||
}
|
||||
|
||||
// Desenhar cada chunk
|
||||
let runningX = startX;
|
||||
for (const chunk of line.chunks) {
|
||||
const font = chunk.isBold && chunk.isItalic ? boldItalicFont :
|
||||
chunk.isBold ? boldFont :
|
||||
chunk.isItalic ? italicFont : normalFont;
|
||||
|
||||
page.drawText(chunk.text, {
|
||||
x: runningX,
|
||||
y: currentY,
|
||||
size: fontSize,
|
||||
font: font,
|
||||
color: color
|
||||
});
|
||||
|
||||
runningX += font.widthOfTextAtSize(chunk.text, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
return currentY; // Retorna a posição Y final
|
||||
};
|
||||
|
||||
let timbradoPdf: PDFDocument | null = null;
|
||||
let timbradoPageCount = 0;
|
||||
let timbradoPages: any[] = [];
|
||||
|
||||
Reference in new issue
Block a user