Falco
Falco

Reputation: 1596

itext7 embed font in header just 1 time for pdfa

I'm applying header on a pdf/a document

I embed my font in document, no problem if I have hundreds of page, in pdf created I see just one font embedded in document properties.

Now I worked on adding an header using canvas as seen in many examples.

At first it throw error because it says font must be embedded.

When I embed the font it works, but in document properties I see the font repeated for every page.

So the document kb size grows a lot.

I want font embedded just one time.

Spring boot, but i think it does not matter.

The code of header:

@Slf4j
public class Header implements IEventHandler {
    
    private IFontProviderService fontProviderService;
    private String logoPath;

    private String header;
    private List<String> subHeaders;
    
    public Header(IFontProviderService fontProviderService, String logoPath, String header, List<String> subHeaders) {
        this.fontProviderService = fontProviderService;
        this.header = header;
        this.subHeaders = subHeaders;
        this.logoPath = logoPath;
    }

    @Override
    public void handleEvent(Event event) {

        try {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            PdfDictionary pdfObject = page.getPdfObject();

            PdfCanvas headerPdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf);
            Rectangle headerRect = new Rectangle(35, 740, 495, 96);
            Canvas headerCanvas = new Canvas(headerPdfCanvas, headerRect);

            headerCanvas.setFont(fontProviderService.getDefaultPdfFont());

            headerCanvas.enableAutoTagging(page);
            CreateHeaderContent(headerCanvas);
            headerCanvas.close();

        } catch (Exception e) {
            log.error("Error in header settings.", e);
        }

    }

    private void CreateHeaderContent(Canvas canvas) throws MalformedURLException {
        Table table = new Table(UnitValue.createPercentArray(new float[] { 80, 20 }));
        table.setWidth(UnitValue.createPercentValue(100));

        Cell cell1 = new Cell().add(new Paragraph(header).setBold().setFontSize(11).setTextAlignment(TextAlignment.LEFT));
        for (int i = 0; i < subHeaders.size(); i++) {
            cell1.add(new Paragraph(subHeaders.get(i)).setFontSize(8).setTextAlignment(TextAlignment.LEFT));
        }
        cell1.setBorder(Border.NO_BORDER);
        table.addCell(cell1);

        ImageData imageData = ImageDataFactory.create(logoPath);
        Image image = new Image(imageData);
        image.getAccessibilityProperties().setAlternateDescription("...");
        Cell cell2 = new Cell().add(image.setTextAlignment(TextAlignment.RIGHT));
        cell2.setBorder(Border.NO_BORDER);
        cell2.setVerticalAlignment(VerticalAlignment.MIDDLE);
        table.addCell(cell2);

        canvas.add(table);
    }
}




@Slf4j
@Service
public class FontProviderService implements IFontProviderService {

    @Value("${pdf.resources.external.path}")
    private String staticResourcesPath;
    
    @Override
    public FontProvider getFontProvider() throws IOException {
        FontProvider fontProvider = new FontProvider("DMSans-Regular");
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Regular.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Bold.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Italic.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-BoldItalic.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Medium.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-MediumItalic.ttf"));
        return fontProvider;
    }

    @Override
    public PdfFont getDefaultPdfFont() throws IOException {
        String defaultFontFamily = this.getFontProvider().getDefaultFontFamily();
        Collection<FontInfo> fonts = this.getFontProvider().getFontSet().getFonts();
        FontInfo fontInfo = fonts.stream().filter(f -> f.getFontName().equals(defaultFontFamily)).findFirst().get();
        PdfFont pdfFont = this.getFontProvider().getPdfFont(fontInfo);
        return pdfFont;
    }

}

Upvotes: 2

Views: 475

Answers (1)

Falco
Falco

Reputation: 1596

...Spring had something to do with it in some way ...at least in the manner i wrote the service...

Well... Actually in my case the problem was just how I used the service sprint to retrieve the fontProvider and the font.

I'm passing to my handler the entire fontProviderService:

public Header(IFontProviderService fontProviderService, String logoPath, String header, List<String> subHeaders)

and calling every time:

headerCanvas.setFont(fontProviderService.getDefaultPdfFont());

That's equal to create every time a new provider:

FontProvider fontProvider = new FontProvider("DMSans-Regular");

The point to focus is that the FontProvider object and the PdfFont objects must be always the same

So modified my Handler like this:

@Slf4j
public class Header implements IEventHandler {
    
    private FontProvider fontProvider;
    private PdfFont pdfFont;

    private String logoPath;
    
    private String header;
    private List<String> subHeaders;
    
    public Header(FontProvider fontProvider, PdfFont pdfFont, String logoPath, String header, List<String> subHeaders) {
        this.fontProvider = fontProvider;
        this.pdfFont = pdfFont;
        this.header = header;
        this.subHeaders = subHeaders;
        this.logoPath = logoPath;
    }

    @Override
    public void handleEvent(Event event) {

        try {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            PdfDictionary pdfObject = page.getPdfObject();

            PdfCanvas headerPdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf);
            Rectangle headerRect = new Rectangle(35, 740, 495, 96);
            Canvas headerCanvas = new Canvas(headerPdfCanvas, headerRect);

            headerCanvas.setFontProvider(fontProvider);
            headerCanvas.setFont(pdfFont);

            headerCanvas.enableAutoTagging(page);
            CreateHeaderContent(headerCanvas);
            headerCanvas.close();

        } catch (Exception e) {
            log.error("Error in header settings.", e);
        }

    }

    private void CreateHeaderContent(Canvas canvas) throws MalformedURLException {
        Table table = new Table(UnitValue.createPercentArray(new float[] { 80, 20 }));
        table.setWidth(UnitValue.createPercentValue(100));

        Cell cell1 = new Cell().add(new Paragraph(header).setBold().setFontSize(11).setTextAlignment(TextAlignment.LEFT));
        for (int i = 0; i < subHeaders.size(); i++) {
            cell1.add(new Paragraph(subHeaders.get(i)).setFontSize(8).setTextAlignment(TextAlignment.LEFT));
        }
        cell1.setBorder(Border.NO_BORDER);
        table.addCell(cell1);

        ImageData imageData = ImageDataFactory.create(logoPath);
        Image image = new Image(imageData);
        image.getAccessibilityProperties().setAlternateDescription("...");
        Cell cell2 = new Cell().add(image.setTextAlignment(TextAlignment.RIGHT));
        cell2.setBorder(Border.NO_BORDER);
        cell2.setVerticalAlignment(VerticalAlignment.MIDDLE);
        table.addCell(cell2);

        canvas.add(table);
    }
}

Just for complete, I removed the getDefaultFont from Service and this is an extract of the pdf creator calling the Handler:

    FontProvider fontProvider = fontProviderService.getFontProvider();
    String defaultFontFamily = fontProvider.getDefaultFontFamily();
    Collection<FontInfo> fonts = fontProvider.getFontSet().getFonts();
    FontInfo fontInfo = fonts.stream().filter(f -> f.getFontName().equals(defaultFontFamily)).findFirst().get();
    PdfFont defaultPdfFont = fontProvider.getPdfFont(fontInfo);

...

        converterProperties.setFontProvider(fontProvider);
        
        Header headerHandler = new Header(fontProvider, defaultPdfFont, staticResourcesPath + "....png", "...", "...");
        pdf.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);

Upvotes: 0

Related Questions