logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

2 Pages12>
Options
Go to last post Go to first unread
rhnatiuk  
#1 Posted : Wednesday, June 12, 2019 2:27:06 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Hi,

We have hit into a major road-block. After modifying a PDF page (adding a few link annotations, a few boxes, and corresponding rectangles), we are calling pdfPage.GenerateContent(), and it takes a lot of time - more than 1 minute on large files, and at least 5-6 seconds on smaller files.

The library we have used before Pdfium.Net had no such problem - the creation of modified PDFs was near-instant.

Any ideas? Can we get improved GenerateContent, or can we somehow avoid using it? It seems that GenerateContent is somehow re-creating the whole PDF (but more than 1 minute?) instead of an incremental update with adding new objects only.

Thank you!
Paul Rayman  
#2 Posted : Friday, June 14, 2019 5:45:07 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
Are you using latest version of SDK? Page's content generation was improved in the version 3.38.2704


1. GenerateContent() recreates the contents of the whole page. This is a feature of the PDF structure.
2. GenerateContent() works only on the page content, but not on the entire document.
3. Perhaps your page contains a lot of objects.
4. Perhaps you have subscribed to the processing of notifications about the generation of each object and the slowdown occurs somewhere in this handler in your code.
5. If you add annotations only, then you should not call the GenerateContent(), because annotations are not part of the page content.

Could you please provide your document for analysis?
rhnatiuk  
#3 Posted : Friday, June 14, 2019 6:07:46 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post
Are you using latest version of SDK? Page's content generation was improved in the version 3.38.2704


Yes, we are using the latest version. 4.7.2704 (from the web site, or NuGet), the dll says that its file version is 4.2.3.471 though.

Originally Posted by: Paul Rayman Go to Quoted Post
1. GenerateContent() recreates the contents of the whole page. This is a feature of the PDF structure.
2. GenerateContent() works only on the page content, but not on the entire document.


Yes, that is what we have figured out...

Originally Posted by: Paul Rayman Go to Quoted Post
3. Perhaps your page contains a lot of objects.


With 1600 objects (a rather small drawing) it already takes about one second. The document itself 722-SWC-10.1.pdf (43kb) downloaded 4 time(s).. The same happens with all document, on all computers. The longest I had to wait for GenerateContent was in the direction of one minute (ok, those files are big - 5 meters x 1 meter, a lot of graphics=drawing), on rather modern i7.

Originally Posted by: Paul Rayman Go to Quoted Post
4. Perhaps you have subscribed to the processing of notifications about the generation of each object and the slowdown occurs somewhere in this handler in your code.


No - all intact.

Originally Posted by: Paul Rayman Go to Quoted Post
5. If you add annotations only, then you should not call the GenerateContent(), because annotations are not part of the page content.


Unfortunately, we have to add boxes for links (background and border). And those are content then.

Originally Posted by: Paul Rayman Go to Quoted Post
Could you please provide your document for analysis?


Sure, it is attached. But, as I said, reproduces with all other documents.

Our old library did not have kind of problem (had many others though). Also, I do not necessarily understand, why the whole page must be recreated, especially that we are only adding to it, and not removing. I have seen that it is possible to pass a list of objects to GenerateContent on the pdfium side, so I thought about some kind of incremental generation. But, needed APIs are missing then.
rhnatiuk  
#4 Posted : Thursday, June 20, 2019 3:50:56 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Hi Paul Rayman ,

Any news on the topic?

We would like to use Pdfium.Net only in our product, instead of using Pdfium.Net to read the document and get all the necessary information from it, and then the old library to add links and rectangles and to save the document. But so far, it seems that it is the only viable solution for us...

Thank you in advance!

Edited by user Thursday, June 20, 2019 3:51:37 AM(UTC)  | Reason: Not specified

Paul Rayman  
#5 Posted : Thursday, June 20, 2019 7:45:04 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
I looked at the document that you sent - it has a rather complicated structure and a large number of objects on a page. Therefore, the full regeneration of these objects takes some time. It is unlikely that something can be optimized.

However, in your situation there is a solution!
In fact, you do not need to regenerate all the objects, since you do not change them.

