iText 7: How to build a paragraph mixing different fonts? - itext

I've been using iText 7 for a few days to build pdf files, unfortunately, iText 7 is very different from iText 5 and the documentation is still very incomplete.
I'm trying to build a paragraph that mixes two fonts or two fonts style (example: have a bold text in the middle of a paragraph)
Using iText 5 this would be done using Chunks:
Font regular = new Font(FontFamily.HELVETICA, 12);
Font bold = Font font = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
Phrase p = new Phrase("NAME: ", bold);
p.add(new Chunk(cc_cust_dob, regular));
PdfPCell cell = new PdfPCell(p);
Using iText 7, I still haven't found way to do this.
Has anyone tried to do this using the last version of iText?
Note: I'm using the csharp but java is also useful

Please read the documentation, more specifically iText 7: building blocks "Chapter 1: Introducing the PdfFont class"
In that chapter, you'll discover that it's much easier to switch fonts when using iText 7, because you can work with default fonts and font sizes, you can define and reuse Style objects, and so on.
An example:
Style normal = new Style();
PdfFont font = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
normal.setFont(font).setFontSize(14);
Style code = new Style();
PdfFont monospace = PdfFontFactory.createFont(FontConstants.COURIER);
code.setFont(monospace).setFontColor(Color.RED)
.setBackgroundColor(Color.LIGHT_GRAY);
Paragraph p = new Paragraph();
p.add(new Text("The Strange Case of ").addStyle(normal));
p.add(new Text("Dr. Jekyll").addStyle(code));
p.add(new Text(" and ").addStyle(normal));
p.add(new Text("Mr. Hyde").addStyle(code));
p.add(new Text(".").addStyle(normal));
document.add(p);
First we define a Style that we call normal and that uses 14 pt Times-Roman. Then we define a Style that we call code and that uses 12 pt Courier in Red with a gray background.
Then we compose a Paragraph using Text objects that use these styles.
Note that you can chain add() comments, as is done in this example:
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);
We set the font size of the newly created Paragraph to 8 pt. This font size will be inherited by all the objects that are added to the Paragraph, unless the objects override that default size. This is the case for title1 for which we defined a font size of 12 pt and for title2 for which we defined a font size of 16 pt. The content added as a String (" by ") and the content added as a Text object for which no font size was defined inherit the font size 8 pt from the Paragraph to which they are added.
This is a copy/paste from the official tutorial. I hope this is sufficient for StackOverflow where "link-only" answers aren't allowed. This "no link-only answers rule" shouldn't lead to copy/pasting a full chapter of a manual...

Related

How can I generate a PDF/UA compatible PDF with iText?

