|
|
In this code example, if the string in Line 28 were much longer, how could you configure the txtObj to wrap across multiple lines?
|
|
|
I have slightly modify the code above to show how you can add text object to existing PDF Code:
static void Main(string[] args)
{
PdfCommon.Initialize();
//Save text to existing document
var doc = PdfDocument.Load(@"d:\1\review.pdf");
var pageDict = doc.Pages[0].Dictionary;
AddTextToPage(doc, doc.Pages[0]);
//or to newly created document
var doc = PdfDocument.CreateNew();
doc.Pages.InsertPageAt(0, 500, 500);
AddTextToPage(doc, doc.Pages[0]);
}
private static void AddTextToPage(PdfDocument doc, PdfPage page)
{
var pageDict = page.Dictionary;
//Create and insert a text object
PdfTextObject txtObj = PdfTextObject.Create();
LOGFONT lf = new LOGFONT() { lfCharSet = LOGFONT.FontCharSet.ANSI_CHARSET, lfPitchAndFamily = LOGFONT.FontPitchAndFamily.DEFAULT_PITCH | LOGFONT.FontPitchAndFamily.FF_ROMAN, lfWeight = LOGFONT.FontWeight.FW_BOLD };
txtObj.Font = PdfFont.CreateWindowsFont(doc, lf, false, true);
txtObj.FillColor = Color.Blue;
txtObj.Transform(50, 0, 0, 50, 0, 0);
txtObj.Location = new PointF(50, 50);
txtObj.TextUnicode = "Hello World";
page.PageObjects.InsertObject(txtObj);
//Get the list of indirect objects and add the text object Font dictionary into it
var list = PdfIndirectList.FromPdfDocument(doc);
int objNum = list.Add(txtObj.Font.Dictionary);
//Create an indirect object for text object Font dictionary
var indirect = PdfTypeIndirect.Create(list, objNum);
//Get "Font" dictionary from page resource
PdfTypeDictionary fontDict = GetFontDictFromResource(pageDict, list);
//Insert that indirect object into Page's resources
fontDict.Add("FontMyQniqName", indirect);
//Create streram for the text object
var stream = PdfTypeStream.Create();
objNum = list.Add(stream);
indirect = PdfTypeIndirect.Create(list, objNum);
//Encode text object and insert it into stream
byte[] data = EncodeTextObject(txtObj);
var streamDict = PdfTypeDictionary.Create();
streamDict.Add("Length", PdfTypeNumber.Create(data.Length));
stream.Init(data, streamDict);
//Get page's content and add text stream into it
PdfTypeArray contents = GetContentsAsArray(list, pageDict);
contents.Add(indirect, list);
//Save document
doc.Save(@"d:\1\review_modified.pdf", SaveFlags.NoIncremental);
}
private static PdfTypeDictionary GetFontDictFromResource(PdfTypeDictionary pageDict, PdfIndirectList list)
{
var res = (pageDict["Resources"] as PdfTypeDictionary);
if (!res.ContainsKey("Font"))
{
var ret = PdfTypeDictionary.Create();
int objNum = list.Add(ret);
var indirect = PdfTypeIndirect.Create(list, objNum);
res.Add("Font", indirect);
return ret;
}
var font = res["Font"];
if (font is PdfTypeDictionary)
return font as PdfTypeDictionary;
else if(font is PdfTypeIndirect)
{
if ((font as PdfTypeIndirect).Direct is PdfTypeDictionary)
return (font as PdfTypeIndirect).Direct as PdfTypeDictionary;
}
throw new Exception("Unexpected type of font resource");
}
public static PdfTypeArray GetContentsAsArray(PdfIndirectList list, PdfTypeDictionary pageDict)
{
if(!pageDict.ContainsKey("Contents"))
{
var array = PdfTypeArray.Create();
//Add array into list of indirect objects
list.Add(array);
//And set it as a contents of the page
pageDict.SetIndirectAt("Contents", list, array);
return array;
}
var contents = pageDict["Contents"];
//check the original content whether it's an array
if (contents is PdfTypeArray)
return contents as PdfTypeArray; //if contents is a array just return it
else if (contents is PdfTypeIndirect)
{
if ((contents as PdfTypeIndirect).Direct is PdfTypeArray)
return (contents as PdfTypeIndirect).Direct as PdfTypeArray; //if contents is a reference to array then return that array
else if ((contents as PdfTypeIndirect).Direct is PdfTypeStream)
{
//if contents is a reference to a stream then create a new array and insert stream as a first element of array
var array = PdfTypeArray.Create();
array.AddIndirect(list, (contents as PdfTypeIndirect).Direct);
//Add array into list of indirect objects
list.Add(array);
//And set it as a contents of the page
pageDict.SetIndirectAt("Contents", list, array);
return array;
}
else
throw new Exception("Unexpected content type");
}
else
throw new Exception("Unexpected content type");
}
private static byte[] EncodeTextObject(PdfTextObject txtObj)
{
string ret = string.Format(
@"BT
/FontMyQniqName {0} Tf
{1} {2} {3} {4} {5} {6} Tm
{7} {8} {9} rg
({10})Tj
ET",
txtObj.FontSize,
txtObj.Matrix.a, txtObj.Matrix.b, txtObj.Matrix.c, txtObj.Matrix.d, txtObj.Matrix.e, txtObj.Matrix.f,
txtObj.FillColor.R, txtObj.FillColor.G, txtObj.FillColor.B,
txtObj.TextAnsi
);
return System.Text.Encoding.GetEncoding(1251).GetBytes(ret);
}
|
|
|
Code:
public void CreatePdfWithText()
{
PdfCommon.Initialize();
//pdfViewer1.DocumentLoaded += PdfViewer1_DocumentLoaded;
//this.Shown += (s, e) => { pdfViewer1.LoadDocument(@"d:\0\hello-world.pdf"); };
//Create new document
var doc = PdfDocument.CreateNew();
//And Insert one page into it
doc.Pages.InsertPageAt(0, 500, 500);
var pageDict = doc.Pages[0].Dictionary;
//Create and insert a text object
PdfTextObject txtObj = PdfTextObject.Create();
LOGFONT lf = new LOGFONT() { lfCharSet = LOGFONT.FontCharSet.ANSI_CHARSET, lfPitchAndFamily = LOGFONT.FontPitchAndFamily.DEFAULT_PITCH | LOGFONT.FontPitchAndFamily.FF_ROMAN, lfWeight = LOGFONT.FontWeight.FW_BOLD };
txtObj.Font = PdfFont.CreateWindowsFont(doc, lf, false, true);
txtObj.FillColor = Color.Blue;
txtObj.Transform(50, 0, 0, 50, 0, 0);
txtObj.Location = new PointF(50, 50);
txtObj.TextUnicode = "Hello World";
doc.Pages[0].PageObjects.InsertObject(txtObj);
//Get the list of indirect objects and add the Font's dictionary into it
var list = PdfIndirectList.FromPdfDocument(doc);
int objNum = list.Add(txtObj.Font.Dictionary);
//Create an indirect object for Font's dictionary
var indirect = PdfTypeIndirect.Create(list, objNum);
//Insert that indirect object into Page's resources
var fontRes = PdfTypeDictionary.Create();
fontRes.Add("F1", indirect);
(pageDict["Resources"] as PdfTypeDictionary).Add("Font", fontRes);
//Create Contents dictionary for the page and insert into Page's dictionary as an indirect object
var contents = PdfTypeStream.Create();
objNum = list.Add(contents);
indirect = PdfTypeIndirect.Create(list, objNum);
pageDict.Add("Contents", indirect);
//Encode text object and insert it into Contents
byte[] data = EncodeTextObject(txtObj);
var contentsDict = PdfTypeDictionary.Create();
contentsDict.Add("Length", PdfTypeNumber.Create(data.Length));
contents.Init(data, contentsDict);
//Save document
doc.Save(@"d:\0\test.pdf", SaveFlags.NoIncremental);
}
private byte[] EncodeTextObject(PdfTextObject txtObj)
{
string ret = string.Format(
@"BT
/F1 {0} Tf
{1} {2} {3} {4} {5} {6} Tm
{7} {8} {9} rg
({10})Tj
ET",
txtObj.FontSize,
txtObj.TextMatrix.a, txtObj.TextMatrix.b, txtObj.TextMatrix.c, txtObj.TextMatrix.d, txtObj.TextMatrix.e, txtObj.TextMatrix.f,
txtObj.FillColor.R, txtObj.FillColor.G, txtObj.FillColor.B,
txtObj.TextAnsi
);
return System.Text.Encoding.GetEncoding(1251).GetBytes(ret);
}
|
|
|
I also need to add text objects to a page and save them. Is now a code example available??? I tryed a lot, but don't get them working.
|
|
|
Hi - I would also like to know if this has been resolved.
We're developing a FinTech cloud-based forms service and PDFium has met all the requirements...except for writing text to a PDF file (not screen). One scenario requires merging multiple PDFs into a single document. When we receive the document back we need to split the document into the individual PDFs again for archiving. We were hoping to write text into the header or footer area of a page and save to a physical file. The header text would be used to indicated each individual document and help with the split.
Ive read through the code samples and Adobe's PDF Developer guide. I understand the Dictionary stream and Indirect Pointer to a Text Object. The question is, how to get the PdfTextObject handle into the stream via PDFium? It appears we need additional API to resolve the PdfTextObject memory (handle) into a stream. PDFium does this for image objects, so it sounds like it's fairly close to doing the same for text objects.
Please advise when we might have this feature?
Cheers D
|
|
|
Hi
Guys let us know , if above one is solved also please share the example, regarding Placing and replacing of Text Objects.
|
|
|
We are working on an example for this. I hope it will appear in the near future.
|
|
|
Thank you for your response. I really appreciate the reference that I am starting to delve into. Just to be sure that I understand…. Using Page.PageObjects.InsertObject(txtObj) is not suppose to save when using the PdfDocument.Save method. There is no easy way to create a new Document, add text objects and then save it. However, if I can figure out how to alter the PdfPage.Dictionary structure that will save with a PdfDocument.Save? Would the low level modification of the ‘Contents’ stream look similar to your post on inserting an image? http://forum.patagames.c...sition-in-WPF-Pdf-ViewerAre there any other good examples of the general use of these directories anywhere? I load in a 1 page PDF file into PdfDocuments and get the PdfPage.Dictionary. I grab the ‘Contents’ entry which is a PdfTypeArray with 1 entry. That 1 entry is of type PdfTypeIndirect. The Direct Property is a PdfTypeStream of length 1048 with 2 Dictionary entries (‘Filter’ with a value of ‘Flat eDecode’ and ‘Length’ with a value of ‘1048’) I read in the 1048 byte stream into byte array. I am stuck trying to figure out what to do with that byte array. I’m assuming that is where the content is for my PDF document which is mostly Text Objects. Does anyone know of any links that might help me to figure out what the next step is? Again, I appreciate the information!
|
|
|
|
|
|
I am simply trying to add text to a document and save it. I'm afraid I am missing something simple, but don't know what else to try. The code looks like this:
PdfDocument pdfDocument1 = PdfDocument.Load("c:\\test001.pdf", null, null); PdfPage page = pdfDocument1.Pages[0];
PdfTextObject txtObj = PdfTextObject.Create(); txtObj.Font = PdfFont.CreateStock(pdfDocument1, FontStockNames.Arial); txtObj.FillColor = Color.Black; txtObj.Transform(50, 0, 0, 50, 0, 0); txtObj.Location = new PointF(50, 50); txtObj.TextAscii = "Hello"; page.PageObjects.InsertObject(txtObj);
pdfDocument1.Save("c:\\test001.pdf", Patagames.Pdf.Enums.SaveFlags.NoIncremental, 0);
The result is just the original document. If I add page.GenerateContent(); The resulting page is blank.
What is the proper way to add or remove a TextObject from a pdfDocument and then be able to save it?
Thanks for any help!
|