I can suggest several solutions:
1. Use the rectangle and/or line annotations to add a border around the link instead of adding objects to the page content; or
2. Use the annotation's NormalAppearance collection to draw a border instead of drawing in the page content. An example can be found here; or
3. Convert the page's content into an array of contents and add new page content to this array. In this case, you do not need to regenerate all objects. You will generate only the objects you have added, it works very fast. A detailed example is here:
Code:
static void Main(string[] args)
{
    using (var doc = PdfDocument.Load(@"e:\0\722-SWC-10.1.pdf"))
    {
        var page = doc.Pages[0];
        var contentsArray = ConvertContentsToArray(page);
        using (var form = PdfFormObject.Create(page))
        {
            //Add some objects to the form object
            form.PageObjects.Add(PdfTextObject.Create("Sample Text", 150, 150, PdfFont.CreateStock(doc, FontStockNames.Arial), 45.0f));
            //Create empty stream and add it to the list of indirect objects
            var stream = PdfTypeStream.Create();
            var list = PdfIndirectList.FromPdfDocument(doc);
            list.Add(stream);
            //Generate content of form object to that stream
            bool b = Pdfium.FPDF_GenerateContentToStream(doc.Handle, form.PageObjects.Handle, stream.Handle, IntPtr.Zero);
            //Add stream to the contentsArray
            contentsArray.AddIndirect(list, stream);
        }
        doc.Save(@"e:\0\722-SWC-10.1_modified.pdf", SaveFlags.NoIncremental);
    }
}


and ConvertContentsToArray

Code:
public static PdfTypeArray ConvertContentsToArray(PdfPage page)
{
    var pageDict = page.Dictionary;
    var list = PdfIndirectList.FromPdfDocument(page.Document);

    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 if(contents is PdfTypeStream)
    {
        //if contents is a stream instead of reference to a stream then try to convert it to a reference then create a new array and insert stream as a first element of array
        list.Add(contents);
        var array = PdfTypeArray.Create();
        array.AddIndirect(list, contents);
        //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");
}

Edited by user Thursday, June 20, 2019 9:38:05 PM(UTC)  | Reason: fix bug in the code - in the "else if(contents is PdfTypeStream)" block

thanks 1 user thanked Paul Rayman for this useful post.
rhnatiuk on 6/20/2019(UTC)
rhnatiuk  
#6 Posted : Thursday, June 20, 2019 8:16:34 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post
I looked at the document that you sent - it has a rather complicated structure and a large number of objects on a page. Therefore, the full regeneration of these objects takes some time. It is unlikely that something can be optimized.

However, in your situation there is a solution!
In fact, you do not need to regenerate all the objects, since you do not change them.

I can suggest several solutions:
1. Use the rectangle and/or line annotations to add a border around the link instead of adding objects to the page content; or
2. Use the annotation's NormalAppearance collection to draw a border instead of drawing in the page content. An example can be found here; or
3. Convert the page's content into an array of contents and add new page content to this array. In this case, you do not need to regenerate all objects. You will generate only the objects you have added, it works very fast. A detailed example is here:


Wow! You ARE magician! :) Your third proposal with ConvertContentsToArray works very well (at least with a quick try)! Thank you very much!!!
rhnatiuk  
#7 Posted : Monday, June 24, 2019 2:20:34 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Hi Paul,

Sorry that I was too optimistic, but the option number 3 is broken: all text runs get some awkward font and size (see 722-SWC-10.1-modified.pdf (43kb) downloaded 2 time(s).). Even if I do absolutely no changes to the content, i.e. remove the

Code:
form.PageObjects.Add(PdfTextObject.Create("Sample Text", 150, 150, PdfFont.CreateStock(doc, FontStockNames.Arial), 45.0f));


line in your code. In fact, the line

Code:
var form = PdfFormObject.Create(page)


is sufficient on its own to kill the document (i.e. load the document, create a form as above, save the document => broken texts).

Is there anything that can be done about it?

Edited by user Monday, June 24, 2019 2:26:26 AM(UTC)  | Reason: Not specified

Paul Rayman  
#8 Posted : Monday, June 24, 2019 4:32:11 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
Hmm ...

Indeed, PdfFormObject has a strange side effect on this document. I think it should be investigated.
However, in your task, this is just an auxiliary element that is easy to replace. Please use this code instead:

