How to set the default font for iText7 / pdfhtml - c#

Various comments are written into a PDF table. The table has one column.
The comments come from an HTML editor from a web application and contain HTML text that is output with pdfhtml.
Examples for comments:
<div> a <b>bold</b> and an <i>italic</i> text.</div>
<div><span style="font-size: 18px">large</span><div><div><span style="font-size: 11px">medium</span><div><div><span style="font-size: 8px">small</span></div>
The whole output should be in Verdana, but some other fonts (AgencyFB) should appear (in the spans of the second example).
The code
public byte[] CreateDoc()
{
using (MemoryStream stream = new MemoryStream())
{
using (PdfWriter writer = new PdfWriter(stream))
{
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc, PageSize.A4);
PdfFont font = PdfFontFactory.CreateRegisteredFont("Verdana", PdfEncodings.CP1252, true);
float fontSize = 11f;
Table table = new Table(1);
table.AddCell(new Cell().Add(new Paragraph("no Html").SetFont(font).SetFontSize(fontSize)));
string comment1 = "<div>a <b>bold</b> and an <i>italic</i> text.</div>";
string comment2 = "<div><span style=\"font-size: 18px\">large</span><div><div><span style=\"font-size: 11px\">medium</span><div><div><span style=\"font-size: 8px\">small</span></div>";
InsertHtmlCell(table, font, fontSize, comment1);
InsertHtmlCell(table, font, fontSize, comment2);
doc.Add(table);
doc.Flush();
doc.Close();
pdfDoc.Close();
writer.Close();
}
byte[] buffer = stream.ToArray();
return buffer;
}
}
private void InsertHtmlCell(Table table, PdfFont f, float fontSize, string comment)
{
var cell = new Cell(1, 1);
// Without ConverterProperties, "times" is used
ConverterProperties prop = new ConverterProperties();
prop.SetFontProvider(new DefaultFontProvider(false, false, true));
var elements = HtmlConverter.ConvertToElements(comment, prop).Cast<IBlockElement>();
foreach (var element in elements)
{
// without the following 2 lines always "AgencyFB" is used.
element.SetProperty(Property.FONT, f);
element.SetProperty(Property.FONT_SIZE, new UnitValue(UnitValue.CreatePointValue(fontSize)));
cell.Add(element);
}
table.AddCell(cell);
}
Result:
"bold", "large", "medium" and "small": AgencyFB
"italic": BookAntiqua
But the whole output should be in Verdana. How can I reach this?

You are telling the font provider to load all the system fonts. If you definitely don't need all of them, you can just have a white list of fonts that you want to use. In your case you need to add Verdana Regular, Verdana Bold and Verdana Italic fonts.
This is how you can do that:
FontProvider fontProvider = new DefaultFontProvider(false, false, false);
fontProvider.addFont("C:/Windows/Fonts/verdana.ttf");
fontProvider.addFont("C:/Windows/Fonts/verdanab.ttf"); // Bold
fontProvider.addFont("C:/Windows/Fonts/verdanai.ttf"); // Italic

Related

How to write Arabic text using MigraDoc?

