I am trying to create pdf documents using iText (version 5.4.0) in a java web application and I have come across an issue with fonts.
The web application is multi-lingual, and so users may save information into the system in various languages (eg. english, french, lithuanian, chinese, japanese, arabic, etc.).
When I tried to configure the pdf to output some sample japanese text it didn't show up, so I started following the examples in the official "iText in Action" book. The problem I have encountered is that when I try and configure a font with BaseFont.IDENTITY_H encoding I get the following error:
java.nio.charset.UnsupportedCharsetException: Identity-H
at java.nio.charset.Charset.forName(Charset.java:505)
at com.itextpdf.text.pdf.PdfEncodings.convertToBytes(PdfEncodings.java:186)
at com.itextpdf.text.pdf.Type1Font.<init>(Type1Font.java:276)
at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:692)
at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:615)
at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:450)
Nothing in the book or searching Google mentions this issue.
Any suggestions as to what I might have missed?
As you probably understood from the answers from two Michaels, you made the wrong assumption that the standard Type 1 font Times Roman and IDENTITY_H are compatible. You'll have to change the font if you want to use IDENTITY_H, or change the encoding if you want to use a standard Type 1 font (in which case using BaseFont.EMBEDDED doesn't make sense because standard Type 1 fonts are never embedded). I'm sorry if I didn't mention this in my book. I thought it was kind of trivial. One can deduct it from what I wrote about composite fonts.
I don't think there's any one encoding that works for all languages, with font embedding. For example, you'd assume that choosing the UTF-8 encoding, with font embedding set to true will embed the font, but it doesn't.
I find myself having to do this, because I don't know the language of the text ahead of time:
try {
// Try to embed the font.
// This doesn't work for type 1 fonts.
return FontFactory.getFont(fontFace, BaseFont.IDENTITY_H,
true, fontSize, fontStyle, textColor);
} catch (ExceptionConverter e) {
return FontFactory.getFont(fontFace, "UTF-8", true,
fontSize, fontStyle, textColor);
}
(The exception class may be different since I'm using an older version of iText -- 2.1.)
As with a lot of iText stuff, this is poorly documented, and makes the easy stuff unnecessarily hard.
Related
Is there a way to check if otf font file contains glyphs for small caps variation?
Is there a way to do it in java?
Thanks!
There is, just don't use standard-library-Java for it. Use either a Java OpenType font analyser, or do the more sensible thing and consult Freetype2 or Harfbuzz for that information.
Really, anything that lets you check OpenType features will do: check whether the font encodes for the smcp feature - if it does, it support proper smallcaps as per the OpenType spec. If not, it doesn't, and whatever text engine you're using is going to fake it.
I fill forms with field.setValue. However even though PDF document has embedded fonts in it, I am getting error "is not available in this font's encoding: WinAnsiEncoding" no matter which type of font it is. Note that this is happening for chinese or russian characters.
Your PDF documents may have embedded fonts but they apparently have been embedded with an Encoding value WinAnsiEncoding.
WinAnsiEncoding contains essentially the Latin-15 characters, so it is intended for “Western European” languages (see the Wikipedia article on this) and in particular neither for Cyrillic nor for CJK languages.
If you want to fill chinese or russian characters into form fields using PDFBox, therefore, you have to
either embed a font into your PDF using an appropriate encoding beforehand
or replace the embedded font with PDFBox right before setting the form field value, see for example this answer.
I have a java application where i have to use "Bodoni MT Black" font using FontFactory in itextPdf how should i modify my code?
This is my code,
Font base = FontFactory.getFont(FontFactory.TIMES_ROMAN, 6);
how to change font to "Bodoni MT Black" (Not supported in FontFactory) instead of TIMES_ROMAN? please help.
The code in your question is code that uses iText 5. However, iText 5 is no longer supported. The current version of iText is iText 7.1.2:
If you are working on a new project, you should abandon iText 5 and upgrade to iText 7 because all new development will be done on iText 7, not on iText 5. Suppose that at some point you need support for PDF 2.0, then you'll need to throw away your iText 5 code, because support for PDF 2.0 will never be supported in iText 5. Suppose that at some point you need support for SVG in the context of HTML to PDF conversion, you will need to throw away all your iText code and start anew with iText 7.
The iText 7 solution
If you follow my advice and upgrade, then you should read the iText 7 tutorial chapter about fonts: https://developers.itextpdf.com/content/itext-7-building-blocks/chapter-1
This tutorial explains that you need a font program if you don't want to use one of the standard Type 1 fonts such as times roman. Mpre specifically, if you want to use "Bodoni MT Black", you need the file BodoniMTBlack.ttf somewhere on your computer, for instance:
public static final String BODONIBLACK = "src/main/resources/fonts/BodoniMTBlack.ttf";
Next, you can use this path to create a FontProgram object obtained from the FontProgramFactory:
FontProgram fontProgram = FontProgramFactory.createFont(BODONIBLACK);
Using the FontProgram instance, you can create a PdfFont object.
PdfFont font = PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true);
The font instance can be used as a parameter for the setFont() method:
Paragraph bodoni = new Paragraph().setFont(font).add("Bodoni");
The iText 5 solution
In the unlikely event that you don't have any other choice than to use iText 5, then you should read the Using fonts in PDF and iText
Just like with iText 7 you need a font program:
public static final String BODONIBLACK = "src/main/resources/fonts/BodoniMTBlack.ttf";
Now you can create a Font object like this:
BaseFont baseFont = BaseFont.createFont(BODONIBLACK, BaseFont.WINANSI, BaseFont.EMBEDDED);
Font bodoni = new Font(basefont, 12);
Additional note:
Stack Overflow has introduced a new Code of Conduct that aims to create a healthier atmosphere on the web site (be kind, contribute, show respect are some of the aspects highlighted in its subtitle).
In the context of that Code of Conduct, I want to inform you that you can contribute to a better atmosphere in the future by using the information that is provided on the official iText web site before asking a question.
When you are using iText and you are confronted with an iText-related question, your first reflex should be to visit the official iText web site where you will find the information I summarized above. People have done a great effort writing tutorials in answer to questions similar to yours. By ignoring that great content, you fail to appreciate the hard work that was done. Please take that into consideration in the future.
One important note on Bruno's answer above. (my rep<50, so cannot comment on his answer).
FontProgramFactory (at least in C#) is found in 'iText.IO.Font.FontProgramFactory'.
I was initially looking in a different 'Font' namespace : 'iText.Kernel.Font'.
And as Bruno says, all of this can be found on their website. This particular tibdit is at:
https://api.itextpdf.com/iText7/7.0.1/com/itextpdf/io/font/FontProgramFactory.html
So perhaps my note should just be deleted based on the Code of Conduct. Someone else can decide. But as I found Bruno's info helpful here, perhaps this note will save someone a few minutes.
Also, turns out that (at least for me in C#) the 'C' in .createFont needs to be capitalized. So...
'PdfFontFactory.CreateFont' rather than 'PdfFontFactory.createFont'
I need to render the below String on a JTable cell. How do we do this?
testä漢字1ગુજરાતી2
Update:
Looks like my question is not clear. The above string is a name of file. Need to display this and many other file names in JTable. Data comes dynamically. I may need a custom renderer to display this string exactly same. Currently, this displays junk characters. Simply changing the table Font from Calibri to MS Gothic, I can see the chinese characters, but not indic letters. But, as the data comes dynamically, we won't be knowing what font to use.
So, want to know if there is way so that I can check the string programmatically and render the string with different fonts as appropriate.
The simplest solution would be to use a font which is more complete. I believe the DejaVu family is decent, others may be able to suggest better. The Oracle manual suggests that the logical fonts Dialog, DialogInput, Monospaced, Serif and SansSerif are also likely to be more complete. Potentially they could map to multiple underlying fonts depending on the specific characters which need to be rendered. Oracle also mentions the Lucidia family which is distributed with Oracle's JRE as another possibility which is fairly complete, though it doesn't have Chinese, Korean or Japanese characters.
A more convoluted solution would be to run Character.UnicodeBlock.of(c) on the characters in each string, assemble a Set<Character.UnicodeBlock> and guess which font is most appropriate based on the blocks present in the string, or even write a custom renderer to render each character (or sequence of characters) with a font appropriate to the Unicode block they belong to. Unicode blocks tend to be categorized according to the script they contain.
I am developing a java game and I need characters, such as monsters and doors etc. I am trying to include them with the help of chars and unicode. However, some chars, such as a key, '\u26BF', do not show up properly in the terminal of the game, but rather as a box. Do I need to import some special fonts or how else would I solve this problem?
GNU Unifont is reported as containing this Glyph. As it comes under the GNU public licence it is not subject to any licence fee.
Home page: http://unifoundry.com/unifont.html
It has TrueType, which should work wiht Java.
Like people already pointed out in the comments sections, you will have to use another font containing those special characeters.
The font you are using seems to not support those characters, you can download any other font containing those character(s). The character 'u26BF' is a square box in some default fonts (source).
You can find different fonts and even try them out on DaFont and, like #SubOptimal warned you, check the licenses also before you download & use it.