iText7 converting signature as an invisible signature after using append mode property - c#

I am getting issue that if I use UseAppendMode property while creating signature field in the document, upon signing it creates invisible signature. Otherwise it displays the content of my custom signature appearance and creates a visible signature into PDF.
Following is my code snippet:
SigningResponse signingResponse = new SigningResponse();
Stream outputStream = new MemoryStream();
Org.BouncyCastle.X509.X509Certificate x509Certificate = null;
int estimatedSize = SigningProfile.ContainsKey(ProfileCommon.DICTIONARY_SIZE.ToString()) ?
int.Parse(SigningProfile[ProfileCommon.DICTIONARY_SIZE.ToString()]) * 1024 : 600 * 1024;
Stream readerStream = new MemoryStream(documentBytes);
PdfReader pdfReader = new PdfReader(readerStream);
PdfSigner pdfSigner = new PdfSigner(pdfReader, outputStream, new StampingProperties().UseAppendMode());
pdfSigner.SetFieldName("Signature1");
pdfSigner.GetDocument().GetCatalog().SetModified();
if (signingRequest.CertifyPolicy != (int)CertifyPolicy.NOT_CERTIFIED)
pdfSigner.SetCertificationLevel(signingRequest.CertifyPolicy);
PdfSignatureAppearance signatureAppearance = pdfSigner.GetSignatureAppearance();
signatureAppearance.SetContact("Contact Info");
signatureAppearance.SetLocation("Location");
signatureAppearance.SetPageNumber(1);
signatureAppearance.SetReason("Signing Reason");
PdfFormXObject n0 = signatureAppearance.GetLayer0();
float x = n0.GetBBox().ToRectangle().GetLeft();
float y = n0.GetBBox().ToRectangle().GetBottom();
float width = n0.GetBBox().ToRectangle().GetWidth();
float height = n0.GetBBox().ToRectangle().GetHeight();
PdfCanvas canvas = new PdfCanvas(n0, pdfSigner.GetDocument());
canvas.SetFillColor(ColorConstants.LIGHT_GRAY);
canvas.Rectangle(x, y, width, height);
canvas.Fill();
// Set the signature information on layer 2
PdfFormXObject n2 = signatureAppearance.GetLayer2();
Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
new Canvas(n2, pdfSigner.GetDocument()).Add(p);
signatureAppearance.SetCertificate(x509Certificate);
PreSigning external = new PreSigning(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
pdfSigner.SignExternalContainer(external, estimatedSize);
signingResponse.DocumentHash = external.getHash();
signingResponse.D2S = signingResponse.DocumentHash;
signingResponse.DocumentBytes = ((MemoryStream)outputStream).ToArray();
return signingResponse;
And the code of creating signature field is as follows:
byte[] documentBytes = null;
foreach (PDFSignatureField field in signatureFields)
{
using (Stream memoryStream = new MemoryStream())
using (PdfReader _pdfReader = new PdfReader(new MemoryStream(_documentBytes)).SetUnethicalReading(true))
using (PdfDocument pdfDocument = new PdfDocument(_pdfReader, new PdfWriter(memoryStream)))
{
PdfAcroForm pdfAcroForm = PdfAcroForm.GetAcroForm(pdfDocument, true);
//Initializing signature position object
PDFSignaturePosition SigPosition = field.Position;
for (int i = 0 ; i < SigPosition.Pages.Length ; ++i)
{
//Getting PDF document page
PdfPage page = pdfDocument.GetPage(SigPosition.Pages[i]);
if (page == null)
{
page = pdfDocument.GetPage(SigPosition.PageNumber);
}
//Getting PDF document page rotation
int rotation = page.GetRotation();
//Getting signature field rects according to PDF page
iText.Kernel.Geom.Rectangle rect;
if (rotation > 0 && SigPosition.Position == PDFSignaturePosition.DefaultSignaturePosition.Custom)
{
rect = GetSignaturePositionAccordingToRotation(SigPosition.Rect, page.GetCropBox(), rotation);
}
else
{
rect = GetSignaturePositionRect(SigPosition.Position, SigPosition.Rect, page.GetCropBox());
}
//Creating signature field into PDF page
PdfFormField sig = PdfFormField.CreateSignature(pdfDocument, rect);
//Setting signature field visible flag
if (field.Display == (int)SignatureDisplayType.INVISIBLE)
{
sig.SetFieldFlags(PdfFormField.HIDDEN);
sig.SetVisibility(PdfFormField.HIDDEN);
}
else
{
sig.SetFieldFlags(PdfFormField.VISIBLE);
}
//Setting signature field font information
sig.Put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g"));
//Setting signature field name
sig.SetFieldName(i == 0 ? field.Name : field.Name + " - " + SigPosition.Pages[i]);
//Setting signature field page
sig.SetPage(SigPosition.Pages[i]);
//Adding signature field into AcroForm
pdfAcroForm.AddField(sig, page);
//Making indirect reference of the added signature field into PDF
sig.MakeIndirect(pdfDocument);
//Closing PDF document object
pdfDocument.Close();
//Getting latest document bytes after adding PDF field
documentBytes = ((MemoryStream)memoryStream).ToArray();
if (i + 1 == SigPosition.Pages.Length)
{
break;
}
}
_documentBytes = documentBytes;
}
}

As you use a lot of variables defined, declared, and filled outside of the code you show, I had to reduce your code considerably. Furthermore, I don't have your example documents to tests with and, therefore, had to test with documents I have at hand here.
Nonetheless, I could reproduce the issue and found a solution for it in my setup. I hope that in spite of all the differences in setup you can use this solution.
The reason for the signature field becoming invisible in my setup turned out to be that while adding the signature fields to the document in append mode, the Fields array in the document-wide AcroForms dictionary was not marked as modified. The signer on the other hand relies on the signature field to sign to be found in that Fields array. The signer, therefore, did not find the prepared, visible field and created a new, invisible field with that name.
A work-around is to manually mark the array in question as modified:
pdfAcroForm.GetPdfObject().Get(PdfName.Fields).SetModified();
pdfAcroForm.GetPdfObject().SetModified();
//Closing PDF document object
pdfDocument.Close();

Related

Outputted pdf not filling with the content in iTextsharp and C#.net, creating with Zero bytes

I am working to replace the specific word inside pdf document using iTextSharp and C#.net, while I am debugging getting the proper value but the outputted pdf getting zero bytes(empty),its not filling with the content.
ReplacePDFText("Mumbai",StringComparison.CurrentCultureIgnoreCase,Application.StartupPath + "\\test.pdf","D:\\test_words_replaced.pdf"); //Do Everything
public void ReplacePDFText(string strSearch, StringComparison scCase, string strSource, string strDest)
{
PdfStamper psStamp = null; //PDF Stamper Object
PdfContentByte pcbContent = null; //Read PDF Content
if (File.Exists(strSource)) //Check If File Exists
{
PdfReader pdfFileReader = new PdfReader(strSource); //Read Our File
psStamp = new PdfStamper(pdfFileReader, new FileStream(strDest, FileMode.Create)); //Read Underlying Content of PDF File
pbProgress.Value = 0; //Set Progressbar Minimum Value
pbProgress.Maximum = pdfFileReader.NumberOfPages; //Set Progressbar Maximum Value
for (int intCurrPage = 1; intCurrPage <= pdfFileReader.NumberOfPages; intCurrPage++) //Loop Through All Pages
{
LocTextExtractionStrategy lteStrategy = new LocTextExtractionStrategy(); //Read PDF File Content Blocks
pcbContent = psStamp.GetUnderContent(intCurrPage); //Look At Current Block
//Determine Spacing of Block To See If It Matches Our Search String
lteStrategy.UndercontentCharacterSpacing = pcbContent.CharacterSpacing;
lteStrategy.UndercontentHorizontalScaling = pcbContent.HorizontalScaling;
//Trigger The Block Reading Process
string currentText = PdfTextExtractor.GetTextFromPage(pdfFileReader, intCurrPage, lteStrategy);
//Determine Match(es)
List<iTextSharp.text.Rectangle> lstMatches = lteStrategy.GetTextLocations(strSearch, scCase);
PdfLayer pdLayer = default(PdfLayer); //Create New Layer
pdLayer = new PdfLayer("Overrite", psStamp.Writer); //Enable Overwriting Capabilities
//Set Fill Colour Of Replacing Layer
pcbContent.SetColorFill(BaseColor.BLACK);
foreach (iTextSharp.text.Rectangle rctRect in lstMatches) //Loop Through Each Match
{
pcbContent.Rectangle(rctRect.Left, rctRect.Bottom, rctRect.Width, rctRect.Height); //Create New Rectangle For Replacing Layer
pcbContent.Fill(); //Fill With Colour Specified
pcbContent.BeginLayer(pdLayer); //Create Layer
pcbContent.SetColorFill(BaseColor.BLACK); //Fill aLyer
pcbContent.Fill(); //Fill Underlying Content
PdfGState pgState = default(PdfGState); //Create GState Object
pgState = new PdfGState();
pcbContent.SetGState(pgState); //Set Current State
pcbContent.SetColorFill(BaseColor.WHITE); //Fill Letters
pcbContent.BeginText(); //Start Text Replace Procedure
pcbContent.SetTextMatrix(rctRect.Left, rctRect.Bottom); //Get Text Location
//Set New Font And Size
pcbContent.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 9);
pcbContent.ShowText("AMAZING!!!!"); //Replacing Text
pcbContent.EndText(); //Stop Text Replace Procedure
pcbContent.EndLayer(); //Stop Layer replace rocedure
}
pbProgress.Value++; //Increase Progressbar Value
pdfFileReader.Close(); //Close File
}
//psStamp.Close(); //Close Stamp Object
}
}
You are only writing to your Console:
Console.WriteLine(ExtractTextFromPdf(#"C:\temp\MyPdf.pdf");
You are not saving the PDF to disk so you can't expect to see any changes in the pdf file. You code should save the modified text to disk:
var editedText = ExtractTextFromPdf(#"C:\temp\MyPdf.pdf");
Console.WriteLine(editedText);
SaveTextToPdf(editedText, #"C:\temp\MyPdf1.pdf");

iTextSharp Re-use Font Embedded In Acrofield

There are tips in "iText In Action" that cover setting fonts, as well as the "FontFactory.RegisterDirectories" method (which is, as the book says...an expensive call). However, in my case, the font that I want to use for new fields is already embedded in the document (in an existing Acrofield). With no guarantee that the same font will exist on the user's machine (or on a web server)....is there a way that I can register that already-embedded font, so that I can re-use it for other objects? In the code below, Acrofield "TheFieldIWantTheFontFrom" has the font that I want to re-use for a field named "my_new_field". Any help would be greatly appreciated!
using (MemoryStream output = new MemoryStream())
{
// Use iTextSharp PDF Reader, to get the fields and send to the
//Stamper to set the fields in the document
PdfReader pdfReader = new PdfReader(#"C:\MadScience\MSE_030414.pdf");
// Initialize Stamper (ms is a MemoryStream object)
PdfStamper pdfStamper = new PdfStamper(pdfReader, output);
// Get Reference to PDF Document Fields
AcroFields pdfFormFields = pdfStamper.AcroFields;
//*** CODE THAT HAVE NOT YET BEEN ABLE TO MAKE USE OF TO ASSIST WITH MY FONT ISSUE
//*** MIGHT BE HELP?
//List<object[]> fonts = BaseFont.GetDocumentFonts(pdfReader);
//BaseFont[] baseFonts = new BaseFont[fonts.Count];
//string[] fn = new string[fonts.Count];
//for (int i = 0; i < fonts.Count; i++)
//{
// Object[] obj = (Object[])fonts[i];
// baseFonts[i] = BaseFont.CreateFont((PRIndirectReference)(obj[1]));
// fn[i] = baseFonts[i].PostscriptFontName.ToString();
// //Console.WriteLine(baseFonts[i].FamilyFontName[0][1].ToString());
// //FontFactory.RegisteredFonts.Add(fn[i]);
// //FontFactory.Register(
// Console.WriteLine(fn[i]);
//}
//ICollection<string> registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;
//foreach (string s in registeredFonts)
//{
// Console.WriteLine("pre-registered: " + s);
//}
if (!FontFactory.Contains("georgia-bold"))
{
FontFactory.RegisterDirectories();
Console.WriteLine("had to register everything"); }
//registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;
//foreach (string s in registeredFonts)
//{
// Console.WriteLine("post-registered: " + s);
//}
Font myfont = FontFactory.GetFont("georgia-bold");
string nameOfField = "my_field";
AcroFields.Item fld = pdfFormFields.GetFieldItem(nameOfField);
//set the text of the form field
pdfFormFields.SetField(nameOfField, "test stuff");
pdfFormFields.SetField("TheFieldIWantTheFontFrom", "test more stuff");
bool madeit = pdfFormFields.SetFieldProperty(nameOfField, "textfont", myfont.BaseFont, null);
bool madeit2 = pdfFormFields.SetFieldProperty(nameOfField, "textsize", 8f, null);
pdfFormFields.RegenerateField(nameOfField);
// Set the flattening flag to false, so the document can continue to be edited
pdfStamper.FormFlattening = true;
// close the pdf stamper
pdfStamper.Close();
//get the bytes from the MemoryStream
byte[] content = output.ToArray();
using (FileStream fs = File.Create(#"C:\MadScience\MSE_Results.pdf"))
{
//byte[] b = outList[i];
fs.Write(content, 0, (int)content.Length);
fs.Flush();
}
}
Yes you can re-use fonts and the PDF specification actually encourages it. You should, however, keep in mind that some fonts may be embedded as subsets only.
The below code is adapted from this post (be careful, that site has nasty popups sometimes). See the comments in the code for more information. This code was tested against iTextSharp 5.4.4.
/// <summary>
/// Look for the given font name (not file name) in the supplied PdfReader's AcroForm dictionary.
/// </summary>
/// <param name="reader">An open PdfReader to search for fonts in.</param>
/// <param name="fontName">The font's name as listed in the PDF.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInForm(PdfReader reader, String fontName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));
//Bail if there isn't one
if (acroForm == null) {
return null;
}
//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);
//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);
//Look for the actual font and return it
return findFontInFontDict(FONT, fontName);
}
/// <summary>
/// Helper method to look at a specific font dictionary for a given font string.
/// </summary>
/// <remarks>
/// This method is a helper method and should not be called directly without knowledge of
/// the internals of the PDF spec.
/// </remarks>
/// <param name="fontDict">A /FONT dictionary.</param>
/// <param name="fontName">Optional. The font's name as listed in the PDF. If not supplied then the first font found is returned.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInFontDict(PdfDictionary fontDict, string fontName) {
//This code is adapted from http://osdir.com/ml/java.lib.itext.general/2004-09/msg00018.html
foreach (var internalFontName in fontDict.Keys) {
var internalFontDict = (PdfDictionary)PdfReader.GetPdfObject(fontDict.Get(internalFontName));
var baseFontName = (PdfName)PdfReader.GetPdfObject(internalFontDict.Get(PdfName.BASEFONT));
//// compare names, ignoring the initial '/' in the baseFontName
if (fontName == null || baseFontName.ToString().IndexOf(fontName) == 1) {
var iRef = (PRIndirectReference)fontDict.GetAsIndirectObject(internalFontName);
if (iRef != null) {
return BaseFont.CreateFont(iRef);
}
}
}
return null;
}
And here's the test code that runs this. It first creates a sample document with an embedded font and then it creates a second document based upon that and re-uses that font. In your code you'll need to actually know beforehand what the font name is that you're searching for. If you don't have ROCK.TTF (Rockwell) installed you'll need to pick a different font file to run this.
//Test file that we'll create with an embedded font
var file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Secondary file that we'll try to re-use the font above from
var file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test2.pdf");
//Path to font file that we'd like to use
var fontFilePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ROCK.TTF");
//Create a basefont object
var font = BaseFont.CreateFont(fontFilePath, BaseFont.WINANSI, true);
//Get the name that we're going to be searching for later on.
var searchForFontName = font.PostscriptFontName;
//Step #1 - Create sample document
//The below block creates a sample PDF file with an embedded font in an AcroForm, nothing too special
using (var fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Create our field, set the font and add it to the document
var tf = new TextField(writer, new iTextSharp.text.Rectangle(50, 50, 400, 150), "first-name");
tf.Font = font;
writer.AddAnnotation(tf.GetTextField());
doc.Close();
}
}
}
//Step #2 - Look for font
//This uses a stamper to draw on top of the existing PDF using a font already embedded
using (var fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var reader = new PdfReader(file1)) {
using (var stamper = new PdfStamper(reader, fs)) {
//Try to get the font file
var f = findFontInForm(reader, searchForFontName);
//Make sure we found something
if (f != null) {
//Draw some text
var cb = stamper.GetOverContent(1);
cb.BeginText();
cb.MoveText(200, 400);
cb.SetFontAndSize(f, 72);
cb.ShowText("Hello!");
cb.EndText();
}
}
}
}
EDIT
I made a small modification to the findFontInFontDict method above. The second parameter is now optional. If null it returns the first font object that it finds in the supplied dictionary. This change allows me to introduce the below method which looks for a specific field by name and gets the font.
static BaseFont findFontByFieldName(PdfReader reader, String fieldName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));
//Bail if there isn't one
if (acroForm == null) {
return null;
}
//Get the fields array
var FIELDS = acroForm.GetAsArray(PdfName.FIELDS);
if (FIELDS == null || FIELDS.Length == 0) {
return null;
}
//Loop through each field reference
foreach (var fieldIR in FIELDS) {
var field = (PdfDictionary)PdfReader.GetPdfObject(fieldIR);
//Check the field name against the supplied field name
if (field.GetAsString(PdfName.T).ToString() == fieldName) {
//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);
//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);
return findFontInFontDict(FONT);
}
}
return null;
}

