We are evaluating Itext7 (hence I am fairly new to IText7) and would like to change the font in a table. Of course changing the font on the table is easy once I have the font, however creating the font is challenging. I have found simple examples
font = PdfFontFactory.createFont(FontConstants.TIMES_ITALIC, PdfEncodings.WINANSI);
but I would like to control the size, family, etc. of the font as well. I have found examples for previous versions of Itext that seem pretty straightforward.
BaseFont helvetica = BaseFont.createFont(HELVETICA, CP1252, EMBEDDED);
Font font = new Font(helvetica, 12, Font.NORMAL);
Thanks for any help.
iText 7 is fairly new. There's iText 7: Jump-Start tutorial to get you started, but we still need to write many tutorials about specific aspects of iText 7.
Fortunatly, the question you've posted has already been dealt with in the second iText 7 tutorial iText 7: Building Blocks. The information you need is in Chapter 1: Introducing the PdfFont class.
When you read this chapter, you'll understand that the size of the font shouldn't be a property of the PdfFont class. Instead, you define the font size at the level of the object that uses this font.
For instance:
Text title1 = new Text("The Strange Case of ").setFontSize(12);
Text title2 = new Text("Dr. Jekyll and Mr. Hyde").setFontSize(16);
Text author = new Text("Robert Louis Stevenson");
Paragraph p = new Paragraph().setFontSize(8)
.add(title1).add(title2).add(" by ").add(author);
document.add(p);
In this case, "The Strange Case of " has a font size of 12; "Dr. Jekyll and Mr. Hyde" has a font size of 16; " by " and "Robert Louis Stevenson" have a font size of 8, because that size is defined at the level of the Paragraph. The font size of " by " is the font size of the Paragraph. No font size was defined for "Robert Louis Stevenson", which means that this Text object inherited the font size of the Paragraph to which it belongs.
I'm currently working on chapter 2. You'll notice that iText 7 now allows you to change the default font size for a Document by defining the font at the Document level. This is one of the many improvements of iText 7.
Related
I am on the mainframe platform and uploaded the arial.ttf from Windows. I used the following code for the font, but the font does not show SUBSETTED or EMBEDDED in Adobe. I even tried to add font.getBaseFont to force it to embed.
Any reason why it would not embed or subset?
String font1 = "arial.ttf";
FontFactory.register(font1,"myfont");
BaseFont bf = BaseFont.createFont(font1, BaseFont.IDENTITY_H, true);
Font font = FontFactory.getFont("arial");
font.getBaseFont().setSubset(true);
Adobe doc show the following font information:
Type truetype
Encoding Ansi
Actual Font: ArialMT
Actual Font type: TrueType
You create a BaseFont object bf, but you aren't doing anything with it. One would expect that you do this:
BaseFont bf = BaseFont.createFont(pathToFont, BaseFont.IDENTITY_H, true);
Font font = new Font(bf, 12);
In this case, font would make sure that a subset of the font is embedded because the encoding is Identity-H and iText always embeds a subset of a font with that encoding.
As you aren't doing anything with bf, it is as if the line isn't present. In that case, we are left with:
String font1 = "arial.ttf";
FontFactory.register(font1,"myfont");
Font font = FontFactory.getFont("arial");
Assuming that the path to arial.ttf is correct, and that the alias of that font is "arial", you are now creating a font with the default encoding (Ansi), the default font size (12) and the default embedding (false).
That is in line with what is shown in Adobe Reader. If you want a subset of the font to be embedded, you need at least:
Font font = FontFactory.getFont("arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
In answer to your question: the reason why the font is not embedded by iText is the fact that you are not telling iText to embed the font.
I am trying to create a PDF on z/OS using JZOS and iText.
I have tried so many combinations for the font as well as the DefaultPlatformEncoding but I just don't seem to be able to get the Arabic characters to display in the PDF. They display as Latin characters. When I turn the PDF compression off and display the hex characters, I see the EBCDIC hex codes.
The input file on z/OS is IBM-420 and the output PDF should have Cp1256 or Windows-1256 for display on Windows.
Here is the snippet of the code:
// Open the input dataset
ZFile zFilein = new ZFile("//DD:INDS", "rb,type=record,noseek");
// Open the output PDF file
PdfWriter writer = PdfWriter.getInstance(document,
FileFactory.newBufferedOutputStream("//DD:OUTPDF"));
document.open();
// Font cf = new Font(Font.FontFamily.COURIER, Font.DEFAULTSIZE, Font.NORMAL);
// Font cf = FontFactory.getFont("Courier","Cp1256", true);
Font cf = FontFactory.getFont("Arial", BaseFont.IDENTITY_H, true, Font.DEFAULTSIZE, Font.NORMAL);
Paragraph paragraph = new Paragraph();
paragraph.setFont(cf);
String encoding = ZUtil.getDefaultPlatformEncoding();
// String encoding = "Cp1256";
String line = new String(recBuf,1,nRead-1,encoding);
paragraph.add(line);
I tried the following options but still unable to get the PDF to display correctly and also
the PDF Font information does not show the font as EMBEDDED. Anything else I missed?
Note: arial.ttf was uploaded from WINDOWS
Option 1
FontFactory.register("arial.ttf");
Font cf = FontFactory.getFont("Arial", 8);
paragraph = new Paragraph(line, cf);
The FONT information in the PDF displays the following:
ArialMT
Type: TrueType
Encoding: Ansi
Actual Font: ArialMT
Actual Font Type: TrueType
Option 2
BaseFont bf = BaseFont.createFont(font1, BaseFont.IDENTITY_H, true);
Font cf = new Font(bf, 10);
paragraph = new Paragraph(line, cf);
Viewing the PDF display the following error:
Cannot extract the embedded font 'ZQRNLC+ArialMT'. Some characters may not display or
print correctly.
Viewing the source of the PDF in an editor I can see the following:
R/FontName/ZQRNLC+ArialMT/
The FONT in the PDF displays the following information:
ArialMT
Type: TrueType(CID)
Encoding: Identity-H
Actual Font: Unknown
Your question is a duplicate of several other questions.
This line of code may be problematic:
Font cf = FontFactory.getFont("Arial", BaseFont.IDENTITY_H, true, Font.DEFAULTSIZE, Font.NORMAL);
This won't give you the font Arial unless you have registered an Arial font program as explained in my answer to the question
"Why doesn't FontFactory.GetFont("Known Font Name", floatSize) work?"
I don't know z/OS (never heard of it), but if it uses EBCDIC, it's doing something wrong. Your strings need to be in UNICODE. It is very important that the String values you are using are in the right encoding as explained in my answer to the question "getBytes() doesn't work for Cyrillic letters". In your case, you are reading the content from a file, but there is no guarantee that the encoding you use to read the file matches the encoding that was used to store the file. When you say that the glyphs are shown in EBCDIC, I think that you're mistaken and that you experience the same problem as explained in "getBytes() doesn't work for Cyrillic letters". You really need Unicode.
You say that you want to create text in Arabic, but I don't see you using the RTL setting anywhere. This is explained in my answer to this question: "how to create persian content in pdf using eclipse".
Please download the free ebook "The Best iText Questions on StackOverflow" and you'll notice that all these problems have been asked and answered before. I would like to close your question as a duplicate of how to create persian content in pdf using eclipse, but unfortunately, that answer wasn't accepted and it didn't receive an upvote, so it can't be used as an original question to mark another question as a duplicate.
This is wrt iText 2.1.6.
I have a string containing characters from different languages, for which I'd like to pick a single font (among the registered fonts) that has glyphs for all these characters. I would like to avoid a situation where different substrings in the string are printed using different fonts, if I already have one font that can display all these glyphs.
If there's no such single font, I would still like to pick a minimal set of fonts that covers the characters in my string.
I'm aware of FontSelector, but it doesn't seem to try to find a minimal set of fonts for the given text. Correct? How do I do this?
iText 2.1.6 is obsolete. Please stop using it: http://itextpdf.com/salesfaq
I see two questions in one:
Is there a font that contains all characters for all languages?
Allow me to explain why this is impossible:
There are 1,114,112 code points in Unicode. Not all of these code points are used, but the possible number of different glyphs is huge.
A simple font only contains 256 characters (1 byte per font), a composite font uses CIDs from 0 to 65,535.
65,535 is much smaller that 1,114,112, which means that it is technically impossible to have a single font that contains all possible glyphs.
FontSelector doesn't find a minimal set of fonts!
FontSelector doesn't look for a minimal set of fonts. You have to tell FontSelector which fonts you want to use and in which order! Suppose that you have this code:
FontSelector selector = new FontSelector();
selector.addFont(font1);
selector.addFont(font2);
selector.addFont(font3);
In this case, FontSelector will first look at font1 for each specific glyph. If it's not there, it will look at font2, etc... Obviously font1, font2 and font3 will have different glyphs for the same character in common. For instance: a, a and a. Which glyph will be used depends on the order in which you added the font.
Bottom line:
Select a wide range of fonts that cover all the glyphs you need and add them to a FontSelector instance. Don't expect to find one single font that contains all the glyphs you need.
We are using iTextSharp to create PDF's using a custom font and I am running into an issue with the unicode character 2120 (SM, Service Mark). The problem is the glyph is not in the custom font. Is there a way I can specify a fallback font for a field in a PDF? We tried adding a text field with Verdana so that the form had the secondary font embedded in it but that didn't seem to help.
First you need to find a font (ttf, otf,...) that has the character you need. Then you can use the FontSelector class and add the different fonts you want to use to this selector (see the FontSelectionExample). Now you can process every string:
FontSelector selector = new FontSelector();
selector.addFont(f1);
selector.addFont(f2);
Phrase ph = selector.process(some_string);
The FontSelector will return a phrase that consists of Chunks with font f1 for all the glyphs that are available in the first font, and Chunks with font f2 for the glyphs that couldn't be font in f1, but that are present in f2.
If you want the C# port of this example, please consult chapter 11.
Update
Using a FontSelector also works in the context of forms (as long as we're talking about AcroForm technology). It's really easy: you just need to add substitutions fonts to the form:
AcroFields form = stamper.getAcroFields();
form.addSubstitutionFont(bf1);
form.addSubstitutionFont(bf2);
Now the font defined in the form has preference, but if that font can't show a specific glyph, it will look at bf1, then at bf2 and so on. You can find an example demonstrating this functionality here.
Note that there's a difference between the first and the second example. In the first example we use a Font object, in the second, we use a BaseFont object.
I'm trying to set up a CTFrame that exactly matches my UITextView's text format in iPad.
First of all, I converted UITextView's text to an attributed string. Then I set up a width and a height of drawing box in which Core Text will draw text.
I succeeded to draw text using Core Text, but UITextView and Core Text show slightly different results even though I used the same font and size.
Specifically, when I used [UIFont systemFontOfSize:21], each space in UITextView has one more pixel than Core Text's result.
It's okay for a short sentence or word, but if UITextView and Core Text have multiple lines, their result become very different. For example, UITextView performs word-wrapping for one word at the end of line, while Core Text keeps that word in the same line. If you see the attached picture, the start positions of the last word "paragraph" are already very different (8 pixel gap due to 8 space characters).
More badly, if I use different fonts such as a custom font added to my project, each character in UITextView has 1 pixel more.
I'm using Core Text to find the pixel-position of the current cursor in UITextView, so both of them should perfectly match each other, containing the same number of characters and words in each line.
Question: Is there a way to make Core Text object that perfectly matches UITextView's text format?
Thank you!
Here's a code how I set up attributed string. (I just followed Core Text Guide.)
CTFontRef font = CTFontCreateWithName((CFStringRef) [UIFont systemFontOfSize:21.0].fontName, 21.0, NULL);
CFMutableAttributedStringRef attrString2 = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString2, CFRangeMake(0, 0), (CFStringRef) string);
CFAttributedStringSetAttribute(attrString2, CFRangeMake(0, [string length]),kCTFontAttributeName, font);
-
-
Here's a picture.
Your solution might work for a specific font at a specific point size, but you can't rely on it in general.
CoreText is simply not compatible with normal UILabels, UITextView:s or UIStringDrawing, so you can't mix them.
Either you have to use only CT functions for all string handling (including implementing custom input if that is what you need) or not use them at all.
Answer to myself.
I just found very simple solution! Using any font editor, you can just change the width of space character (ascii value 32); an original font for UITextView and a modified font for Core Text or vice versa. I used a freeware font editor FontForge. Though I still have to do some extreme-case tests such as writing Japanese characters and English alphabets in the same line and so on, now it becomes almost possible to find a pixel-position of a cursor/caret in UITextView.