How to use Fonts in iText PDF - java

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'

Related

re-embed subset font in pdf with itext 7

I have some input PDF all with full set fonts, I want to "shrink" them all creating fonts subset. I know there is the way to unembed fonts and embed subset font, but the problem is that i don't have the source file of fonts. I just have fonts embedded in source PDF.
Someone can help me to troubleshoot this issue ?
ENV: java8, itext7.1.5
Here's a thread on a similar question (about embedding, not subsetting, despite the OP's question): How to subset fonts into an existing PDF file. The following statement is relevant:
If you want to subset it, you'd need to parse all the content streams
in the PDF to find out which glyphs are used. That's NOT a trivial
task.
I wouldn't recommend attempting this in iText, unless it's really necessary. It would likely end up buggy unless you have a very complete understanding of the PDF specs. It might be worth pursuing other avenues such as changing the way the PDFs are created, or use something like Distiller that can do this for you.
If you do want to do this in iText, I'm afraid you will likely have to use a PdfCanvasProcessor and some custom operator handlers. You would need to find all text fields, determine which font they use, build a new subset font with the applicable glyphs, and replace the fonts with new subset copies. This is how you would create a copy of the complete font to prepare for subsetting (assuming you don't have copies of the font files):
String encoding = PdfEncodings.WINANSI; // or another encoding if needed for more glyph support
PdfFont completeFont = ...; // get complete font from font dictionary
PdfFont subsetFont = PdfFontFactory.createFont(completeFont.getFontProgram(), encoding, true);
subsetFont.setSubset(true);
When you encounter a Font change operator (Tf), you would need to look up that font in the font dictionary and create a new (or lookup an already created) subset copy of that font to prepare for upcoming text fields. Don't forget to keep the font in a stack so you can pop back to the previous font (look for q and Q operators). And don't forget to check parent forms and page groups for the fonts if they don't exist in the current XObject or page resource dictionary.
When you encounter text (a Tj, TJ, ', or " operator), you would need to decode the text using the complete font, then re-encode it to the new subset font's encoding (unless you know for sure that all your source fonts are ASCII-compatible). Add that text's characters to the subset like this:
subsetFont.addSubsetRange(new int[]{character});

How to add tab space to paragragh in itext java [duplicate]

I'm still trying to learn iText and have a few of the concepts down. However I can't figure out what TabStop is or how to use it. My particular problem is that I want to fill the end of all paragraphs with a bunch of dashes. I believe this is called a TabStop and I see the class in the itext jar but I have no clue on how to use it. I must be searching the wrong thing on google, but I've come up with nothing. The iText in Action book also doesnt seem to even know of the existance of this class so any help is much appreciated!
Please take a look at the ChunkTest class in iText's test suite. It contains several use cases of the tab stop functionality. For instance:
java.util.List<TabStop> tabStopsList = new ArrayList<TabStop>();
tabStopsList.add(new TabStop(100, new DottedLineSeparator()));
tabStopsList.add(new TabStop(200, new LineSeparator(), TabStop.Alignment.CENTER));
tabStopsList.add(new TabStop(300, new DottedLineSeparator(), TabStop.Alignment.RIGHT));
p = new Paragraph(new Chunk("Hello world", f));
p.setTabSettings(new TabSettings(tabStopsList, 50));
addTabs(p, f, 0, "la|la");
ct.addElement(p);
The TabStop functionality was introduced after the iText in Action books were written. They'll be documented in one of the new books.
For another example, see http://developers.itextpdf.com/examples/itext-building-blocks/tabbing-examples

Setting character spacing with PDFBox

I'm currently using Java and the PDFBox library to create some PDFs on the fly.
I need to be able to set the character spacing/tracking of some text but can't seem to figure it out.
It looks as there is a method to do so : http://ci.apache.org/projects/pdfbox/javadoc/index.html?org/apache/pdfbox/util/operator/SetCharSpacing.html
But I'm not quite sure how to apply this in the situation.
cs.beginText();
cs.setFont( font, fontSize );
cs.setNonStrokingColor(color);
cs.moveTextPositionByAmount(position[0], position[1]);
cs.drawString(text);
cs.endText();
Any help would be appreciated! Thanks.
You need to do it the hard way, because the "Tc" operator isn't supported by the PDPageContentStream class:
cs.appendRawCommands("0.25 Tc\n");
The SetCharSpacing method you mentioned is for parsing existing PDFs.
PS: don't forget to call close after finishing writing to the content stream!
PPS: setCharacterSpacing() is available in version 2.0.4 and higher.

Problems with Chinese Fonts in iText-PDF on Windows Machines

I'm using a Ubuntu-PC to create PDFs with iText which are partly in Chinese. To read them I use Evince. So far there were hardly any problems
On my PC I tried the following three BaseFonts and they worked with success:
bf = BaseFont.createFont("MSungStd-Light", "UniCNS-UCS2-H", BaseFont.NOT_EMBEDDED);
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
bf = BaseFont.createFont("MSung-Light","UniCNS-UCS2-H", BaseFont.NOT_EMBEDDED);
Unfortunately in the moment the final PDF is opened on Windows with the Acrobat-Reader the document can't be displayed correctly any more.
After I googled the Fonts to get a solution I came to that Forum where the problem is explained in an understandable way (Here MSung-Light was used): http://community.jaspersoft.com/questions/531457/chinese-font-cannot-be-seen
You are using a built-in Chinese font in PDF. I'm not sure about the
ability of this font to support both English and Chinese, or mixed
language anyway.
The advantage of using an Acrobat Reader built-in font is that it
produces smaller PDF files, because it relies on those fonts being
available on the client machine that display the PDF, through the
pre-installed Acribat Asian Font Pack.
However, using the PDF built-in fonts has some disadvantages that were
discovered through testing on different machines, when we investegated
a similar problem related to a built-in Korean font.
What should I do about it?
It's not so important to be able to copy the Chinese letters. Can iText convert a paragraph to an image? Or are there any better solutions?
You're using a CJK font. CJK fonts are never embedded and they require a font pack when opening such a file in Adobe Reader. Normally, Adobe Reader will ask you if you want to install such a font pack automatically. If it doesn't, you can download the appropriate font pack here.
It seems that you want to avoid having an end user install a font pack. That's understandable to some extent. What is really bad, is your suggestion to avoid using a font and to draw the glyphs one by one instead. This is possible with iText (and documented in my book), but it comes with a severe warning: Don't do this! Your file will be bloated and print results risk being awful!
An alternative is to use another font, e.g. arialuni.ttf, YaHei, SimHei,... These fonts contain Chinese glyphs and you can embed a subset of these fonts into your PDF (embedding the whole font would be overkill). See for instance the FontTest example.
If you have a font program such as arialuni.ttf, you can use this code to create a BaseFont object:
BaseFont.createFont("c:/windows/fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
With this font, you can display Chinese characters that will be visible using any viewer on any OS. If you don't have arialuni.ttf, you need to look for another font and use the FontText example to test if Chinese is supported (if you don't see any text after "Chinese:", then Chinese isn't supported).
Extra answer in reply to your comment:
Please forget about iText-Asian as that is a jar you need when you want to use CJK fonts. You explicitly say you don't want to use CJK fonts, so you don't need to use iText-Asian.
If you want to embed the font (as opposed to rely on a font pack), you need to pick a font program that knows how to draw Chinese characters. This immediately makes your question regarding "Can you point me to an example that draws Chinese characters?" void. I could point you to such an example, but you'd still need a font program.
Once you have that font program: why wouldn't you use it the correct way? You should use that font program the way you're supposed to use it. You shouldn't use that font program to draw your glyphs as images as that would result in a PDF file with a huge filesize and a bad resolution (bad quality of the glyphs because you draw each separate character instead of using the font program in the PDF).
Did you look for a font program yet? There was a similar question about Vietnamese fonts a while ago: Can't export Vietnamese characters to PDF using iText It took me less than a quarter of my time to Google for a font that could be used. Why don't you spend a quarter of your time finding a font that supports Chinese?
Extra answer in reply to your extra comment:
When we refer to CJK, we refer to a specific approach in which fonts aren't embedded, but rely on a font pack being installed on the end users machine, so that Adobe Reader can use that font. You don't want this so all your questions about using the itext asian jar and MSung-Light and so on are irrelevant.
The Chinese character set is huge and many computers ship without any Chinese fonts (especially in the US), so the answer to your question "Isn't there any way to use a built-in arialuni" is "No, you shouldn't count on that!"
What you say about Vietnamese is irrelevant. A font is a font is a font. You have a character code on one side and a glyph on the other side. The glue that connects one with the other is the encoding. For instance: You have the hexadecimal character code B2E2 and the hexadecimal character code CAD4. If the encoding is GBK, the corresponding glyphs are 测 and 试. Note that when you'd want to represent the very same characters in UNICODE, you'd use the characters 6D4D and 8BD5. There is very little difference with other systems. For instance: you have the hexadecimal character code 41 (65 in decimals) and if the encoding is Latin-1, the corresponding glyph is A.
I have asked you to search for a font that supports Chinese. I have opened Google and I searched for the keywords "Chinese fonts". I found this page: http://www.freechinesefont.com/ and I picked a font that seemed OK to me: http://www.freechinesefont.com/simplified-hxb-mei-xin-download/
Now I use this code snippet:
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
public class ChineseTest {
/** Path to the resulting PDF file. */
public static final String DEST = "results/test.pdf";
/** Path to the vietnamese font. */
public static final String FONT = "resources/hxb-meixinti.ttf";
/**
* Creates a PDF file: hello.pdf
* #param args no arguments needed
*/
public static void main(String[] args) throws DocumentException, IOException {
new ChineseTest().createPdf(DEST);
}
/**
* Creates a PDF document.
* #param filename the path to the new PDF document
* #throws DocumentException
* #throws IOException
*/
public void createPdf(String filename) throws DocumentException, IOException {
// step 1
Document document = new Document();
// step 2
PdfWriter.getInstance(document, new FileOutputStream(filename));
// step 3
document.open();
BaseFont bf = BaseFont.createFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font font = new Font(bf,15);
// step 4
document.add(new Paragraph("\u6d4b\u8bd5", font));
// step 5
document.close();
}
}
The result looks like this on Windows:
How is this different from Vietnamese? The word test is displayed correctly in Chinese. A subset of the font is embedded, which means you can keep the file size low. The text is not embedded as an image which means the quality of the text is excellent.
Extra answer in answer to your extra comment: In your comment, you claim that the example that uses the file hxb-meixinti.ttf requires the installation of a font. That is incorrect. hxb-meixinti.ttf is merely a file that is read by iText and used to embed the definition of specific glyphs (a subset of the font) into a PDF.
When you write: Related to a Font-Program: Java seems to be able to do it without using external software. Java is able to use fonts because Java uses font files, just the same way as iText uses font files.
For more info, read Supported Fonts in the Java manual. I quote:
Physical fonts need to be installed in locations known to the Java
runtime environment. The JRE looks in two locations: the lib/fonts
directory within the JRE itself, and the normal font location(s)
defined by the host operating system. If fonts with the same name
exist in both locations, the one in the lib/fonts directory is used.
What I tried explaining (and what you have been ignoring since the start of this thread) is that iText needs access to a physical font. iText can accept a font from file or as a byte[], but you need to provide something like a TTF, OTF, TTC, AFM+PFB. This is not different from how Java works.
In your comment you also say that you want Adobe Reader to accept a byte stream instead of reading a PDF from file. This is not possible. Adobe Reader always requires the presence of the PDF file on disk. Even if the PDF file is served by a browser, the bytes of the PDF are stored as a temporary file. This is inherent to your request that the file needs to be viewed in Adobe Reader.
The rest of your comment is unclear. What do you mean by If everyone would just upload anything he might need a switch causes difficulties. Are you talking about downloading instead of uploading? Also: I gave you a solution that doesn't require downloading anything extra on the client side, yet you keep on nagging that no one will install anything on Acrobat.
As for your remark For BS I got a solution recently, I have no idea what you mean by BS.

itext font UnsupportedCharsetException

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.

Categories

Resources