ITextsharp invalidates signatures when using lines or rectangles

When I use ITextSharp to digitally sign a document that is already digitally signed using this code it invalidates the other signatures. If I digitally sign using a text or image it works fine. Is this an Adobe/Itextsharp limitation or is something wrong with the code?
public void SignWithLine(string pdfFilePath, string outputFilePath, LineAnnotation lineAnnotation)
{
double xStartPoint = 89.285969238281268, yStartPoint = 343.08978515624881, xEndPoint = 72.7515234375, yEndPoint = 496.03341796874878, lineStroke = .24;
CertificateWrapper certificate = CertificateWrapper.GetCertificateInformationFromSignature(GetCertificateInformation());
PdfReader reader = new PdfReader(pdfFilePath);
PdfTemplate layer = null;
using (PdfStamper signature = PdfStamper.CreateSignature(reader, null, '\0', outputFilePath, true))
{
PdfSignatureAppearance signatureAppearance = signature.SignatureAppearance;
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC;
Rectangle rect = new Rectangle((float)Math.Min(xStartPoint, xEndPoint), (float)Math.Min(yStartPoint, yEndPoint), (float)Math.Min(xStartPoint, xEndPoint) + (float)Math.Abs(xEndPoint - xStartPoint), (float)Math.Min(yStartPoint, yEndPoint) + (float)Math.Abs(yEndPoint - yStartPoint));
signatureAppearance.SetVisibleSignature(rect, lineAnnotation.PageIndex + 1, GetCertificateFieldName());
layer = signatureAppearance.GetLayer(2);
PdfContentByte cb = signature.GetUnderContent(lineAnnotation.PageIndex + 1);
cb.SetLineWidth((float)lineStroke);
cb.MoveTo((float)xStartPoint, (float)yStartPoint);
cb.LineTo((float)(xEndPoint), (float)(yEndPoint));
cb.Stroke();
signatureAppearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
// Normal signature, not a certification
MakeSignature.SignDetached(signatureAppearance, certificate.DigitalSignature, certificate.Chain, null, null, null, 0, true);
signature.Close();
}
}
signature is your PdfStamper. You draw a line on
PdfContentByte cb = signature.GetUnderContent(lineAnnotation.PageIndex + 1);
i.e. You draw it in the content stream of a page. This counts as a change of the page content and, therefore, is forbidden by the original signature. For details on the allowed changes cf. this answer.
I found a way to do this by modifying the iTextSharp library.
// First I overloaded the SetVisibleSignature to pass a list of int
public void SetVisibleSignature(Rectangle pageRect, String fieldName, List pageList)
{
pages = pageList; // pages is a private List pages;
...
}
// Secondly, in the PreClose event you update it as shown below
sigField.Page = pagen;
if (pagen != 0)
writer.AddAnnotation(sigField, pagen);
else if (pages != null && pages.Count > 0)
pages.ForEach(f => writer.AddAnnotation(sigField, f)); // this annotates all pages with the same signature
else
throw new DocumentException("No pages specified for signature.");

