LibrePDF / OpenPDF

OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Please feel free to submit pull-requests and bugreports to this GitHub repository.
Other
3.61k stars 597 forks source link

Openpdf does not apply font #1218

Open josemrfl opened 2 months ago

josemrfl commented 2 months ago

We are trying to migrate our application from the Itextpdf to Openpdf and we are finding problems with openpdf registering the font and styles we were already using.

It does not apply them correctly and seems to be picking up a default font and size making it sloppy.

/* The Constant PDF_INF_FONTS. / private static final String PDF_INF_FONTS = "/reports/fonts/trebuc.ttf";

/* The Constant MAIN_FONT. / private static final String MAIN_FONT = "trebuchet ms";

static { try { FontFactory.register(PDF_INF_FONTS, MAIN_FONT); } catch (final Exception e) { LOG.error("Specific font could not be registered for pdf generation", e); } }

private static void registerFonts(final ParametersExport parametrosExportacion) { letraCabeceras = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 9, Font.NORMAL, new Color(53, 46, 109)); letraFechasPar = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.NORMAL, new Color(53, 46, 109)); letraFechasImpar = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.NORMAL, new Color(255, 255, 255)); black = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.NORMAL, Color.BLACK); blackBold = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.BOLD, Color.BLACK); etiquetaIndicadores = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 6, Font.NORMAL, new Color(80, 88, 91)); letraIndicadores = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 1, Font.NORMAL, Color.BLACK); red = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.NORMAL, new Color(178, 34, 34)); blue = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 7, Font.NORMAL, new Color(0, 0, 205)); }

On the left side an example of what the code generates using ItextPDF and on the right what OpenPDF generates, not applying the font, nor the size or style

Screenshots

image

andreasrosdal commented 2 months ago

I created a test case based on the code you provided. According to ChatGPT the image has the font Trebuchet Ms.

Can you please create a full Junit test which demonstrates how you create the full PDF file, how you initialize the fonts and create the text.

Here are the results:

Image with font: image

This PDF file was generated: test_semana_output.pdf

Java test case:

package com.lowagie.text.pdf.fonts;

import static org.junit.jupiter.api.Assertions.*;

import com.lowagie.text.*;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import org.junit.jupiter.api.Test;

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FontRegistrationTest {

    private static final String PDF_INF_FONTS = "trebuc.ttf";
    private static final String MAIN_FONT = "trebuchet ms";
    private static final String OUTPUT_PDF_PATH = "test_semana_output.pdf";

    @Test
    public void testCreatePdfWithRegisteredFontAndTable() {
        // Register the font
        try {
            FontFactory.register(PDF_INF_FONTS, MAIN_FONT);
        } catch (Exception e) {
            fail("Font registration failed: " + e.getMessage());
        }

        // Create a PDF document using the registered fonts
        Document document = new Document();
        try (FileOutputStream fos = new FileOutputStream(OUTPUT_PDF_PATH)) {
            PdfWriter.getInstance(document, fos);
            document.open();

            // Create fonts for the PDF
            Font headerFont = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 12, Font.BOLD, Color.BLACK);
            Font bodyFont = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 10, Font.NORMAL, new Color(53, 46, 109));
            Font tableFont = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 9, Font.NORMAL, Color.BLACK);
            Font smallFont = FontFactory.getFont(MAIN_FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 8, Font.NORMAL, Color.GRAY);

            // Add "Semana" header
            Paragraph semanaHeader = new Paragraph("SEMANA 18 | 29/04/2024 - 05/05/2024", headerFont);
            semanaHeader.setAlignment(Element.ALIGN_CENTER);
            document.add(semanaHeader);
            document.add(Chunk.NEWLINE);

            // Add a simple drawing or placeholder for the image (a rectangle here)
            document.add(new Paragraph("Image Placeholder", smallFont));
            document.add(new Paragraph(" ", smallFont)); // Space for the image

            // Add mock data section with similar layout
            Paragraph mockDataHeader = new Paragraph("0/0/0", headerFont);
            mockDataHeader.setAlignment(Element.ALIGN_CENTER);
            document.add(mockDataHeader);

            Paragraph mockDataContent = new Paragraph("MOCK DATA MOCK DATA MOCK DATA", bodyFont);
            mockDataContent.setAlignment(Element.ALIGN_CENTER);
            document.add(mockDataContent);
            document.add(Chunk.NEWLINE);

            // Create a table like the one in the image
            PdfPTable table = new PdfPTable(4); // 4 columns
            table.setWidthPercentage(100);
            table.setSpacingBefore(10f);
            table.setSpacingAfter(10f);

            // Add the mock data cells
            for (int i = 0; i < 4; i++) {
                table.addCell(new Phrase("Mock Data", tableFont));
            }

            document.add(table);

            document.close();

            // Verify the PDF file has been created successfully
            File outputFile = new File(OUTPUT_PDF_PATH);
            assertTrue(outputFile.exists(), "PDF file should be created.");
            assertTrue(outputFile.length() > 0, "PDF file should not be empty.");

        } catch (DocumentException | IOException e) {
            fail("Failed to create PDF: " + e.getMessage());
        } finally {
            if (document.isOpen()) {
                document.close();
            }
        }
    }
}
josemrfl commented 1 month ago

Hi @andreasrosdal, On the first time, thanks so much for your help.

I can't upload the application's code for legal reasons, but honestly, it's quite strange. I tried generating a PDF using your unit test with the OpenPDF library, and it correctly applies both the font, sizes, and styles.

However, I later tried implementing another test that calls the method in my service to export PDFs, where I do exactly the same to register and use the font, and here it's not applying it. Moreover, I even tried putting the code from your test inside my service, and it still doesn’t apply it correctly.

I made sure to have the trebuc.ttf font in the classpath of my project and verified that it’s loading correctly with URL fontUrl = getClass().getClassLoader().getResource("trebuc.ttf");

No exception occurs when registering the font either, but in the generated PDF, if I check the document properties and look at the fonts used, TrebuchetMS doesn’t appear.

What could be happening here? With ItexPdf, I don't have this kind of issue. I am attaching the PDF generated by my export service, where it doesn’t have the TrebuchetMS font

CP Openpdf test.pdf image

jsmanrique commented 3 weeks ago

Any clue about what could be going on here?