I have a class given below which is giving me Exception: Exception in thread "main" com.itextpdf.text.DocumentException: com.itextpdf.text.pdf.PdfAConformanceException: All the fonts must be embedded. This one isn't: ZapfDingbats
I have the ZapfDingbats font embedded but I am still getting this Exception.
What i am trying to achieve here is create a list with a bullet in front of every item in the list.
What am i missing here?
public class SquareBullet {
public static void main(String[] args) throws IOException, DocumentException, XMPException {
Document document = new Document();
PdfAWriter writer = PdfAWriter.getInstance(document, new FileOutputStream("list.pdf"), PdfAConformanceLevel.PDF_A_1A);
writer.setViewerPreferences(PdfAWriter.PageModeUseOutlines);
writer.setRunDirection(PdfAWriter.RUN_DIRECTION_LTR);
writer.setTagged(PdfAWriter.markAll);
writer.createXmpMetadata();
XmpWriter xmp = writer.getXmpWriter();
DublinCoreProperties.addSubject(xmp.getXmpMeta(), "Subject");
DublinCoreProperties.setTitle(xmp.getXmpMeta(), "Title", "en_US", "en_US");
DublinCoreProperties.setDescription(xmp.getXmpMeta(), "Description", "en_US", "en_US");
PdfProperties.setKeywords(xmp.getXmpMeta(), "Keywords");
PdfProperties.setVersion(xmp.getXmpMeta(), "1.4");
document.addLanguage("en_US");
document.open();
Font font = FontFactory.getFont(FontFactory.ZAPFDINGBATS, BaseFont.ZAPFDINGBATS, BaseFont.EMBEDDED, 12);
Font font1 = FontFactory.getFont(FontFactory.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED, 12);
ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream("sRGB Color Space Profile.icm"));
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
List list = new List(10);
list.setListSymbol(new Chunk(String.valueOf((char)110), font));
list.add(new ListItem(new Chunk("Test 1", font1)));
list.add(new ListItem(new Chunk("Test 2", font1)));
list.add(new ListItem(new Chunk("Test 3", font1)));
document.add(list);
document.close();
}
}
Your claim I have the ZapfDingbats font embedded is wrong.
Granted, you define the font like this:
Font font = FontFactory.getFont(FontFactory.ZAPFDINGBATS,
BaseFont.ZAPFDINGBATS, BaseFont.EMBEDDED, 12);
As you use BaseFont.EMBEDDED, you might assume that the font will be embedded, but it isn't. You can check this by using that font in any other PDF that isn't PDF/A: if you go to Document Properties > Fonts, you'll see that the font isn't embedded.
Why is this?
There are 14 special fonts in PDF. We refer to them as the Standard Type 1 fonts. Every PDF viewer should be able to render text that uses those fonts, hence these fonts don't need to be embedded: 4 Helvetica fonts (regular, bold, italic, bold-italic), 4 Times Roman fonts (regular, bold, italic, bold-italic), 4 Courier fonts (regular, bold, italic, bold-italic), Symbol and Zapfdingbats.
iText ships with the AFM files of these fonts. AFM stands for Adobe Font Metrics and the files contain data about the widths, bounding boxes, and other metrics of glyphs that are available in each font.
The actual description of the shape of these fonts isn't shipped with iText. These are stored in a PFB (Printer Font Binary) file. Without these PFB files, iText can't (and won't) embed these Standard Type 1 fonts.
In other words: iText ignores the BaseFont.EMBEDDED parameter.
This is documented on many places. If you want to create PDF/A, you need font files, such as TTF, OTF, TTC files, or a combination of AFM and PFB files.
you must add the "jasperreports-fonts-" jar to your classpath.
Related
I am creating a Rich text editor in java where i have to use pfm font in jtextPane .how can i use it? I previously used ttf font, it works fine.but as industry standard i have to use pfm font
String fName = "d:\\CHANK___0.PFM"
Font font = new Font(bf, 12, Font.NORMAL);
fonts = font ;
but when i write textPane.setFont(font) it shows an error
I'm trying to open PDF file in iText7, write there some new piece of text, apply font from original PDF to it and save it in another PDF document. I'm using Java 1.8
Thus, I need a set of font names used in original pdf, from where user will choose one, that will be applied to a new paragraph.
And I also need to somehow apply this font.
For now I have this piece of code, that I've taken from here:
public static void main(String[] args) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfReader("example.pdf"));
Set<PdfName> fonts = listAllUsedFonts(pdf);
fonts.stream().forEach(System.out::println);
}
public static Set<PdfName> listAllUsedFonts(PdfDocument pdfDoc) throws IOException {
PdfDictionary acroForm = pdfDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.AcroForm);
if (acroForm == null) {
return null;
}
PdfDictionary dr = acroForm.getAsDictionary(PdfName.DR);
if (dr == null) {
return null;
}
PdfDictionary font = dr.getAsDictionary(PdfName.Font);
if (font == null) {
return null;
}
return font.keySet();
}
It returns this output:
/Helv
/ZaDb
However, the only font example.pdf has is Verdana (it is what document properties in Adobe Acrobat Pro says). Moreover, there are Verdana in two implementations: Bold and normal.
So, I have these questions:
Why does this function returns two fonts instead of one (Verdana).
How can I generate normal well-read names of fonts to display them
to user (e.g. Helvetica instead of Helv)?
How can I apply font got from the original document to the
new paragraph?
Thank you in advance!
If you only wish to display the names of the fonts being used (which you are legally allowed to do) you can use the following code:
public void go() throws IOException {
final Set<String> usedFontNames = new HashSet<>();
IEventListener fontNameExtractionStrategy = new IEventListener() {
#Override
public void eventOccurred(IEventData iEventData, EventType eventType) {
if(iEventData instanceof TextRenderInfo)
{
TextRenderInfo tri = (TextRenderInfo) iEventData;
String fontName = tri.getFont().getFontProgram().getFontNames().getFontName();
usedFontNames.add(fontName);
}
}
#Override
public Set<EventType> getSupportedEvents() {
return null;
}
};
PdfCanvasProcessor parser = new PdfCanvasProcessor(fontNameExtractionStrategy);
File inputFile = new File("YOUR_INPUT_FILE_HERE.pdf");
PdfDocument pdfDocument = new PdfDocument(new PdfReader(inputFile));
for(int i=1;i<=pdfDocument.getNumberOfPages();i++)
{
parser.processPageContent(pdfDocument.getPage(i));
}
pdfDocument.close();
for(String fontName : usedFontNames)
{
System.out.println(fontName);
}
}
You should not reuse a font from one PDF in another PDF, and here's why: fonts are hardly ever fully embedded in a PDF document. For instance: you use the font Verdana regular (238 KB) and the font Verdana bold (207 KB), but when you create a simple PDF document saying "Hello World" in regular and bold, the file size will be much smaller than 238 + 207 KB. Why is this? Because the PDF will only consist of a subset of the font Verdana regular and a subset of the font Verdana bold.
You may have noticed that I am talking of the font Verdana regular
and the font Verdana bold. Those are two different fonts from
the same font family. Reading your question, I notice that you don't make that distinction. You talk about the font Verdana with
two implementations bold and normal. This is incorrect. You should
talk about the font family Verdana and two fonts Verdana bold and
Verdana regular.
A PDF usually contains subsets of different fonts. It can even contain two different subsets of the same font. See also What are the extra characters in the font name of my PDF?
Your goal is to take the font of one PDF and to use that font of another PDF. However, suppose that your original PDF only contains the subset that is required to write "Hello World" and that you want to create a new PDF saying "Hello Universe." That will never work, because the subset won't contain the glyphs to render the letter U, n, i, v, r, and s.
Also take into account that fonts are usually licensed. Many fonts
have a license that states that you can use to font to create a
document and embed that font in that document. However, there is
often a clause that says that other people are not allowed to
extract to font to use it in a different context. For instance: you paid for the font when you purchased a copy of MS Windows, but someone
who receives a PDF containing that font may not have a license to use
that font. See Does one need to have a license for fonts if we are using ttf files in itext?
Given the technical and legal issues related to your question, I don't think it makes sense to work on a code sample. Your design is flawed. You should work with a licensed font program instead of trying to extract a font from an existing PDF. This answers question 3: How can I apply font got from the original document to the new paragraph? You can't: it is forbidden by law (see Extra info below) and it might be technically impossible if the subset doesn't contain all the characters you need!
Furthermore, the sample you found on the official iText web site looks for the fonts defined in a form. /Helv and ZaDb refer to Helvetica and Zapfdingbats. Those are two fonts of a set of 14 known as the Standard Type 1 fonts. These fonts are never embedded in the document since every viewer is supposed to know how to render them. You don't need a full font program if you want to use these fonts; the font metrics are sufficient. For instance: iText ships with 14 AFM files (AFM = Adobe Font Metrics) that contain the font metrics.
You wonder why you don't find Verdana, since Verdana is used as font for the text in your document, but you are looking at the wrong place. You are asking iText for the fonts used for the form, not for the fonts used in the text. This answer question 1: Why does this function returns two fonts instead of one (Verdana).
As for your question 2: you are looking at the internal name of the font, and that internal name can be anything (even /F1, /F2,...). The postscript name of the font is stored in the font dictionary. That's the name you need.
Extra info:
I checked the Verdana license:
Microsoft supplied font. You may use this font to create, display, and print content as permitted by the license terms or terms of use, of the Microsoft product, service, or content in which this font was included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content. Any other use is prohibited.
The use you want to make of the font is prohibited. If you have a license for Verdana, you can embed the font in a PDF. However, it is not permitted to extract that font and use it for another purpose. You need to use the original font program.
I am trying to draw a checkmark (found in the PDF standard ZapfDingbats font, Unicode 2714) in my PDF document. I'm a newbie to Apache's PDFBox, using version 2.0.0 at the moment (no specific reason except that it's the newest).
My code looks as follows:
PDDocument document = PDDocument.load(new File("myfile.pdf"));
PDPage page = document.getPages().get(0); // first page
PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true);
PDType1Font font = PDType1Font.ZAPF_DINGBATS;
String glyph = "\u2714";
contentStream.beginText();
contentStream.setFont(font, fontSize);
contentStream.newLineAtOffset(10, 10); // towards lower left corner of page
contentStream.showText(glyph);
contentStream.endText();
contentStream.close();
document.save("output.pdf");
document.close();
... but this produces a nice Exception:
Exception in thread "main" java.lang.IllegalArgumentException: U+2714 ('a20') is not available in this font's encoding: WinAnsiEncoding
at org.apache.pdfbox.pdmodel.font.PDType1Font.encode(PDType1Font.java:345)
at org.apache.pdfbox.pdmodel.font.PDFont.encode(PDFont.java:286)
:
Debugging through the code shows that what happens at PDType1Font.java:345 is:
(PDType1Font extends PDSimpleFont)
PDSimpleFont.glyphList correctly contains a mapping from the Unicode codepoint (U+2714) to a PDF name ("a20") as shown in the Exception text (set up in PDSimpleFont's constructor for the ZapfDingbat glyphs).
... but the PDSimpleFont.encoding, which is set to WinAnsiEncoding in PDType1Font's constructor line 110, does not contain the name a20 - these names (encodings) are set up statically in the WinAnsiEncoding class - see the WIN_ANSI_ENCODING_TABLE constant at line 36.
Has anyone managed showing Dingbat glyphs using PDFbox - even if in a lower version?
I suspect it is a bug (a20 should be converted to 064 according to "ZapfDingbats Set and Encoding" and I can't find where this is being done), please open an issue in JIRA. In the meantime, here's a workaround if you're using windows:
instead of
PDType1Font font = PDType1Font.ZAPF_DINGBATS;
use
PDFont font = PDType0Font.load(document, new File("c:/windows/fonts/arialuni.ttf"));
Update: now solved
This was indeed found to be a bug and JIRA issue PDFBOX-3298 addressed this. It is now resolved in PDFBox version 2.0.3.
I´m trying to create a PDF with PDFBOX-2.0.0-SNAPSHOT but I´m having problems and errors.
This is the typical Hello World example with Spanish and French characters:
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
PDType1Font font = PDType1Font.HELVETICA;
PDPageContentStream stream = new PDPageContentStream(document, page);
String text = "áÁÀà";
stream.beginText();
stream.setFont(font, 12);
stream.newLineAtOffset(100, 700);
stream.showText(text);
stream.endText();
stream.close();
document.save("sample.pdf");
document.close();
And I get this error:
sep 02, 2015 12:42:43 PM org.apache.pdfbox.pdmodel.font.PDType1Font <init>
ADVERTENCIA: Using fallback font ArialMT for base font ZapfDingbats
Exception in thread "main" java.lang.IllegalArgumentException: This font type only supports 8-bit code points
If I load arialuni.ttf font it compiles but only get question marks in the PDF file.
I have tried PDFBOX 1.8 and doesn´t work either.
Any idea?
Thanks in advance.
UPDATE:
After some test I realized that if you change the encoding of the project (at least in Intellij IDEA) and don´t retype the problematic characters in the code, the new encoding doesn´t take effect.
The PDType1Font.XXX are fonts which are provided by the PDF viewers itself which don't support unicode. You should be able to use a TTF font like on: https://github.com/apache/pdfbox/blob/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java
PDType0Font font = PDType0Font.load(document, new File("path/YourFont.ttf"));
I am using itext and ColdFusion (java) to write text strings to a PDF document. I have both trueType and openType fonts that I need to use. Truetype fonts seem to be working correctly, but the kerning is not being used for any font file ending in .otf. The code below writes "Line 1 of Text" in Airstream (OpenType) but the kerning between "T" and "e" is missing. When the same font is used in other programs, it has kerning. I downloaded a newer version of itext also, but the kerning still did not work. Does anyone know how to get kerning to work with otf fonts in itext?
<cfscript>
pdfContentByte = createObject("java","com.lowagie.text.pdf.PdfContentByte");
BaseFont= createObject("java","com.lowagie.text.pdf.BaseFont");
bf = BaseFont.createFont("c:\windows\fonts\AirstreamITCStd.otf", "" , BaseFont.EMBEDDED);
document = createobject("java","com.lowagie.text.Document").init();
fileOutput = createObject("java","java.io.FileOutputStream").init("c:\inetpub\test.pdf");
writer = createobject("java","com.lowagie.text.pdf.PdfWriter").getInstance(document,fileOutput);
document.open();
cb = writer.getDirectContent();
cb.beginText();
cb.setFontAndSize(bf, 72);
cb.showTextAlignedKerned(PdfContentByte.ALIGN_LEFT,"Line 1 of Text",0,72,0);
cb.endText();
document.close();
bf.hasKernPairs(); //returns NO
bf.getClass().getName(); //returns "com.lowagie.text.pdf.TrueTypeFont"
</cfscript>
according the socalled spec: http://www.microsoft.com/typography/otspec/kern.htm
OpenType™ fonts containing CFF outlines are not supported by the 'kern' table and must use the 'GPOS' OpenType Layout table.
I checked out the source, IText implementation only check the kern for truetype font, not read GPOS table at all, so the internal kernings must be empty, and the hasKernPairs must return false.
So, there have 2 way to solove:
get rid of the otf you used:)
patch the truetypefont by reading the GPosition table
wait for me, I'm processing the cff content, but PDF is optional of ever of my:) but not exclude the possibility:)
Have a look at this thread about How to use Open Type Fonts in Java.
Here is stated that otf is not supported by java (not even with iText). Otf support depends on sdk version and OS.
Alternatively you could use FontForge which converts otf to ttf.