Sign PDF file on last page

I am using C# and iTextSharp 3.1 to sign PDF files. The signing is working, but I want to sign on the last page of the file. The code I use is such :
reader = new PdfReader(inputPDF);
int numberOfPages = reader.NumberOfPages;
PdfStamper st = PdfStamper.CreateSignature(reader, new FileStream(outputPDF, FileMode.Create, FileAccess.Write), '\0', null, true);
PdfSignatureAppearance sap = st.SignatureAppearance;
if (logoSign != null)
{
// Scale img to fit
logoSign.ScaleToFit(100, 50);
// Set Signature position on page
logoSign.SetAbsolutePosition(300, 80);
sap.Image = logoSign;
}
sap.SetCrypto(this.myCert.Akp, this.myCert.Chain, null, PdfSignatureAppearance.VERISIGN_SIGNED);
if (SigReason.Length > 0)
sap.Reason = SigReason;
if (SigContact.Length > 0)
sap.Contact = SigContact;
if (SigLocation.Length > 0)
sap.Location = SigLocation;
if (visible)
sap.SetVisibleSignature(mySignRect, 1, null);
try
{
st.Close();
} catch(Exception e) { }
This code signs of the 1st page of the file. I want o sign on the last page of the file. How do I set to sign on last page.
I also wonder, the same code doesn't work in iTextSharp5.4.2. It gives error on sap.SetCrypto() and st.Close(). Any idea how to I make it work in 5.4.2.
Thanks
Please try the C# version of the examples that come with the white paper referenced by mkl: http://sourceforge.net/p/itextsharp/code/HEAD/tree/tutorial/signatures/