Code:
static void Main(string[] args)
{
    using (var doc = PdfDocument.Load(@"e:\0\722-SWC-10.1.pdf"))
    {
        var page = doc.Pages[0];
        var contentsArray = ConvertContentsToArray(page);
        using (var tmpAnnot = new PdfTextAnnotation(page))
        {
            tmpAnnot.CreateEmptyAppearance(AppearanceStreamModes.Normal);
            //Add some objects to the form object
            tmpAnnot.NormalAppearance.Add(PdfTextObject.Create("Sample Text", 150, 150, PdfFont.CreateStock(doc, FontStockNames.Arial), 45.0f));
            //Create empty stream and add it to the list of indirect objects
            var stream = PdfTypeStream.Create();
            var list = PdfIndirectList.FromPdfDocument(doc);
            list.Add(stream);
            //Generate content of form object to that stream
            bool b = Pdfium.FPDF_GenerateContentToStream(doc.Handle, tmpAnnot.NormalAppearance.Handle, stream.Handle, IntPtr.Zero);
            //Add stream to the contentsArray
            contentsArray.AddIndirect(list, stream);
        }
        doc.Save(@"e:\0\722-SWC-10.1_modified.pdf", SaveFlags.NoIncremental);
    }
}
rhnatiuk  
#9 Posted : Monday, June 24, 2019 5:00:32 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Thank you for your response and a new idea!

Originally Posted by: Paul Rayman Go to Quoted Post
Hmm ...

Indeed, PdfFormObject has a strange side effect on this document. I think it should be investigated.


Ok. Good to know that it was not us! :) If this behavior would be fixed, it would be the cleanest solution...

Originally Posted by: Paul Rayman Go to Quoted Post
However, in your task, this is just an auxiliary element that is easy to replace. Please use this code instead:...


Do we have to create a new stream for each text and box added to the document? Or is it somehow possible to add multiple elements to one such "layer"?
rhnatiuk  
#10 Posted : Monday, June 24, 2019 5:11:09 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post

However, in your task, this is just an auxiliary element that is easy to replace. Please use this code instead:...


There is a problem here as well: it seems I cannot add semi-transparent boxes this way - they are always opaque.

Paul Rayman  
#11 Posted : Monday, June 24, 2019 8:11:59 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
Originally Posted by: rhnatiuk Go to Quoted Post

Do we have to create a new stream for each text and box added to the document?


No, you can use one stream for all your objects.

Originally Posted by: rhnatiuk Go to Quoted Post

There is a problem here as well: it seems I cannot add semi-transparent boxes this way - they are always opaque.


Oh yes!
Resources must be located in the dictionary of the page, but not in the stream.
Please replace the content generation code (line 17) with the following:
Code:
//Generate content of form object to that stream
if (!page.Dictionary.ContainsKey("Resources"))
    page.Dictionary["Resources"] = PdfTypeDictionary.Create();
bool b = Pdfium.FPDF_GenerateContentToStream(doc.Handle, tmpAnnot.NormalAppearance.Handle, stream.Handle, page.Dictionary["Resources"].Handle);
rhnatiuk  
#12 Posted : Tuesday, June 25, 2019 1:41:23 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post
Resources must be located in the dictionary of the page, but not in the stream.


Yes, transparency works using this new code!

But, the moment I add these two lines (even leaving the dictionary out of FPDF_GenerateContentToStream):

Code:
if (!page.Dictionary.ContainsKey("Resources"))
page.Dictionary["Resources"] = PdfTypeDictionary.Create();



the same problem as using
Code:
PdfFormObject.Create(page)
comes back, i.e. all text runs get wrong font and width.

And, I guess, PdfFormObject.Create internally adds the Resources dictionary, thus the result.