We have a number of dynamically generated printable forms files on our site that use iText 4.2.0. However, we also have a large number of users that have print disabilities and use screen readers, like JAWS, to render our PDFs. We use the .setTagged() method to tag the PDFs, but some elements of the PDF appear out of order. Some even become more jumbled after calling setTagged!
I read about PDF/UA in a 2013 interview about iText with Bruno Lowagie, and this seems like something that might help with our problem. However, I have not been able to find a good example of how to generate a PDF/UA document. Can you provide an example? Also, what is the minimum version of iText we will need to generate a PDF/UA compliant PDF document?
Please take a look at the PdfUA example. It explains step by step what is needed to be compliant with PDF/UA. A similar example was presented at the iText Summit in 2014 and at JavaOne. Watch the iText Summit video tutorial.
public void createPdf(String dest) throws IOException, DocumentException {
Document document = new Document(PageSize.A4.rotate());
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
writer.setPdfVersion(PdfWriter.VERSION_1_7);
//TAGGED PDF
//Make document tagged
writer.setTagged();
//===============
//PDF/UA
//Set document metadata
writer.setViewerPreferences(PdfWriter.DisplayDocTitle);
document.addLanguage("en-US");
document.addTitle("English pangram");
writer.createXmpMetadata();
//=====================
document.open();
Paragraph p = new Paragraph();
//PDF/UA
//Embed font
Font font = FontFactory.getFont(FONT, BaseFont.WINANSI, BaseFont.EMBEDDED, 20);
p.setFont(font);
//==================
Chunk c = new Chunk("The quick brown ");
p.add(c);
Image i = Image.getInstance(FOX);
c = new Chunk(i, 0, -24);
//PDF/UA
//Set alt text
c.setAccessibleAttribute(PdfName.ALT, new PdfString("Fox"));
//==============
p.add(c);
p.add(new Chunk(" jumps over the lazy "));
i = Image.getInstance(DOG);
c = new Chunk(i, 0, -24);
//PDF/UA
//Set alt text
c.setAccessibleAttribute(PdfName.ALT, new PdfString("Dog"));
//==================
p.add(c);
document.add(p);
p = new Paragraph("\n\n\n\n\n\n\n\n\n\n\n\n", font);
document.add(p);
List list = new List(true);
list.add(new ListItem("quick", font));
list.add(new ListItem("brown", font));
list.add(new ListItem("fox", font));
list.add(new ListItem("jumps", font));
list.add(new ListItem("over", font));
list.add(new ListItem("the", font));
list.add(new ListItem("lazy", font));
list.add(new ListItem("dog", font));
document.add(list);
document.close();
}
You make the document tagged with the setTagged document, but that's not sufficient. You also need to set document data: the document title needs to be displayed and you need to indicate the language used in the document. XMP metadata is mandatory.
Furthermore you need to embed all fonts. When you have images, you need a alternate description. In the example, we replace the words "dog" and "fox" by an image. To make sure that these images are "read out loud" correctly, we need to use the setAccessibleAttribute() method.
At the end of the example, I added a numbered list. In your duplicate question https://stackoverflow.com/questions/28222490/numbered-list-across-a-page-break-causes-jaws-to-read-numbers-out-of-order-in-it, you claim that the list is not read out loud correctly by JAWS. If you check the PDF file created with the above example, more specifically pdfua.pdf, you'll discover that JAWS reads the document as expected, with the numbers and the text in the right order.
The reason why "it doesn't work" when you try this, is simple. You claim that you are using iText, but you are not. You are using a "gork" of iText. A "gork" is an unofficial "fork" of which God Only Really Knows what's inside. You need the latest iText version to achieve what you want because PDF/UA is a standard dating from 2012 and you are using a version of iText that dates from 2009.
I suggest that you delete that other question because:
it is a duplicate of this question (if you disagree, read my answer: isn't it exactly what you're asking in both questions?),
it is off-topic in the sense that it sounds like "I am using an ancient DVD player and it doesn't want to play my blue ray disks." (I know that you downvoted my correct answer because you don't believe this to be true. So be it. Other people will find this answer valuable and understand that your vote was unfair.)
Please read the final question in The Best iText Questions on StackOverflow to find out what I think about people using unofficial, rogue, obsolete versions of iText.
See also https://stackoverflow.com/questions/25696851/can-itext-2-1-7-or-earlier-can-be-used-commercially

iTextSharp embedded cyrillic font in Adobe Reader

My PDF is not displayed properly with Adobe Reader. It is fine with other PDF readers so this must be a syntax issue, as I've heard that Adobe Reader is more strict with PDF syntax. The fonts seem to be twice as big as they should be but the horizontal spacing is correct, this makes the fonts overlap with each other.
This is my C# code (font creation code is at the end of this post).
Font officialUseFont = EmbeddedResources.CreateDesignFont(webform);
PdfContentByte officialUseCanvas = _stamper.GetOverContent(3);
ColumnText.ShowTextAligned(officialUseCanvas, Element.ALIGN_CENTER, new Phrase(webform.Text, officialUseFont), posX, posY, 0);
I'm using iTextSharp 5.4.2.0 with runtime v2.0.50727.
I must have embedded some fonts because the Cyrillic alphabet and Chinese alphabets were not working before but they work now. The form fields which exist in the PDF are populated with Cyrillic characters without any problems, it's only the canvas which causes the issue.
public Font CreateDesignFont(IForm webform)
{
var baseFont = GetBaseFont(fontNamespace.Length, selectedFontName);
return new Font(baseFont, webform.FontSize);
}
private static BaseFont GetBaseFont(int fontNamespaceLength, string selectedFontName)
{
byte[] fontBuffer;
using (var stream = (Assembly.GetExecutingAssembly().GetManifestResourceStream(selectedFontName)))
{
fontBuffer = new byte[stream.Length];
stream.Read(fontBuffer, 0, fontBuffer.Length);
}
var fontfile = selectedFontName.Substring(fontNamespaceLength);
var customFont = BaseFont.CreateFont(fontfile, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, BaseFont.CACHED, fontBuffer, null);
return customFont;
}
The code snippet you're providing isn't sufficient. The problem originates in whatever happens when you do EmbeddedResources.CreateDesignFont(webform);
If the font isn't shown in Adobe Reader, you didn't embed the font. Maybe you think you do, but judging by the behavior of the PDF viewers, you didn't.
Can you provide a screen shot of the Document Properties, more specifically the "Fonts" tab?
UPDATE
I tried writing my own code snippet, and I wasn't able to reproduce the problem. So I took another look at your code, and I saw that you're caching the font, but you've already used ArialMT using the WINANSI encoding to fill out the fields on page 1. IMO (I don't have the time to check) that's incompatible with using the same font from cache using IDENTITY_H. If you don't cache the font (why would you? you're passing the fontBuffer! no need to store the font in a cache if you're already caching the font bytes yourself), your problem will probably be solved.
The problem stemmed from the fact I was using .otf fonts. When I changed to .ttf the problem disappeared.

