Rank: Member
Groups: Registered
Joined: 7/26/2016(UTC) Posts: 25  Location: Somerset Thanks: 5 times
|
Hi, I have just investigated the 'PdfTypeBase.Clone()' method for the first time and was wondering if it can be used to copy a dictionary object (including all the sub-directories, sub-streams, sub-arrays, etc it contains) from one PDF to another PDF? Using the debugger to examine a cloned dictionary suggests that the answer is 'yes' if method 'Clone(true)' is called, however this appears to replace all indirect objects in the dictionary with direct objects. I want all indirect objects to remain indirect and this appears to be achievable by calling 'Clone(false)', but the resultant dictionary cannot be simply inserted into another PDF because the indirect object numbers will be wrong and the objects will not be added to the PDF's indirect object list. So, is there any easy way to insert a cloned dictionary into another PDF and still retain all indirect objects as indirect? Also, have I interpreted the meaning of the 'bDirect' parameter of 'Clone(bDirect)' correctly? (Since the documentation at https://pdfium.patagames...17-7219-0819f886d761.htmappears to be broken.) Many thanks for your help. Terry.
|
|
|
|
|
|
Rank: Administration
Groups: Administrators
Joined: 1/5/2016(UTC) Posts: 1,138
Thanks: 10 times Was thanked: 133 time(s) in 130 post(s)
|
The API has no such method to do this in one call. It seems you'll have to clone each such object, insert it into the list of indirect objects in a new document, and then change the references in the dictionary.
|
 1 user thanked Paul Rayman for this useful post.
|
|
|
|
Rank: Member
Groups: Registered
Joined: 7/26/2016(UTC) Posts: 25  Location: Somerset Thanks: 5 times
|
Okay, thanks Paul, this is what I suspected (feared!). I just thought I would check with you first and perhaps save myself some work. I was very impressed with how well Clone() worked on very complicated dictionaries containing references to lots of other dictionaries, streams and arrays, therefore great for copying within the same PDF, but for copying between PDFs maintaining valid references to indirect objects is tricky.
Thanks for your help. Terry.
|
|
|
|
|
|
Rank: Administration
Groups: Administrators
Joined: 1/5/2016(UTC) Posts: 1,138
Thanks: 10 times Was thanked: 133 time(s) in 130 post(s)
|
Here is the code for cloning PDF objects from one document to another without losing indirect references. There is two overloads for dictionary and for array. Indirect objects may be contained in these two type of objects only. Also please note the object may referenced by other object and this object may reference to first one. In order to prevent the endless looping of the algorithm, a list of processed objects is used. If the object has already been processed, then it is skipped. Otherwise the object is processed and stored in this list. Code:private static Dictionary<IntPtr, byte> processedObjects = new Dictionary<IntPtr, byte>();
private void CloneIndirectObjects(PdfTypeDictionary dict, PdfIndirectList dstList)
{
foreach (var item in dict)
{
if (processedObjects.ContainsKey(item.Value.Handle))
continue;
var obj = item.Value;
processedObjects.Add(obj.Handle, 1);
if (obj is PdfTypeIndirect)
{
obj = (obj as PdfTypeIndirect).Direct.Clone();
dstList.Add(obj);
dict.SetIndirectAt(item.Key, dstList, obj);
}
if (obj.Is<PdfTypeDictionary>())
CloneIndirectObjects(obj.As<PdfTypeDictionary>(), dstList);
else if (obj.Is<PdfTypeArray>())
CloneIndirectObjects(obj.As<PdfTypeArray>(), dstList);
}
}
private void CloneIndirectObjects(PdfTypeArray array, PdfIndirectList dstList)
{
for (int i = 0; i < array.Count; i++)
{
if (processedObjects.ContainsKey(array[i].Handle))
continue;
var obj = array[i];
processedObjects.Add(obj.Handle, 1);
if (obj is PdfTypeIndirect)
{
obj = (obj as PdfTypeIndirect).Direct.Clone();
dstList.Add(obj);
array.SetAt(i, obj, dstList);
}
if (obj.Is<PdfTypeDictionary>())
CloneIndirectObjects(obj.As<PdfTypeDictionary>(), dstList);
else if (obj.Is<PdfTypeArray>())
CloneIndirectObjects(obj.As<PdfTypeArray>(), dstList);
}
}
usage: Code:// firstly we should clone dictionary (or array) in usual way using API.
var dict = srcTextObj.Font.Dictionary.Clone(false) as PdfTypeDictionary; // <----------- FALSE should be passed to the Clone method
// Next recursively clone all indirect objects inside the cloned one.
var dstList = PdfIndirectList.FromPdfDocument(dstDoc);
CloneIndirectObjects(dict, dstList);
//Thats all. Now the dict may be used in other document.
Edited by user Wednesday, October 3, 2018 8:38:59 PM(UTC)
| Reason: Not specified
|
 1 user thanked Paul Rayman for this useful post.
|
|
|
|
Rank: Member
Groups: Registered
Joined: 7/26/2016(UTC) Posts: 25  Location: Somerset Thanks: 5 times
|
Thanks Paul, very helpful and interesting. First class support as always!
Terry.
|
|
|
|
|
|
Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.
Important Information:
The Patagames Software Support Forum uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close