One more problem is, that we cannot have link annotations with bounding boxes and backgrounds. While those are visible in Chrome and Foxit, but Adobe Reader and PDF-XChange Editor show links without UI (link can be clicked, but no border nor background are there). We hoped to use it like this, but it seems that we cannot. Thus, we need boxes/backgrounds to be part of the page (via streams would be OK), but transparency is missing there, and then link annotations are broken in other viewers. :(

Edited by user Tuesday, June 25, 2019 6:13:56 AM(UTC)  | Reason: Not specified

Paul Rayman  
#13 Posted : Tuesday, June 25, 2019 7:41:21 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
Hm...

PDF specification says:
Quote:
Resources dictionary (Required; inheritable) A dictionary containing any resources required by
the page (see Section 3.7.2, “Resource Dictionaries”). If the page requires
no resources, the value of this entry should be an empty dictionary. Omitting the entry entirely indicates that the resources are to be inherited from
an ancestor node in the page tree.


So, instead of creating new Resource (if it does not exists) we should try to find parent object first.
Something like this
Code:
//Generate content of form object to that stream
PdfTypeDictionary resDict = FindResource(page.Dictionary);
bool b = Pdfium.FPDF_GenerateContentToStream(doc.Handle, tmpAnnot.NormalAppearance.Handle, stream.Handle, resDict.Handle);


and

Code:
private static PdfTypeDictionary FindResource(PdfTypeDictionary dict)
{
    if (dict.ContainsKey("Resources"))
        return dict["Resources"].As<PdfTypeDictionary>();

    if (dict.ContainsKey("Parent"))
        return FindResource(dict["Parent"].As<PdfTypeDictionary>());

    dict["Resources"] = PdfTypeDictionary.Create();
    return dict["Resources"].As<PdfTypeDictionary>();
}



I hope this is final solution :)

Edited by user Tuesday, June 25, 2019 7:42:40 AM(UTC)  | Reason: Not specified

rhnatiuk  
#14 Posted : Tuesday, June 25, 2019 8:53:33 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Hi,

Originally Posted by: Paul Rayman Go to Quoted Post
[...]
So, instead of creating new Resource (if it does not exists) we should try to find parent object first.
Something like this
[...]
I hope this is final solution :)


WOW! YES, IT WORKS NOW!!! :D THANK YOU!!!

But, ... (I hope you will not try to murder me! :) ... the border of the rectangle we are adding now using annotation is very thin. Looks like PDF viewer is trying hard to display it as 1 pixel, no matter what. The color is correct, but the thickness is heading to 0. Our code:

Code:
var pdfPathObject = PdfPathObject.Create(FillModes.Winding, true);
pdfPathObject.FillColor = new FS_COLOR(50, 0, 200, 0);
pdfPathObject.StrokeColor = new FS_COLOR(50, 200, 0, 0);
pdfPathObject.Path.AppendRect(boundingBox);
tmpAnnot.NormalAppearance.Add(pdfPathObject);


I looked for some ways to set the stroke thickness, but no success. Before the change with Resources dictionary, the border was thick, I think.
Paul Rayman  
#15 Posted : Tuesday, June 25, 2019 9:12:30 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)

https://pdfium.patagames...PageObj_SetLineWidth.htm

Code:
Pdfium.FPDFPageObj_SetLineWidth(pdfPathObject.Handle, 10.0f);

thanks 1 user thanked Paul Rayman for this useful post.
rhnatiuk on 6/26/2019(UTC)
rhnatiuk  
#16 Posted : Wednesday, June 26, 2019 1:52:02 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post

https://pdfium.patagames...PageObj_SetLineWidth.htm

Code:
Pdfium.FPDFPageObj_SetLineWidth(pdfPathObject.Handle, 10.0f);



Great! Now all is working as expected! :) Thank you!
rhnatiuk  
#17 Posted : Wednesday, June 26, 2019 5:18:34 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Greetings from Finland!