PDFNet trying to add a text not working

I am basically trying out PDFNet and tweaking one of the samples of PDFNet. Here is the code:
PDFNet.Initialize();
// Relative path to the folder containing test files.
string input_path = "../../../../TestFiles/";
string output_path = "../../../../TestFiles/Output/";
PDFDoc doc = new PDFDoc(input_path + "form1.pdf");
for (int index = 1; index <= doc.GetPageCount(); index++)
{
Page page = doc.GetPage(index);
ElementBuilder eb = new ElementBuilder(); // ElementBuilder is used to build new Element objects
eb.Reset(); // Reset GState to default
ElementWriter writer = new ElementWriter(); // ElementWriter is used to write Elements to the page
writer.Begin(page);
// Begin writing a block of text
string data = "Page " + index;
Element element = eb.CreateTextRun(data, Font.Create(doc, Font.StandardType1Font.e_times_roman, true), 100.0);
element.SetTextMatrix(10, 0, 0, 10, 100, 100);
GState gstate = element.GetGState();
gstate.SetTextRenderMode(GState.TextRenderingMode.e_stroke_text);
gstate.SetStrokeColorSpace(pdftron.PDF.ColorSpace.CreateDeviceRGB());
gstate.SetStrokeColor(new pdftron.PDF.ColorPt(1, 0, 0));
writer.WriteElement(element);
writer.End();
writer.Dispose(); // save changes to the current page
}
doc.Save(output_path + "element_builder.pdf", SDFDoc.SaveOptions.e_linearized);
doc.Close();
But problem is, no text is added to element_builder.pdf. It is just copied as it is and looks same as form1.pdf. Can anybody help me out?
This is the link to PDFNet http://www.pdftron.com/pdfnet/downloads.html
I am using 64 bit version for .Net 4.0
It seems that you are missing the calls eb.CreateTextBegin() and eb.CreateTextEnd(). You should try something like this:
PDFNet.Initialize();
// Relative path to the folder containing test files.
string input_path = "../../../../TestFiles/";
string output_path = "../../../../TestFiles/Output/";
PDFDoc doc = new PDFDoc(input_path + "form1.pdf");
ElementWriter writer = new ElementWriter();
ElementBuilder eb = new ElementBuilder();
for (int index = 1; index <= doc.GetPageCount(); index++)
{
Page page = doc.GetPage(index);
writer.Begin(page);
eb.Reset();
// Begin writing a block of text
string data = "Page " + index;
Element element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman, true), 10.0);
writer.WriteElement(element);
eb.CreateTextRun(data);
element.SetTextMatrix(10, 0, 0, 10, 100, 100);
GState gstate = element.GetGState();
gstate.SetTextRenderMode(GState.TextRenderingMode.e_fill_text);
gstate.SetStrokeColorSpace(pdftron.PDF.ColorSpace.CreateDeviceRGB());
gstate.SetStrokeColor(new pdftron.PDF.ColorPt(1, 0, 0));
writer.WriteElement(element);
writer.WriteElement(eb.CreateTextEnd());
writer.End();
}
writer.Dispose();
eb.Dispose();
doc.Save(output_path + "element_builder.pdf", SDFDoc.SaveOptions.e_linearized);
doc.Close();
Btw. a possibly simpler way to add text to an existing page may be to use 'pdftron.PDF.Stamper' as shown in Stamper sample.

Categories

Resources