I am creating a PDF using componentOne library to create a PDF in my universal application, this is creating a PDF fine for English, but when I create a PDF in Arabic it starts giving garbage characters instead of Arabic characters.
This looks like an encoding issue to me. Please let me know how do we solve such issues generally for creating PDF, even if you do not know about componentOne library. I might pick the clue.
EDIT:
Download Stripped down code:
http://1drv.ms/1ABAuqi
Code:
async void CreatePdfDocument()
{
try
{
var pdf = new C1PdfDocument(PaperKind.Letter);
pdf.Landscape = false;
// measure and show some text
var text = App.GetResource("DocumentHeading");
var font = new Font("Segoe UI Light", 36, PdfFontStyle.Bold);
var fmt = new StringFormat();
fmt.Alignment = HorizontalAlignment.Center;
// measure it
var sz = pdf.MeasureString(text, font, 72 * 3, fmt);
var rc = new Rect(0, 0, pdf.PageRectangle.Width, sz.Height);
rc = PdfUtils.Offset(rc, 0, 0);
// draw the text
pdf.DrawString(text, font, Colors.Orange, rc, fmt);
}
catch (Exception e)
{
}
}
Related
I have a rich text box named:”DocumentContent” which I’m going to add its content to pdf using the below code:
iTextSharp.text.Font font = FontFactory.GetFont(#"C:\Windows\Fonts\arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 12f, Font.NORMAL, BaseColor.BLACK);
DocumentContent = System.Web.HttpUtility.HtmlDecode(DocumentContent);
Chunk chunkContent = new Chunk(DocumentContent);
chunkContent.Font = font;
Phrase PhraseContent = new Phrase(chunkContent);
PhraseContent.Font = font;
PdfPTable table = new PdfPTable(2);
table.WidthPercentage = 100;
PdfPCell cell;
cell = new PdfPCell(new Phrase(PhraseContent));
cell.Border = Rectangle.NO_BORDER;
table.AddCell(cell);
The problem is when I open PDF file the content appears as HTML not a text as below:
<p>Overview line1 </p><p>Overview line2
</p><p>Overview line3 </p><p>Overview
line4</p><p>Overview line4</p><p>Overview
line5 </p>
But it should look like below
Overview line1
Overview line2
Overview line3
Overview line4
Overview line4
Overview line5
What I'm going to do is to keep all the styling which user apply to the rich text and just change font family to Arial.
I can change Font Family but I need to Decode this content from HTML to Text.
Could you please advise?
Thanks
Please take a look at the HtmlContentForCell example.
In this example, we have the HTML you mention:
public static final String HTML = "<p>Overview line1</p>"
+ "<p>Overview line2</p><p>Overview line3</p>"
+ "<p>Overview line4</p><p>Overview line4</p>"
+ "<p>Overview line5 </p>";
We also create a font for the <p> tag:
public static final String CSS = "p { font-family: Cardo; }";
In your case, you may want to replace Cardo with Arial.
Note that we registered the regular version of the Cardo font:
FontFactory.register("resources/fonts/Cardo-Regular.ttf");
If you need bold, italic and bold-italic, you also need to register those fonts of the same Cardo family. (In case of arial, you'd register arial.ttf, arialbd.ttf, ariali.ttf and arialbi.ttf).
Now we can parse this HTML and CSS into a list of Element objects with the parseToElementList() method. We can use these objects inside a cell:
PdfPTable table = new PdfPTable(2);
table.addCell("Some rich text:");
PdfPCell cell = new PdfPCell();
for (Element e : XMLWorkerHelper.parseToElementList(HTML, CSS)) {
cell.addElement(e);
}
table.addCell(cell);
document.add(table);
See html_in_cell.pdf for the resulting PDF.
I do not have the time/skills to provide this example in iTextSharp, but it should be very easy to port this to C#.
Finally I write this code in c# which is working perfectly, Thanks to Bruno who helped me to understand XMLWorker.
Here is an example using XMLWorker in C#.
I used a sample HTML as below:
public static string HTML = "<p>Overview line1âââŵẅẃŷûâàêÿýỳîïíìôöóòêëéèẁẃẅŵùúúüûàáäâ</p>"
+ "<p>Overview line2</p><p>Overview line3</p>"
+ "<p>Overview line4</p><p>Overview line4</p>"
+ "<p>Overview line5 </p>";
I have created Test.css file and saved it in SharePoint Style Library. (for this test I saved it in D drive to keep it simple)
Here is the content of my test css file:
p { font-family: arial; }
Then using the below c# code I saved the PDF file in D drive. ( In SharePoint I used Memorystream. I keep this example very simple to understand )
string fileName = #"D:\Test.pdf";
var css = #"D:\Test.css";
using (var ActionStream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(HTML)))
{
using (FileStream cssFile = new FileStream(css, FileMode.Open))
{
var document = new Document(PageSize.A4, 30, 30, 10, 10);
var worker = XMLWorkerHelper.GetInstance();
var writer = PdfWriter.GetInstance(document, new FileStream(fileName, FileMode.Create));
document.Open();
worker.ParseXHtml(writer, document, ActionStream, cssFile);
writer.CloseStream = false;
document.Close();
}
}
It creates Test.pdf file adding my HTML with Font Family:Arial. So all of the Welsh Characters can be saved in PDF file.
Note: I have added iTextSharp.dll v:5.5.3 and XMLworker.dll v: 5.5.3 to my project.
using iTextSharp.text;
using iTextSharp.text.html;
using iTextSharp.text.pdf;
using iTextSharp.tool.xml;
using iTextSharp.tool.xml.css;
using iTextSharp.tool.xml.html;
using iTextSharp.tool.xml.parser;
using iTextSharp.tool.xml.pipeline;
Hope this can be useful.
Kate
This code returns lots of \0\0s and extracts only a few English phrases from the PDF. Any Japanese text is not returned.
I am using Unicode encoding, so I am not sure what is happening here.
StringBuilder text = new StringBuilder(2000);
string fullFileName = #"c:\my_japanaese_pdf.pdf";
PdfReader pdfReader = new iTextSharp.text.pdf.PdfReader(fullFileName);
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);
currentText = Encoding.Unicode.GetString(UnicodeEncoding.Convert(Encoding.Unicode, Encoding.Unicode, Encoding.Unicode.GetBytes(currentText)));
text.Append(currentText);
}
pdfReader.Close();
(Windows 7 x64, iTextSharp 5.0.2.0)
Thanks
Ryan
I had this same problem, and here's what I did (note this code is extremely similar to the code in the question, but doesn't use any encoding conversion stuff).
using (iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(inputPDF))
{
ITextExtractionStrategy Strategy = new LocationTextExtractionStrategy();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
string page = PdfTextExtractor.GetTextFromPage(reader, i, Strategy);
string[] lines = page.Split('\n');
foreach (string line in lines)
{
// do anything you want here
}
}
}
Even when using the above code, I was still not getting any Japanese characters out of the PDF, so I changed the font used in the PDF to Meiryo UI font. That is how to solve this problem. Meiryo UI is a font that iTextSharp recognizes (at least version 5.5.13.2), so Japanese text with that font can successfully be extracted from the PDF.
I have about 180 PDF files that are generated from a geodatabase. I would like to programmatically add links as hot spots (no text) at the top, bottom, left and right as needed to navigate to the adjoining page files. I would also like to add links over a 3x3 grid in the lower left corner of the page for additional navigation. The grid is already in the existing PDF just no links. Total there will be a possible 14 links added to each page
I am open to suggestions as to how to go about this. I am using Acrobat Pro XI, and I am familiar with various programing languages python, vb.net, C#... Just no experience working directly with PDF files.
This is very late answer. Actually I was searching for free alternative to above paid libraries. I found the following links which can be helpful to others.
Apache PDFBox is a vast java library to create pdf programmatically.
TomRoush/PdfBox-Android is it's android implementation. You can find the sample project with this implementation.
I have added the code for creating clickable links in pdf by using above android library and sample project.
public void createPdf(View v) {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA;
// Or a custom font
//try {
// PDType0Font font = PDType0Font.load(document, assetManager.open("MyFontFile.TTF"));
//} catch(IOException e) {
// e.printStackTrace();
//}
PDPageContentStream contentStream;
try {
// Define a content stream for adding to the PDF
contentStream = new PDPageContentStream(document, page);
String preText = "Icons made by ";
String linkText = "My_Site";
float upperRightX = page.getMediaBox().getUpperRightX();
float upperRightY = page.getMediaBox().getUpperRightY();
// Write linkText in blue text
contentStream.beginText();
contentStream.setNonStrokingColor(15, 38, 192);
contentStream.setFont(font, 18);
contentStream.moveTextPositionByAmount( 0, upperRightY-20);
contentStream.drawString(preText + linkText);
contentStream.endText();
// create a link annotation
PDAnnotationLink txtLink = new PDAnnotationLink();
// set up the markup area
float offset = (font.getStringWidth(preText) / 1000) * 18;
float textWidth = (font.getStringWidth(linkText) / 1000) * 18;
PDRectangle position = new PDRectangle();
position.setLowerLeftX(offset);
position.setLowerLeftY(upperRightY - 24f);
position.setUpperRightX(offset + textWidth);
position.setUpperRightY(upperRightY -4);
txtLink.setRectangle(position);
// add an action
PDActionURI action = new PDActionURI();
action.setURI("https://www.**********.com/");
txtLink.setAction(action);
// and that's all ;-)
page.getAnnotations().add(txtLink);
// load 'Social media' icons from 'vector' resources.
float padding = 5, startX = 5, startY = upperRightY-100, width = 25, height=25;
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_facebook,
"https://www.facebook.com/My_Name/", startX, startY, width, height);
startX += (width + padding);
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_instagram,
"https://www.instagram.com/My_Name", startX, startY, width, height);
// Make sure that the content stream is closed:
contentStream.close();
// Save the final pdf document to a file
String path = root.getAbsolutePath() + "/Download/Created.pdf";
document.save(path);
document.close();
tv.setText("Successfully wrote PDF to " + path);
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadVectorIconWithLink( PDDocument theDocument,
PDPage thePage,
PDPageContentStream theContentStream,
#DrawableRes int theDrawableId,
String theUriString,
float x, float y, float width, float height
) throws IOException
{
Bitmap alphaImage = getBitmapFromDrawable(this, theDrawableId);
PDImageXObject alphaXimage = LosslessFactory.createFromImage(theDocument, alphaImage);
theContentStream.drawImage(alphaXimage, x, y, width, height );
// create a link annotation
PDAnnotationLink iconLink = new PDAnnotationLink();
PDRectangle position = new PDRectangle( x, y, width, height );
iconLink.setRectangle(position);
// add an action
PDActionURI action1 = new PDActionURI();
action1.setURI(theUriString);
iconLink.setAction(action1);
// and that's all ;-)
thePage.getAnnotations().add(iconLink);
}
public static Bitmap getBitmapFromDrawable(Context context, #DrawableRes int drawableId) {
Drawable drawable = AppCompatResources.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawableCompat || drawable instanceof VectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
There are at least three types of links you might want to add: links to pages within the same document, links to pages in other PDF document, links to URLs on the web.
Docotic.Pdf library can add links of any of these types (please note that I am on of the developers of this library). Here are two relevant examples:
Create link to page
Create hyperlink
There are no examples for how to create links to pages in an other PDF document published online, but you can always contact support if you need such an example.
After continuing to search and not finding any other promising open source solutions I went with Debenu Quick PDF Library. The specific functions I used are are noted below:
AddLinkToFile
AddLinkToPage
Other annotations and hotspot links
The time that the two library functions are going to save me weekly is worth the cost alone. I am sure I will find other use for the other 900+ PDF functions
I have a text file that is pre-formatted with spacing and line breaks. I am writing the text out to a blank pdf that has been set to landscape with minimal margins to fit all the text to a single page, however I am still running off the page. Can anyone recommend how I can use itextsharp to dynamically "fit to page" by reducing the font size and/or line-height (lead). I have seen responses about using a textfield or rectangles but I can't seem to get those working properly.
Update: Here is what I have so far that uses no advanced stuff at all, simply margin control and font size adjustments to force my sample text to the page. This works fine if I always have fixed line lengths, but that unfortunately won't be the case. There might be a common max line length I can use across the files but I don't have that data at this time.
private void CreatePDF()
{
string line = string.Empty;
StreamReader sr = new StreamReader(#"C:\dev\text1.txt");
StringBuilder sb = new StringBuilder();
string newFile = #"C:\dev\testPDF1.pdf";
Document pdfDoc = new Document(PageSize.LETTER.Rotate(), 50, 5, 5, 5);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, new FileStream(newFile, FileMode.OpenOrCreate));
pdfDoc.Open();
while ((line = sr.ReadLine()) != null)
{
if (line != "\f")
{
sb.AppendLine(line);
}
else
{
pdfDoc.Add(new Paragraph(sb.ToString(), new Font(Font.NORMAL, 6)));
pdfDoc.NewPage();
pdfDoc.SetPageSize(PageSize.LETTER.Rotate());
pdfDoc.SetMargins(50, 5, 5, 5);
sb.Clear();
sb.AppendLine("");
}
}
pdfDoc.Add(new Paragraph(sb.ToString(), new Font(Font.NORMAL, 6)));
pdfDoc.Close();
//Console.Write(sb);
}
I used this technique to insert an image
Adding a dynamic image to a PDF using ColdFusion and iText
Now, I need to insert a link to a external URL at X/Y and text inside with itext and ColdFusion.
Can someone help me do this?
Thanks.
Here is rough example that works with CF9. There are probably more elegant methods, but this should give you the basic idea.
Note - IIRC CF8 uses an earlier version of iText (1.4). CF9 uses 2.1.0. So I am relatively certain it will not run "as is" with CF8. If needed, you can use the JavaLoader.cfc to run a later version.
Update: Modified to show one way of defining a specific font, size and color. The correct settings will vary depending on your system, desired font, encoding, etcetera.
<cfscript>
inputPath = "c:\sourceFile.pdf";
outputPath = "c:\sourceFileWithLink.pdf";
try {
// initialize objects
pdfReader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );
outStream = createObject("java", "java.io.FileOutputStream").init( outputPath );
pdfStamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( pdfReader, outStream );
// create a chunk with a link to www.google.com
chunk = createObject("java", "com.lowagie.text.Chunk").init("Go To Google");
chunk.setAnchor("http://www.google.com");
//////////////////////////////////////////
// Define embedded font
BaseFont = createObject("java", "com.lowagie.text.pdf.BaseFont");
Font = createObject("java", "com.lowagie.text.Font");
bf = BaseFont.createFont("c:/windows/fonts/Framd.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);
// Create the main font object (size 14)
Color = createObject("java", "java.awt.Color");
textFont = Font.init(bf, 14, Font.UNDERLINE, Color.RED);
// Apply the font to the chunk text
chunk.setFont( textFont );
//////////////////////////////////////////
// prepare to write the link onto the *first* page only
cb = pdfStamper.getOverContent(1); // first page
ct = createObject("java", "com.lowagie.text.pdf.ColumnText").init(cb);
ct.addElement( chunk );
// position towards bottom right of page
page = pdfReader.getPageSize(1);
llx = page.getRight()-200;
lly = page.getBottom();
urx = page.getRight();
ury = page.getBottom() + 36;
// initialize column dimensions
ct.setSimpleColumn(llx, lly, urx, ury);
// write the text
ct.go();
WriteOutput("Finished!");
}
finally
{
// cleanup
if (IsDefined("pdfStamper")) {
pdfStamper.close();
}
if (IsDefined("outStream")) {
outStream.close();
}
}
</cfscript>