Open admannon opened 7 months ago
I'm observing the same problem. However, in my case, I can generate one PDF without problems, but subsequent PDFs fail with this exact exception, though I'm also getting
Caused by: java.io.IOException: Helvetica not found as file or resource.
at com.lowagie.text.pdf.LayoutProcessor.loadFont(LayoutProcessor.java:307)
If that's related, I'm using the technique discussed by V-F in #1078 to render an SVG image.
Oh, and version 2.0.1 of OpenPDF works fine, only 2.0.2 breaks.
Ok, that is strange. Maybe there is a problem or difference resolving the font-resource. There were some changes so the tests also work on Windows.
Keeping the tests compatible in Windows, Unix and Mac is not easy, as I only have access to the first 2.
@admannon can you verify, that the error don't occur with 2.0.1?
It's also a strange behaviour, as helvetica may be a font provided by the OS, but there are helvetica-font-files also in the JAR.
Well, I'm on Linux and don't have any form of Helvetica installed. Could this influence something?
Ok, that is strange. Maybe there is a problem or difference resolving the font-resource. There were some changes so the tests also work on Windows.
Keeping the tests compatible in Windows, Unix and Mac is not easy, as I only have access to the first 2.
@admannon can you verify, that the error don't occur with 2.0.1?
Apologies for the delayed response. Yes, this error don't occur with OpenPDF v2.0.1. The attached PDF was generated using OpenPDF v2.0.1.
Are there any news on this? I'd be willing to spend some time on this if I could get a hint on where the culprit may be.
By the way, this issue is also present in OpenPDF 2.0.3
This bug was introduced in this change: https://github.com/LibrePDF/OpenPDF/pull/1114 (in OpenPDF 2.0.2 and later)
The test included in the first comment in this bugreport will fail for versions which include #1114 or later. Earlier commits do not have this problem. So I recommend to consider #1114 and how to fix this problem. Possibly revert #1114.
@vk-github18
See https://github.com/LibrePDF/OpenPDF/wiki/Accents,-DIN-91379,-non-Latin-scripts
LayoutProcessor works only with OpenType fonts provided as file. It does not work with Type1-fonts. This is documented and no bug. However, other fonts should by silently ignored - this will be fixed.
So the fix for your example is:
@vk-github18 Thanks for the tips. However, while these may apply to the OP's situation, I can say for certain that no document I'm generating with OpenPDF uses any Type 1 fonts whatsoever.[^1] Take a look at #1209 for how I'm loading and registering my fonts. (Even when I'm generating headers and footers I'm using one of those fonts.)
Furthermore, not calling LayoutProcessor.enable
or LayoutProcessor.enableKernLiga
is not an option because I need support for RTL text and such.
Please note that I still only observe the issue upon the second document I'm trying to generate. Running OpenPDF only once works perfectly fine.
Is what I'm observing a separate issue then?
[^1]: Side note: In the past, I've had some documents produced by OpenPDF that contained Helvetica in their fonts table though they didn't use it. I've gone over all my generating code since and I always provide one of the fonts I'm loading as TTF files whenever I instantiate a new Element
. Could this spurious reference of Helvetica without using be somehow related to this?
I can provide some more context: For rendering an SVG image, I'm using this code (mostly by V-F from #1078):
Image produceLogoImage (PdfWriter writer) {
try {
SAXSVGDocumentFactory svgFactory = new SAXSVGDocumentFactory (XMLResourceDescriptor.getXMLParserClassName ());
SVGDocument logoDocument = svgFactory.createSVGDocument (null, Thread.currentThread ().getContextClassLoader ().getResourceAsStream (/*some SVG*/));
UserAgent ua = new UserAgentAdapter ();
DocumentLoader loader = new DocumentLoader (ua);
BridgeContext context = new BridgeContext (ua, loader);
context.setDynamicState (BridgeContext.DYNAMIC);
GVTBuilder builder = new GVTBuilder ();
GraphicsNode rootGraphicsNode = builder.build (context, logoDocument);
PdfTemplate template = PdfTemplate.createTemplate (writer, 110, 37);
Graphics2D logoG2d = template.createGraphics (template.getWidth (), template.getHeight ());
try {
rootGraphicsNode.paint (logoG2d);
} catch (Exception e) {
e.printStackTrace ();
return null;
} finally {
logoG2d.dispose ();
}
return new ImgTemplate (template);
} catch (IOException e) {
e.printStackTrace ();
return null;
}
}
It fails (upon running the second time for a new PdfWriter
) on the line
Graphics2D logoG2d = template.createGraphics (template.getWidth (), template.getHeight ());
with the following exception:
java.lang.RuntimeException: Font creation failed for Helvetica.
at com.lowagie.text.pdf.LayoutProcessor.loadFont(LayoutProcessor.java:318)
at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:727)
at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:650)
at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:486)
at com.lowagie.text.pdf.DefaultFontMapper.awtToPdf(DefaultFontMapper.java:145)
at com.lowagie.text.pdf.PdfGraphics2D.getCachedBaseFont(PdfGraphics2D.java:1070)
at com.lowagie.text.pdf.PdfGraphics2D.setFont(PdfGraphics2D.java:1063)
at com.lowagie.text.pdf.PdfGraphics2D.<init>(PdfGraphics2D.java:269)
at com.lowagie.text.pdf.PdfContentByte.createGraphics(PdfContentByte.java:3185)
// further stack only includes my classes
Caused by: java.io.IOException: Helvetica not found as file or resource.
at com.lowagie.text.pdf.LayoutProcessor.loadFont(LayoutProcessor.java:307)
Do I need to set a font here too? If so, how?
@a-leithner As PdfTemplate extends PdfContentBytePdfTemplate you could call template.setFontAndSize(BaseFont bf, float size)
However with https://github.com/LibrePDF/OpenPDF/pull/1211 this exception should not occure any more. But LayoutProcessor does nothing without an OpenType font.
@vk-github18 Great, thanks a lot! I'll try the changes from that PR locally and'll report back.
I've tried calling template.setFontAndSize
but that unfortunately didn't help.
@vk-github18 Thanks again for that fix! I can confirm it works in my scenario and I'm no longer getting this exception.
PLEASE FILL THIS TEMPLATE AS MUCH AS POSSIBLE. REMOVE IRRELEVANT PARTS.
Describe the bug
We can't generate PDF document from code below and got error:
To Reproduce
Code to reproduce the issue
Unit Test
```java import com.lowagie.text.Document; import com.lowagie.text.pdf.LayoutProcessor; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfWriter; import org.junit.jupiter.api.Test; import java.awt.*; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.print.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; class PdfConverterTest { private static int generateContent(Graphics g, PageFormat pf, int i) { var g2 = (Graphics2D) g; float h = (float) pf.getHeight(); float w = (float) pf.getWidth(); Ellipse2D.Double circle = new Ellipse2D.Double(); Ellipse2D.Double oval = new Ellipse2D.Double(); Ellipse2D.Double leaf = new Ellipse2D.Double(); Ellipse2D.Double stem = new Ellipse2D.Double(); g2.setColor(Color.green); double eh = h / 2; double ew = w / 2; leaf.setFrame(ew - 16, eh - 29, 15.0, 15.0); Area leaf1 = new Area(leaf); leaf.setFrame(ew - 14, eh - 47, 30.0, 30.0); Area leaf2 = new Area(leaf); leaf1.intersect(leaf2); g2.fill(leaf1); // Creates the second leaf. leaf.setFrame(ew + 1, eh - 29, 15.0, 15.0); leaf1 = new Area(leaf); leaf2.intersect(leaf1); g2.fill(leaf2); g2.setColor(Color.black); // Creates the stem by filling the Area resulting from the subtraction of two Area objects created from an // ellipse. stem.setFrame(ew, eh - 42, 40.0, 40.0); Area st1 = new Area(stem); stem.setFrame(ew + 3, eh - 47, 50.0, 50.0); Area st2 = new Area(stem); st1.subtract(st2); g2.fill(st1); g2.setColor(Color.yellow); // Creates the pear itself by filling the Area resulting from the union of two Area objects created by two // different ellipses. circle.setFrame(ew - 25, eh, 50.0, 50.0); oval.setFrame(ew - 19, eh - 20, 40.0, 70.0); Area circ = new Area(); circ.add(new Area(circle)); circ.add(new Area(oval)); g2.fill(circ); g2.setColor(Color.black); g2.setFont(new Font("Arial", Font.PLAIN, 18)); String pear = "Pear"; FontMetrics metrics = g2.getFontMetrics(); int width = metrics.stringWidth(pear); g2.drawString(pear, (w - width) / 2, 20); return Printable.PAGE_EXISTS; } private static PageFormat getPageFormat(double width, double height, int orientation) { PageFormat pageFormat = new PageFormat(); Paper paper = pageFormat.getPaper(); paper.setSize(width, height); paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight()); pageFormat.setPaper(paper); pageFormat.setOrientation(orientation); return pageFormat; } @Test void generateFromPageable() throws IOException, PrinterException { Book book = new Book(); book.append( PdfConverterTest::generateContent, getPageFormat(595.2755905511812, 841.8897637795277, PageFormat.PORTRAIT)); LayoutProcessor.enable(); byte[] pdfContentByte; try (var outputStream = new ByteArrayOutputStream()) { try (var document = new Document()) { var writer = PdfWriter.getInstance(document, outputStream); document.open(); var contentByte = writer.getDirectContent(); var totalPages = book.getNumberOfPages(); for (var i = 0; i < totalPages; i++) { var pageFormat = book.getPageFormat(i); var printable = book.getPrintable(i); float pageW = (float) pageFormat.getWidth(); float pageH = (float) pageFormat.getHeight(); float marginL = (float) pageFormat.getImageableX(); float marginT = (float) pageFormat.getImageableY(); float marginR = (float) (pageW - pageFormat.getImageableWidth()); float marginB = (float) (pageH - pageFormat.getImageableHeight()); document.setPageSize(new com.lowagie.text.Rectangle(pageW, pageH)); document.setMargins(marginL, marginR, marginT, marginB); document.newPage(); Graphics2D g2 = contentByte.createGraphics(pageW, pageH); printable.print(g2, pageFormat, i); g2.dispose(); contentByte.sanityCheck(); } } pdfContentByte = outputStream.toByteArray(); } try (var inputStream = new ByteArrayInputStream(pdfContentByte)) { new PdfReader(inputStream); } } } ```
Expected behavior
This code should generate a PDF normally
System
(please complete the following information)
new Font(Font.SANS_SERIF, Font.PLAIN, 12)