superscripts does not show properly on an image created by itext on pdf

I have a very confusing problem about unicode support in the generated pie chart in my pdf.
Here is what I have:
I am generating pie chart (with jfreechart library) that need to add superscripts on the title of the pie chart.
I tested and I know that jfreechart is generating correct title (superscripts are fine) and I also tested itext unicode support.
There is a Graphics2D (from java awt) in between which turns the jfreechart into a template and then I can print this template into my pdf.
according my tests I guess problem should be in between graphics2d and itext template.
PdfContentByte canvas = writer.getDirectContent();
PdfTemplate template = canvas.createTemplate(width, height);
FontMapper mapper = new DefaultFontMapper();
template.setFontAndSize(mapper.awtToPdf(new java.awt.Font("Arial Unicode MS", java.awt.Font.PLAIN, 7)) , 7);
Graphics2D graphics2d = template.createGraphics(width, height);
graphics2d.setFont(new java.awt.Font("Arial Unicode MS", java.awt.Font.PLAIN, 7));
JFreeChart chart = getPieChart("", title, value);
I found out the problem.
Problem is template (PdfTemplate) does not show the unicode character. Although I embedded unicode fonts and set it for template, still not working.
any ideas?
Actually finally I fixed the problem by removing superscript from pie chart and print it directly into template. This also eliminates the use of unicode font (which costs extra money):
template.beginText();
template.setFontAndSize(arial, 8);
// the fixed position of the xy coordinate that I want to print superscript
template.moveText(97, 142);
template.showText(superscript);
template.setTextRise(5f);
template.endText();

iTextSharp equivalent of XPdfFontOptions

I'm converting a C# app page which uses PdfSharp to iTextSharp & have found a line of code I can't see an obvious replacement for.
The existing code is
PdfSharp.Drawing.XPdfFontOptions options = new PdfSharp.Drawing.XPdfFontOptions(PdfFontEncoding.Unicode,
PdfFontEmbedding.Always);
Also, what if I want to use other, non-base fonts? I can see from the docs how to create one of the 16 types, however what if I want "Frutiger LT 45 Light"?
Thanks in advance.
Have a look at the examples from iText in Action — 2nd Edition Chapter 11: Choosing the right font; the .Net versions are available here.
You'll see that fonts can be selected, configured, and used like this:
public const string FONT = "c:/windows/fonts/arialbd.ttf";
BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font f = new Font(bf, 12);
document.Add(new Paragraph("Text", f));
Font garamondItalic = FontFactory.GetFont(
"Garamond", BaseFont.WINANSI, BaseFont.EMBEDDED, 12, Font.ITALIC
);
document.Add(new Paragraph("Garamond-Italic", garamondItalic));
Thus, you explicitly enter the encoding and embedding options in the font creation instead of via some font option object.
BTW, here BaseFont does not refer to the standard 14 fonts which shall be available to the conforming reader according to ISO 32000-1:2008 (I assume that you mean those fonts when you talk about the 16 types) but instead is a base object from which fonts at given sizes are created.

iText, What's going on with Font, BaseFont and createFont()?

There is a lot of mystery to me about what is going on with font and basefont. Especially when it comes to the constructor. The iText website gives this line as example code for new fonts
BaseFont unicode = BaseFont.createFont("c:/windows/fonts/arialuni.ttf",
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED);
I can get this call to work:
BaseFont bf = BaseFont.createFont(BaseFont.COURIER, BaseFont.CP1257,
BaseFont.EMBEDDED);
But if I replace BaseFont.CP1257 with say BaseFont.HELVETICA then it doesn't work and I get a page that says "failed to load pdf document."
I tried looking through the class file and I can't seem to figure out what that second parameter is (I'm assuming it is something like a backup font in case the first font doesn't work, like in HTML) and I can't figure out why some fonts would work and not others.
To load it from inside your jar use the leading slash otherwise, just use the absolute path of your font ("C:[...]\fonts\Sansation_Regular.ttf"). For example:
Font font = FontFactory.getFont("/fonts/Sansation_Regular.ttf",
BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 0.8f, Font.NORMAL, BaseColor.BLACK);
BaseFont baseFont = font.getBaseFont();
The relative path of the font is: 'src/main/resources/fonts'
Using Itext 5.4.5
example: https://code.google.com/p/jhocr/source/browse/trunk/src/main/java/com/googlecode/jhocr/converter/HocrPageProcessor.java
The second parameter is the encoding.
Refer to documentation here for more information.
This is what worked for me. Old post, but I couldn't find a simple answer.
//Here you setup the font that you want. I put it under the root/Content/fonts folder in my project
Font font = FontFactory.GetFont("~/Content/fonts/ARIALN.ttf", BaseFont.CP1252,false, 9);
//Here I create the paragraph then assign the font to it at the end
var addressAttn = new Paragraph("Attn: Manager, Billing Services", font);