I am using ASP for this and I had to generate reports in PDF format and send the file back to clients so they can download it.
I made the reports using MigraDoc library and they were great but after I tried it with Arabic text I found the texts were in LTR and the characters were disjointed so I made this code to test things out
...............
MigraDoc.DocumentObjectModel.Document reportDoc = new MigraDoc.DocumentObjectModel.Document();
reportDoc.Info.Title = "test";
sec = reportDoc.AddSection();
string fileName = "test.pdf";
addformattedText(sec, "العبارة", true);
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = reportDoc;
renderer.RenderDocument();
MemoryStream pdfStream = new MemoryStream();
renderer.PdfDocument.Save(pdfStream);
byte[] bytes = pdfStream.ToArray();
...............
private void addformattedText(Section sec,string text, bool shouldBeBold = false)
{
var tf = sec.AddTextFrame();
var p = tf.AddParagraph(text);
p.Format.Font.Name = "Tahoma";
if (shouldBeBold) p.Format.Font.Bold = true;
}
I get the output like this
I have tried to encode the text and make it a unicode string using this code
private string getEscapedString(string text)
{
if (true || HasArabicCharacters(text))
{
string uString = "";
byte[] utfBytes = Encoding.Unicode.GetBytes(text);
foreach (var u in utfBytes)
{
if (u != 0)
{
uString += String.Format(#"\u{0:x4}", u);
}
}
return uString;
}
else
return text;
}
and get the returned string into a paragraph and save the PDF documents with unicode parameter set to true
But it is all the same.
I can not figure out how to get it done.
The reports were done using MigraDoc 1.50.5147 library.
The problem is Arabic language font have 4 different shap in begging,last,connected and alone, where Pdfsharp and MigraDoc can not recognize which shap to print farther more you need to reverse the character order to solve this you can use AraibcPdfUnicodeGlyphsResharper to help do such work as following:
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using AraibcPdfUnicodeGlyphsResharper;
namespace MigraDocArabic
{
internal class PrintArabicUsingPdfSharp
{
public PrintArabicUsingPdfSharp(string path)
{
PdfDocument document = new PdfDocument();
document.Info.Title = "Created with PDFsharp";
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
// Create an empty page
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
// Create a font
XFont font = new XFont("Arial", 20, XFontStyle.BoldItalic);
var xArabicString = "كتابة اللغة العربية شيئ جميل".ArabicWithFontGlyphsToPfd();
// Draw the text
gfx.DrawString("Hello, World!", font, XBrushes.Black, new XRect(0, 0, page.Width, page.Height), XStringFormats.Center);
gfx.DrawString(xArabicString, font, XBrushes.Black, new XRect(50, 50, page.Width, page.Height), XStringFormats.Center);
// Save the document...
document.Save(path);
}
}
}
Do not Forget the Extension method
By the way this is work with iText7 too
see the image for result
Result
PDFsharp does not support RTL languages yet:
http://www.pdfsharp.net/wiki/PDFsharpFAQ.ashx#Does_PDFsharp_support_for_Arabic_Hebrew_CJK_Chinese_Japanese_Korean_6
You can work around this limitation by reversing the string.
PDFsharp does not support font ligatures yet. You are probably able to work around this limitation by replacing letters with the correct glyph (start, middle, end) depending on the position.

Append HTML header to Spire PDF

I am using Spire PDF to convert my HTML template to PDF file. Here is the sample code for the same:
class Program
{
static void Main(string[] args)
{
//Create a pdf document.
PdfDocument doc = new PdfDocument();
PdfPageSettings setting = new PdfPageSettings();
setting.Size = new SizeF(1000,1000);
setting.Margins = new Spire.Pdf.Graphics.PdfMargins(20);
PdfHtmlLayoutFormat htmlLayoutFormat = new PdfHtmlLayoutFormat();
htmlLayoutFormat.IsWaiting = true;
String url = "https://www.wikipedia.org/";
Thread thread = new Thread(() =>
{ doc.LoadFromHTML(url, false, false, false, setting,htmlLayoutFormat); });
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
//Save pdf file.
doc.SaveToFile("output-wiki.pdf");
doc.Close();
//Launching the Pdf file.
System.Diagnostics.Process.Start("output-wiki.pdf");
}
}
This is working as expected but now I want to add Header and Footer to all the pages. Though adding header and footer is possible using SprirePdf but my requirement is to add HTML template to the Header which I am not able to achieve. Is there any way to render html template to Header and footer?
Spire.PDF provides a class PdfHTMLTextElement supporting to render simple HTML tags including Font, B, I, U, Sub, Sup and BR on a PDF page. You can append HTML to header space in an existing PDF document using the following code snippet. As far as I know, there is no way to render complicated HTML only as a part of the document by using Spire.PDF.
//load an existing pdf document
PdfDocument doc = new PdfDocument();
doc.LoadFromFile(#"C:\Users\Administrator\Desktop\sample.pdf");
//loop through the pages
for (int i = 0; i < doc.Pages.Count; i++)
{
//get the specfic page
PdfPageBase page = doc.Pages[i];
//define HTML string
string htmlText = "<b>XXX lnc.</b><br/><i>Tel:889 974 544</i><br/><font color='#FF4500'>Website:www.xxx.com</font>";
//render HTML text
PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 12);
PdfBrush brush = PdfBrushes.Black;
PdfHTMLTextElement richTextElement = new PdfHTMLTextElement(htmlText, font, brush);
richTextElement.TextAlign = TextAlign.Left;
//draw html string at the top white space
richTextElement.Draw(page.Canvas, new RectangleF(70, 20, page.GetClientSize().Width - 140, page.GetClientSize().Height - 20));
}
//save to file
doc.SaveToFile("output.pdf");

Arabic in pdf using iTextSharp in c#

I want to create a PDF file with Arabic text content in C#. I'm using iTextSharp to create this. I followed the instruction in http://geekswithblogs.net/JaydPage/archive/2011/11/02/using-itextsharp-to-correctly-display-hebrew--arabic-text-right.aspx. I want to insert the following Arabic sentence in pdf.
تم إبرام هذا العقد في هذا اليوم [●] م الموافق [●] من قبل وبين .
The [●] need to be replaced by dynamic English words. I tried to implement this by using ARIALUNI.TTF [This tutorial link suggested it]. The code is given below.
public void WriteDocument()
{
//Declare a itextSharp document
Document document = new Document(PageSize.A4);
//Create our file stream and bind the writer to the document and the stream
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(#"D:\Test.Pdf", FileMode.Create));
//Open the document for writing
document.Open();
//Add a new page
document.NewPage();
//Reference a Unicode font to be sure that the symbols are present.
BaseFont bfArialUniCode = BaseFont.CreateFont(#"D:\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//Create a font from the base font
Font font = new Font(bfArialUniCode, 12);
//Use a table so that we can set the text direction
PdfPTable table = new PdfPTable(1);
//Ensure that wrapping is on, otherwise Right to Left text will not display
table.DefaultCell.NoWrap = false;
//Create a regex expression to detect hebrew or arabic code points
const string regex_match_arabic_hebrew = #"[\u0600-\u06FF,\u0590-\u05FF]+";
if (Regex.IsMatch("م الموافق", regex_match_arabic_hebrew, RegexOptions.IgnoreCase))
{
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
}
//Create a cell and add text to it
PdfPCell text = new PdfPCell(new Phrase(" : "+"من قبل وبين" + " 2007 " + "م الموافق" + " dsdsdsdsds " + "تم إبرام هذا العقد في هذا اليوم ", font));
//Ensure that wrapping is on, otherwise Right to Left text will not display
text.NoWrap = false;
//Add the cell to the table
table.AddCell(text);
//Add the table to the document
document.Add(table);
//Close the document
document.Close();
//Launch the document if you have a file association set for PDF's
Process AcrobatReader = new Process();
AcrobatReader.StartInfo.FileName = #"D:\Test.Pdf";
AcrobatReader.Start();
}
While calling this function, I got a PDF with some Unicode as given below.
اذه يف دقعلا اذه ماربإ مت dsdsdsdsds قفاوملا م 2007 نيبو لبق نم
مويلا
It is not matching with our hard coded Arabic sentence. Is this a issue of font? Please help me or suggest me any other method to implement the same.
#csharpcoder has the right idea, but his execution is off. He doesn't add the cell to a table, and the table doesn't end up in the document.
void Go()
{
Document doc = new Document(PageSize.LETTER);
string yourPath = "foo/bar/baz.pdf";
using (FileStream os = new FileStream(yourPath, FileMode.Create))
{
PdfWriter.GetInstance(doc, os); // you don't need the return value
doc.Open();
string fontLoc = #"c:\windows\fonts\arialuni.ttf"; // make sure to have the correct path to the font file
BaseFont bf = BaseFont.CreateFont(fontLoc, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font f = new Font(bf, 12);
PdfPTable table = new PdfPTable(1); // a table with 1 cell
Phrase text = new Phrase("العقد", f);
PdfPCell cell = new PdfPCell(text);
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL; // can also be set on the cell
table.AddCell(cell);
doc.Add(table);
doc.Close();
}
}
You will probably want to get rid of the cell borders etc, but that information can be found elsewhere on SO or the iText website. iText should be able to handle text that contains both RTL and LTR characters.
EDIT
I think the source problem is actually with how the Arabic text is rendered in Visual Studio and in Firefox (my browser), or alternatively with how the Strings are concatenated. I'm not very familiar with Arabic text editors, but the text seems to come out correctly if we do this:
FYI I had to take a screenshot, because copy-pasting into the browser from VS (and vice versa) messes up the order of the parts of the text.
Right-to-left writing and Arabic ligatures are only supported in ColumnText and PdfPTable!
Try out the below code :
Document Doc = new Document(PageSize.LETTER);
//Create our file stream
using (FileStream fs = new FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf"), FileMode.Create, FileAccess.Write, FileShare.Read))
{
//Bind PDF writer to document and stream
PdfWriter writer = PdfWriter.GetInstance(Doc, fs);
//Open document for writing
Doc.Open();
//Add a page
Doc.NewPage();
//Full path to the Unicode Arial file
string ARIALUNI_TFF = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "arabtype.TTF");
//Create a base font object making sure to specify IDENTITY-H
BaseFont bf = BaseFont.CreateFont(ARIALUNI_TFF, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font f = new Font(bf, 12);
//Write some text, the last character is 0x0278 - LATIN SMALL LETTER PHI
Doc.Add(new Phrase("This is a ميسو ɸ", f));
//add Arabic text, for instance in a table
PdfPCell cell = new PdfPCell();
cell.AddElement(new Phrase("Hello\u0682", f));
cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
//Close the PDF
Doc.Close();
}
I hope these notes can help you from other answers:
Use a safe code to achieve your font:
var tahomaFontFile = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Fonts),
"Tahoma.ttf");
Use BaseFont.IDENTITY_H and BaseFont.EMBEDDED properties.
var tahomaBaseFont = BaseFont.CreateFont(tahomaFontFile,
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED);
var tahomaFont = new Font(tahomaBaseFont, 8, Font.NORMAL);
Use PdfWriter.RUN_DIRECTION_RTL, for both your cell and your table:
var table = new PdfPTable(1)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL
};
var phrase = new Phrase("تم إبرام هذا العقد في هذا اليوم [●] م الموافق [●] من قبل وبين .",
tahomaFont);
var cell = new PdfPCell(phrase)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
Border = 0,
};
i believe your problem in string structure part, try to use the below code it works fine with me, Good Luck.`
public static void GeneratePDF()
{
//Declare a itextSharp document
Document document = new Document(PageSize.A4);
Random ran = new Random();
string PDFFileName = string.Format(#"C:\Test{0}.Pdf", ran);
//Create our file stream and bind the writer to the document and the stream
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(PDFFileName, FileMode.Create));
//Open the document for writing
document.Open();
//Add a new page
document.NewPage();
var ArialFontFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ARIALUNI.ttf");
//Reference a Unicode font to be sure that the symbols are present.
BaseFont bfArialUniCode = BaseFont.CreateFont(ArialFontFile, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//Create a font from the base font
Font font = new Font(bfArialUniCode, 12);
//Use a table so that we can set the text direction
var table = new PdfPTable(1)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
};
//Ensure that wrapping is on, otherwise Right to Left text will not display
table.DefaultCell.NoWrap = false;
ContentObject CO = new ContentObject();
CO.Name = "Ahmed Gomaa";
CO.StartDate = DateTime.Now.AddMonths(-5);
CO.EndDate = DateTime.Now.AddMonths(43);
string content = string.Format(" تم إبرام هذا العقد في هذا اليوم من قبل {0} في تاريخ بين {1} و {2}", CO.Name, CO.StartDate, CO.EndDate);
var phrase = new Phrase(content, font);
//var phrase = new Phrase("الحمد لله رب العالمين", font);
//Create a cell and add text to it
PdfPCell text = new PdfPCell(phrase)
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
Border = 0
};
//Ensure that wrapping is on, otherwise Right to Left text will not display
text.NoWrap = false;
//Add the cell to the table
table.AddCell(text);
//Add the table to the document
document.Add(table);
//Close the document
document.Close();
//Launch the document if you have a file association set for PDF's
Process AcrobatReader = new Process();
AcrobatReader.StartInfo.FileName = PDFFileName;
AcrobatReader.Start();
}
}
public class ContentObject
{
public string Name { set; get; }
public DateTime StartDate { set; get; }
public DateTime EndDate { set; get; }
}
`

ItextSharp HTML to PDF conversion how to convert text with superscript and subscript as it is

Hi this is my implementation to convert an HTML in to PDF as i
private static PdfContent PdfContentA()
{
var cssText = System.IO.File.ReadAllText(#"C:\Users\kalanamithm\Desktop\Ground Operations\MvcApplication1\MvcApplication1\Resources\CSS\FTL.css");
//var htmlText = System.IO.File.ReadAllText(#"C:\Users\kalanamithm\Desktop\Ground Operations\MvcApplication1\MvcApplication1\Resources\HTML\grace.html");
var htmlText = System.IO.File.ReadAllText(#"C:\Users\kalanamithm\Desktop\Ground Operations\MvcApplication1\MvcApplication1\Resources\HTML\FLT.html");
var memoryStream = new MemoryStream();
var document = new Document();
var writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
var xmlWorkerFontProvider = new XMLWorkerFontProvider();
xmlWorkerFontProvider.Register("http://localhost:58045/Resources/Fonts/TequilaSunset-Regular.ttf");
xmlWorkerFontProvider.Register("http://localhost:58045/Resources/Fonts/Mf Sippin On Sunshine.ttf");
using (var cssMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(cssText)))
{
using (var htmlMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(htmlText)))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, htmlMemoryStream, cssMemoryStream);
}
}
document.Close();
var pdfContent = new PdfContent
{
MemoryStream = memoryStream,
FileName = "SomeName"
};
return pdfContent;
}
um facing a problem here , when um converting SuperScript pr subscript it wont show in Pdf.
Is there a solution for this in ITextSharp?
Since your question mentions 'as it is' then you can add the css for sub and sup tags in you css file. And then all subscript and superscript tags will render fine in pdf. No need to change the intial html.
<style>
sup {
vertical-align: super;
font-size: 9px;
}
sub {
vertical-align: sub;
font-size: 9px;
}
</style>
I came up with a solution
in the html I manually created a superscript as follows and it works
(based on my scenario)
"<span style=\"width:500px;\">" +
"<span>500 m</span>" +
"<span style=\"vertical-align:super;font-size:8px;\">2</span>" +
"</span>" +

