OpenType font kerning with itext - java

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.

Related

PdfBox write hindi characters in pdf file

I tried many things to write hindi characters using Apache PdfBox but seems its existing issue in the library.
I tried many font files available, Can someone really help me out in this.
I tried following :
PDDocument doc = new PDDocument();
PDPage page = new PDPage();
doc.addPage(page);
PDFont font = PDTrueTypeFont.loadTTF( doc, new FileInputStream(new File("D:\\Data\\fonts\\dn.ttf")));
font.setFontEncoding(new WinAnsiEncoding());
PDPageContentStream content = new PDPageContentStream( doc, page, true, false );
content.setFont(font, 10);
content.beginText();
content.moveTextPositionByAmount( 200, 100 );
content.drawString( "हिंदी" ); // Writing word "Hindi" in hindi language.
content.endText();
content.close();
doc.save( new FileOutputStream(new File("D:\\testOutput1.pdf")));
doc.close();
It's working for me in PDFBox.
The trick here is to use non-unicode string instead of unicode string.
Use Kruti Dev Font given in below link.
Then convert your unicode string to non-unicode string.
And finally use that converted string in your code.
That means replace this like
content.drawString( "हिंदी" ); // Writing word "Hindi" in hindi language.
With this line
content.drawString( "fganh" ); // Writing word "Hindi" in hindi language.
Convert Unicode (Mangal) To Kruti Dev Font
I think this cannot be done using PdfBox as there are lot of issues with it.
I tried many fonts and the encoding types of PdfBox but failed to write in Hindi.
At the end I tried it in Node Js express pdfmaker() which converts Html to PDF, However I had issues on my Linux server and I installed appropriate ttf font and it worked !

PDFBox "This font does not permit subsetting" - Possible to use font without subsetting?

I used PDFBox (2.0.11) to create/edit PDFs and struggled with the usage of two fonts that always lead to an exception as follows
This font does not permit subsetting
Even though it is possible to subset the fonts with other tools like Everything fonts without any issues.
Is it possible to use a font with PDFbox without subsetting it or are there any other ways to solve this problem?
Exception message:
Exception in thread "main" java.io.IOException: This font does not permit subsetting
at org.apache.pdfbox.pdmodel.font.TrueTypeEmbedder.subset(TrueTypeEmbedder.java:298)
at org.apache.pdfbox.pdmodel.font.PDType0Font.subset(PDType0Font.java:239)
SOLVED:
Here is a working example on how to load a font without subsetting it:
File fontFile1 = new File("/fonts/fontfile.ttf");
InputStream fontFile1Stream = new FileInputStream(fontFile1);
PDType0Font product_title_font = PDType0Font.load(doc, fontFile1Stream, false);
Yes, you can still use the font without subsetting, use
PDType0Font.load(PDDocument doc, InputStream input, boolean embedSubset)
with the last parameter = false. Your files will be bigger, that's all. If another product can subset the font, then it means either that it doesn't respect the license settings, or that there's a bug in PDFBox. Open your font in a tool that can display the os2 table, e.g. DTL OTMaster Light. There look for the "fstype" entry.
https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fstype

How to reuse font from one pdf in another in iText7?

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.

Drawing glyph from ZapfDingbats using PDFbox

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.

IText Unicode Indic characters are not diplayed Properly

I am using Itext for PDF Generation.
I have Text In Marathi.
but Itext is generation that text without Glyph Substitution.
For Example :
Text Should Be : ल्ल
But iText Showing in PDF : लल
.
Same as
Text should be : क्ष्म
But iText Showing in PDF : कष
I have using windows Sytem file for font .e. arial unicode font.
And Code is
BaseFont base=BaseFont.createFont("c:/windows/fonts/ARIALUNI.ttf",BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
i am using itext Version itext-5.4.3.jar.
Please give me solution.In what way i should procceed.
Thank you
You need to add unicode with your string when you're passing as input.The unicode for bangla or Hindi is
\u0986\u09ae\u09bf \u0995\u09cb\u09a8 \u09aa\u09a5\u09c7
\u0995\u09cd\u09b7\u09c0\u09b0\u09c7\u09b0 \u09b7\u09a8\u09cd\u09a1
\u09aa\u09c1\u09a4\u09c1\u09b2 \u09b0\u09c1\u09aa\u09cb
\u0997\u0999\u09cd\u0997\u09be \u098b\u09b7\u09bf
Here is the Example
I got Solution...
The solution is That IText currently not support (as per my searching) Indic languages such as Marathi.
It's language parser is yet not completely mature for indic Language.
As it is open source,i was using it.
Now,I have moved to Apache FOP 1.1.
It support indic Languages.But important con is that it is resource intensive.In other word, it is slower than IText.
Thank You...

Categories