To generate a valid PDF/X document, it's mandatory to have all fonts embedded. Somehow it's not possible for me to use those fonts in an Graphics2D context.
This Unittests shows the problem (commented lines are some tests i made):
import java.awt.Font;
import java.awt.Graphics2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Map.Entry;
import org.junit.Test;
import com.itextpdf.awt.DefaultFontMapper;
import com.itextpdf.awt.DefaultFontMapper.BaseFontParameters;
import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
public class TestFont
{
@Test
public void shouldBeAbleToAddFountsAndDrawOnCanvas() throws FileNotFoundException, DocumentException
{
final DefaultFontMapper mapper = new DefaultFontMapper();
mapper.insertDirectory(".");
final PrintStream out2 = new PrintStream(System.out);
for (final Entry<String, BaseFontParameters> entry : mapper.getMapper().entrySet())
{
out2.println(String.format("%s: %s", entry.getKey(), entry.getValue().fontName));
}
out2.flush();
final float width = 150;
final float height = 150;
final Document document = new Document(new Rectangle(width, height));
final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("fonts.pdf"));
writer.setPDFXConformance(PdfWriter.PDFX32002);
document.open();
final Graphics2D g2d = new PdfGraphics2D(writer.getDirectContent(), width, height, mapper);
g2d.setFont(new Font("Comicate", Font.PLAIN, 12));
g2d.drawString("Hello world", 5, 24);
g2d.dispose();
document.close();
}
}
It will throw an PdfXConformanceException
with message: "All the fonts must be embedded. This one isn't: Helvetica.
I already browsed though the PdfGraphics2D
class to check the setFont()
implementation and found out, that a FontMapper
will be used. I already added this to the Unittest above.
public void setFont(Font f) {
if (f == null)
return;
if (onlyShapes) {
font = f;
return;
}
if (f == font)
return;
font = f;
fontSize = f.getSize2D();
baseFont = getCachedBaseFont(f);
}
private BaseFont getCachedBaseFont(Font f) {
synchronized (baseFonts) {
BaseFont bf = (BaseFont)baseFonts.get(f.getFontName());
if (bf == null) {
bf = fontMapper.awtToPdf(f);
baseFonts.put(f.getFontName(), bf);
}
return bf;
}
}
The Unittest is based on this example from the iText in Action book. Here are some other examples about the FontMapper.
To run the Unittest you need this dependency:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.3.2</version>
</dependency>
The Custom Font (located in ".") you find here.
The Console Output shows me this (to identify the fontName):
Comicate: ./COMICATE.TTF
I am not sure of the exact way to correct the error in your code, but there are easy workarounds:
Workaround 1) Create a BufferedImage to do all your graphics painting to. Then you can use all normal java.awt.Graphics
functions like drawString
and setColor
regardless of iText, and when you are done just draw the image to a PDF. WARNING you do loose quality of text when zooming, but here is an example:
//create doccument and writer
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));
BufferedImage bf = new BufferedImage(BorderWidth, BorderHeight, BorderWidth);
//Do all graphics code here, draw strings and images etc
//Some code to set font (java.awt.Font)
//Some code to draw string
//Some code to draw image?
//Convert BufferedImage to Image
Image img = (Image)bf;
//draw image to PDF using writer
writer.getDirectContentUnder().addImage(img);
Workaround 2) This uses iText features to draw strings, without needing to create any graphics objects, the font is taken care of by using a BaseFont
as follows:
//create doccument and writer
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));
document.open();
//This sample uses the "GOTHIC.TTF" font file located in the "Template" package
BaseFont bf = BaseFont.createFont(GUI.class.getClass().getResource("/Template/GOTHIC.TTF") + "", BaseFont.WINANSI, BaseFont.EMBEDDED);
//set font type, size and color
Font font = new Font(bf, 13.5f);
PdfContentByte canvas = writer.getDirectContent();
canvas.beginText();
canvas.setFontAndSize(bf, 10);
//Method Usage: showTextAligned(Align, String, x, y, rotation);
canvas.showTextAligned(Element.ALIGN_TOP, "My Text Here", 75, 40, 0);
canvas.endText();
document.close();
I know this does not give the answer you were looking for, however if you are just drawing a small amount of text then workaround 2 works great, I have used something similar to workaround 2 before. If this does not help then I am sure Bruno will have the answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With