Why is the customization of my PDF fonts using iTextSharp failing?

I want to decorate various paragraphs in a PDF file by bolding some text, using different fonts, and colors. I thought I found the code for how to do that (below), but it's not working - all the text is the same font, color (black), and size. Why are my virtual sweat-inducing efforts to prettyify the PDF file so far in vain? Here is my code:
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
// Mimic the appearance of Duckbill_Platypus.pdf
var docTitle = new Paragraph("Duckbilled Platypi - they're not what's for dinner");
var titleFont = FontFactory.GetFont("Courier", 18, BaseColor.BLACK);
docTitle.Font = titleFont;
doc.Add(docTitle);
var subTitle = new Paragraph("Baby, infant, toddler, and perhaps 'Terrible 2s' Platypi are called Platypups");
var subtitleFont = FontFactory.GetFont("Times Roman", 13, BaseColor.BLACK);
subTitle.Font = subtitleFont;
doc.Add(subTitle);
var importantNotice = new Paragraph("Teenage platypi are sometimes called Platydude[tte]s");
var importantNoticeFont = FontFactory.GetFont("Courier", 13, BaseColor.RED);
importantNotice.Font = importantNoticeFont;
doc.Add(importantNotice);
ListColumns lc;
for (int i = 0; i < listOfListItems.Count; i++)
{
lc = listOfListItems[i];
sb.AppendLine(String.Format(#"<p>Request date is {0}; Payee Name is {1}; Remit Address or Mail Stop is {2}; Last 4 of SSN or ITIN is {3}; 204 Submitted or on file is {4}; Requester Name is {5}; Dept or Div Name is {6}; Phone is {7}; Email is {8}</p>",
lc.li_requestDate, lc.li_payeeName, lc.li_remitAddressOrMailStop, lc.li_last4SSNDigitsOrITIN, lc.li_204SubmittedOrOnFile, lc.li_requesterName, lc.li_deptDivName, lc.li_phone, lc.li_email));
}
String htmlToRenderAsPDF = sb.ToString();
//XMLWorker also reads from a TextReader and not directly from a string
using (var srHtml = new StringReader(htmlToRenderAsPDF))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
}
doc.Close();
}
}
try
{
var bytes = ms.ToArray();
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "iTextSharpTest.pdf");
File.WriteAllBytes(testFile, bytes);
}
catch (Exception ex)
{
String exMsg = ex.Message;
; // what is "ex" here?
}
I'm setting two sizes of font (18 and 13), two colors (black and red), two fonts ("Courier" and "Times Roman") yet all my hours of travail here for PDF fancification seem yet in vain (apologies to Vachel Lindsay and Abraham Lincoln).
You should use the font when creating the Paragraph:
Font f = new Font(FontFamily.COURIER);
Paragraph p = new Paragraph("text", f);
document.add(p);
Or you should wait to add content until you've set the font:
Paragraph p = new Paragraph();
Font f = new Font(FontFamily.COURIER);
p.setFont(f);
p.addText("text");
document.add(p);
In your code, you have something like this:
Paragraph p = new Paragraph("text");
Font f = new Font(FontFamily.COURIER);
p.setFont(f);
document.add(p);
When setting the font using setFont(), you set the font for the text that will be added to the paragraph, not to the text that is already stored in the paragraph.
For instance:
Paragraph p = new Paragraph("font 1 ");
p.setFont(new Font(FontFamily.COURIER);
p.add("font 2");
document.add(p);
This will add the text font 1 in the default font and font 2 in Courier.

Categories