Sorry to bug you again, but it seems that the approach with "annotation as container converted to stream" is not working for some files (in our case, those PDF files are generated by Teigha / OpenDesign Alliance converter from DWG)... :(

Here are three files:

jv 755002_Limited (2).pdf (5kb) downloaded 2 time(s). - original file

jv 755002_Limited (2)-modified links.pdf (9kb) downloaded 1 time(s). - modified so that link annotations have rectangles (correct positions and sizes, but does not work in e.g. Adobe reader)

jv 755002_Limited (2)-modified objects.pdf (9kb) downloaded 2 time(s). - modified so that link annotations have no rectangles, but rectangles are added into other annotation converted to stream (incorrect positions and sizes); I specifically use PdfLinkAnnotation here, but the result is same with other annotation-containers.

The code (this one will output both variants; colors may vary; just adds links to all text runs):

Code:

			using (var doc = PdfDocument.Load(@"C:\temp\jv 755002_Limited (2).pdf"))
			{
				var page = doc.Pages[0];
				if (page.Annots == null) page.CreateAnnotations();
				var contentsArray = ConvertContentsToArray(page);
				using (var tmpAnnot = new PdfLinkAnnotation(page))
				{
					tmpAnnot.CreateEmptyAppearance(AppearanceStreamModes.Normal);
					tmpAnnot.NormalAppearance.Add(PdfTextObject.Create("Sample Text", 150, 150, PdfFont.CreateStock(doc, FontStockNames.Arial), 45.0f));

					var pdfTextObjects = (
						from pdfPageObject in page.PageObjects
						let pdfTextObject = pdfPageObject as PdfTextObject
						where pdfTextObject != null
						select pdfTextObject).ToList();
					foreach (var pdfTextObject in pdfTextObjects)
					{
						var text = pdfTextObject.TextUnicode;
						var boundingBox = pdfTextObject.BoundingBox;
						var x = boundingBox.left;
						var y = boundingBox.top;
						var w = boundingBox.Width;
						var h = boundingBox.Height;
						Console.WriteLine($"@({x}, {y}) {w} x {h} : {text}");

						var pdfPathObject = PdfPathObject.Create(FillModes.Winding, true);
						pdfPathObject.FillColor = new FS_COLOR(50, 200, 0, 0);
						pdfPathObject.StrokeColor = new FS_COLOR(50, 0, 100, 0);
						//Patagames.Pdf.Pdfium.FPDFPageObj_SetLineWidth(pdfPathObject.Handle, 1.15f);
						var d = 1;
						var bb = new FS_RECTF(x - d, y + d, x + w + d, y - h - d);
						pdfPathObject.Path.AppendRect(bb);
						pdfPathObject.CalcBoundingBox();
						tmpAnnot.NormalAppearance.Add(pdfPathObject);

						var pdfPathObjectNormalAppearance = PdfPathObject.Create(FillModes.Winding, false);
						pdfPathObjectNormalAppearance.FillColor = new FS_COLOR(50, 0, 200, 0);
						pdfPathObjectNormalAppearance.StrokeColor = new FS_COLOR(50, 100, 0, 0);
						pdfPathObjectNormalAppearance.Path.AppendRect(bb);
						pdfPathObjectNormalAppearance.CalcBoundingBox();
						var pdfTypeDictionary = PdfTypeDictionary.Create();
						pdfTypeDictionary["S"] = PdfTypeName.Create("URI");
						pdfTypeDictionary["URI"] = PdfTypeString.Create("https://google.com?" + text);
						var pdfLinkAnnotation = new PdfLinkAnnotation(page)
						{
							Rectangle = bb
						};
						pdfLinkAnnotation.Dictionary["A"] = pdfTypeDictionary;
						pdfLinkAnnotation.Dictionary["H"] = PdfTypeName.Create("N");
						var pdfTypeArray = PdfTypeArray.Create();
						pdfTypeArray.AddInteger(0);
						pdfTypeArray.AddInteger(0);
						pdfTypeArray.AddInteger(0);
						pdfLinkAnnotation.Dictionary["Border"] = pdfTypeArray;
						pdfLinkAnnotation.CreateEmptyAppearance(AppearanceStreamModes.Normal);
						pdfLinkAnnotation.NormalAppearance.Add(pdfPathObjectNormalAppearance);
						pdfLinkAnnotation.GenerateAppearance(AppearanceStreamModes.Normal);
						page.Annots.Add(pdfLinkAnnotation);
					}
					var stream = PdfTypeStream.Create();
					var list = PdfIndirectList.FromPdfDocument(doc);
					list.Add(stream);
					var resDict = FindResource(page.Dictionary);
					Patagames.Pdf.Pdfium.FPDF_GenerateContentToStream(doc.Handle, tmpAnnot.NormalAppearance.Handle, stream.Handle, resDict.Handle);
					//Add stream to the contentsArray
					contentsArray.AddIndirect(list, stream);
				}
				doc.Save(@"C:\temp\jv 755002_Limited-mod.pdf", SaveFlags.Incremental);
			}


It seems that conversion from fake annotation to stream shrinks all contained objects. But this happens only to some files, like this one. Any ideas?

Edited by user Wednesday, June 26, 2019 5:19:54 AM(UTC)  | Reason: Not specified

Paul Rayman  
#18 Posted : Wednesday, June 26, 2019 6:01:14 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
Why you do not want to use PdfSquareAnnotation?
rhnatiuk  
#19 Posted : Wednesday, June 26, 2019 6:24:32 AM(UTC)
rhnatiuk

Rank: Advanced Member

Groups: Registered
Joined: 4/30/2019(UTC)
Posts: 34
Man
Finland
Location: Raisio

Thanks: 9 times
Originally Posted by: Paul Rayman Go to Quoted Post
Why you do not want to use PdfSquareAnnotation?


But the result is the same with any Pdf*Annotation container - rectangles end up in the left bottom corner of the document. :( You can check the jv 755002_Limited (2)-modified objects.pdf (9kb) downloaded 2 time(s). file - it shows the result of annotation used as a container.

Also, annotations are not displayed correctly in Adobe reader of PDF-XChange Editor (Foxit, Chrome show them fine).

Edited by user Wednesday, June 26, 2019 6:25:48 AM(UTC)  | Reason: Not specified

Paul Rayman  
#20 Posted : Wednesday, June 26, 2019 6:36:06 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 789

Thanks: 1 times
Was thanked: 98 time(s) in 96 post(s)
No, no

I mean following
Code:
public void test2()
{
    using (var doc = PdfDocument.Load(@"e:\7\jv 755002_Limited.pdf"))
    {
        var page = doc.Pages[0];
        if (page.Annots == null)
            page.CreateAnnotations();

        var pdfTextObjects = (
            from pdfPageObject in page.PageObjects
            let pdfTextObject = pdfPageObject as PdfTextObject
            where pdfTextObject != null
            select pdfTextObject).ToList();

        foreach (var pdfTextObject in pdfTextObjects)
        {
            var text = pdfTextObject.TextUnicode;
            var boundingBox = pdfTextObject.BoundingBox;
            var x = boundingBox.left;
            var y = boundingBox.top;
            var w = boundingBox.Width;
            var h = boundingBox.Height;
            var d = 1;
            var bb = new FS_RECTF(x - d, y + d, x + w + d, y - h - d);

            var pdfTypeDictionary = PdfTypeDictionary.Create();
            pdfTypeDictionary["S"] = PdfTypeName.Create("URI");
            pdfTypeDictionary["URI"] = PdfTypeString.Create("https://google.com?" + text);
            var pdfLinkAnnotation = new PdfLinkAnnotation(page)
            {
                Rectangle = bb
            };
            pdfLinkAnnotation.Dictionary["A"] = pdfTypeDictionary;
            pdfLinkAnnotation.Dictionary["H"] = PdfTypeName.Create("N");
            var pdfTypeArray = PdfTypeArray.Create();
            pdfTypeArray.AddInteger(0);
            pdfTypeArray.AddInteger(0);
            pdfTypeArray.AddInteger(0);
            pdfLinkAnnotation.Dictionary["Border"] = pdfTypeArray;


            var squareAnnot = new PdfSquareAnnotation(page, bb, new FS_COLOR(50, 255, 0, 0), new FS_COLOR(50, 0, 255, 0));
            page.Annots.Add(squareAnnot);
            page.Annots.Add(pdfLinkAnnotation);
        }
        doc.Save(@"e:\7\jv 755002_Limited-mod.pdf", SaveFlags.Incremental);
    }
    Process.Start(@"e:\7\jv 755002_Limited-mod.pdf");
}


The point of idea here
Code:
var squareAnnot = new PdfSquareAnnotation(page, bb, new FS_COLOR(50, 255, 0, 0), new FS_COLOR(50, 0, 255, 0));
page.Annots.Add(squareAnnot);
page.Annots.Add(pdfLinkAnnotation);

Edited by user Wednesday, June 26, 2019 6:37:12 AM(UTC)  | Reason: Not specified

Users browsing this topic
2 Pages12>
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.