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

Notification

Icon
Error

Options
Go to last post Go to first unread
rhnatiuk  
#1 Posted : Tuesday, April 30, 2019 8:08:35 AM(UTC)
rhnatiuk

Rank: Advanced Member

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

Thanks: 8 times
Hi,

Trying to figure out how to add a link (http URI) to an existing PDF.

I can add texts and paths, but links are somehow mysterious.

This is what I've got:

var pdfLinkAnnotation = new PdfLinkAnnotation(pdfPage);
pdfLinkAnnotation.Rectangle = boundingBox;
pdfLinkAnnotation.Contents = text;
pdfPage.Annots.Add(pdfLinkAnnotation);

And I see a link added to PDF (the cursor turns to finger over that box), but I cannot specify URI, cannot specify how it should look (background, border, etc.).

Can anyone help?

Thanks!
Paul Rayman  
#2 Posted : Tuesday, April 30, 2019 9:15:56 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
To set the URI for the annotation, you must create an Action dictionary and fill it in accordance with the documentation.
For a simple link to a web page, you can use the code below.

Code:

var linkAnnot = new PdfLinkAnnotation(annots.Page);
linkAnnot.Rectangle = new FS_RECTF(10, 790, 160, 760);
linkAnnot.Dictionary["A"] = PdfTypeDictionary.Create();
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["S"] = PdfTypeName.Create("URI");
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["URI"] = PdfTypeString.Create("https://patagames.com");
annots.Add(linkAnnot);


Since this annotation does not have an appearance stream, it will be invisible and can be used to make link under existing content on the page.

Instead, you can create an annotation that will have an appearance stream and will be visible on the screen. Please see the code below.
Code:

PdfCommon.Initialize();

var doc = PdfDocument.CreateNew(new PdfForms());
doc.Pages.InsertPageAt(0, 800, 800);
doc.Pages[0].CreateAnnotations();
var annots = doc.Pages[0].Annots;

var linkAnnot = new PdfLinkAnnotation(annots.Page);
//specify URI
linkAnnot.Dictionary["A"] = PdfTypeDictionary.Create();
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["S"] = PdfTypeName.Create("URI");
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["URI"] = PdfTypeString.Create("https://patagames.com");
//Link Text, border and BG
var textObj = PdfTextObject.Create("link text", 10, 750, PdfFont.CreateStock(linkAnnot.Page.Document, FontStockNames.Arial), 12);
var pathObj = PdfPathObject.Create(FillModes.Winding, true);
pathObj.Path.AppendRect(new FS_RECTF(textObj.BoundingBox.left - 5, textObj.BoundingBox.top + 5, textObj.BoundingBox.right + 5, textObj.BoundingBox.bottom - 5));
pathObj.StrokeColor = FS_COLOR.Red;
pathObj.FillColor = FS_COLOR.Yellow;
pathObj.CalcBoundingBox();

linkAnnot.CreateEmptyAppearance(AppearanceStreamModes.Normal);
linkAnnot.NormalAppearance.Add(pathObj);
linkAnnot.NormalAppearance.Add(textObj);
linkAnnot.GenerateAppearance(AppearanceStreamModes.Normal);


doc.Pages[0].Dispose();
annots.Add(linkAnnot);
                       
pdfViewer1.Document = doc;
thanks 1 user thanked Paul Rayman for this useful post.
rhnatiuk on 5/2/2019(UTC)
rhnatiuk  
#3 Posted : Thursday, May 2, 2019 1:52:02 AM(UTC)
rhnatiuk

Rank: Advanced Member

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

Thanks: 8 times
Hi Paul, and thank you for your code - it worked! :) But...

Originally Posted by: Paul Rayman Go to Quoted Post

Since this annotation does not have an appearance stream, it will be invisible and can be used to make link under existing content on the page.



I see something else... When I add a link with the following code, the link is created but has a black rectangle around it:

Code:
var pdfTypeDictionary = PdfTypeDictionary.Create();
pdfTypeDictionary["S"] = PdfTypeName.Create("URI");
pdfTypeDictionary["URI"] = PdfTypeString.Create("https://google.com?" + text);
var pdfLinkAnnotation = new PdfLinkAnnotation(pdfPage) {
    Rectangle = boundingBox
};
pdfLinkAnnotation.Dictionary["A"] = pdfTypeDictionary;
pdfPage.Annots.Add(pdfLinkAnnotation);


I would survive with a completely "faceless" link, or I need some way to customize its appearance. Any ideas?

I found NormalAppearance and its siblings on pdfLinkAnnotation, but, again, no idea how to use those, as the code below didn't work - the black border is gone, but so is the link (the cursor is not turning to pointer anymore over the link text):

Code:
pdfLinkAnnotation.CreateEmptyAppearance(AppearanceStreamModes.Normal);
pdfLinkAnnotation.GenerateAppearance(AppearanceStreamModes.Normal);


UPDATE I solved the problem by adding the box that I am generating to highlight the underlying text to the pdfLinkAnnotation.NormalAppearance collection, instead of adding it to the page itself. But the question remains - is there a way to create a link without any UI that occupies a certain rectangle?

One more question: is there any decent documentation (guide) for the library? The API reference is probably good as a reference, once you know what to look for, but it is very difficult to write something like you wrote starting with it.

Thanks!

Edited by user Thursday, May 2, 2019 2:16:25 AM(UTC)  | Reason: Not specified

Paul Rayman  
#4 Posted : Thursday, May 2, 2019 10:12:42 PM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
try the following
Code:
var linkAnnot = new PdfLinkAnnotation(annots.Page);
//specify URI
linkAnnot.Dictionary["A"] = PdfTypeDictionary.Create();
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["S"] = PdfTypeName.Create("URI");
linkAnnot.Dictionary["A"].As<PdfTypeDictionary>()["URI"] = PdfTypeString.Create("https://patagames.com");
//Disable highlighting.
linkAnnot.Dictionary["H"] = PdfTypeName.Create("N"); 
//Disable border
linkAnnot.Dictionary["Border"] = PdfTypeArray.Create();
linkAnnot.Dictionary["Border"].As<PdfTypeArray>().AddInteger(0);
linkAnnot.Dictionary["Border"].As<PdfTypeArray>().AddInteger(0);
linkAnnot.Dictionary["Border"].As<PdfTypeArray>().AddInteger(0);


The general annotation dictionary is described on page 606, and the annotation-reference dictionary on page 622 of the PDF specification
https://www.adobe.com/co...ve/pdf_reference_1-7.pdf


As for generating the appearance stream.
When the stream is absent, many viewers display annotations incorrectly. Even Adobe Reader does not fully comply with the specifications on this subject. Therefore, the use of the appearance stream is preferred.

When you generate an empty appearance stream, the annotation rectangle is recalculated to zero width and height. You must explicitly point it to the area you need (as well as the BBox entry of annotation dictionary)

Or you can just create invisible path like shown below
Code:

//invisible path
var pathObj = PdfPathObject.Create(FillModes.None, false);
pathObj.Path.AppendRect(new FS_RECTF(10, 790, 150, 750));
pathObj.CalcBoundingBox();

Edited by user Thursday, May 2, 2019 10:28:17 PM(UTC)  | Reason: Not specified

thanks 1 user thanked Paul Rayman for this useful post.
rhnatiuk on 5/3/2019(UTC)
rhnatiuk  
#5 Posted : Friday, May 3, 2019 5:27:21 AM(UTC)
rhnatiuk

Rank: Advanced Member

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

Thanks: 8 times
Thank you! Works great!
MeJonah  
#6 Posted : Thursday, May 30, 2019 10:56:20 AM(UTC)
MeJonah

Rank: Newbie

Groups: Registered
Joined: 2/18/2019(UTC)
Posts: 2
United States
Location: Minnesota

I'm trying to figure out how to link to another page within the same PDF. I can't find any examples. I'm thinking it should be something like this:
Code:

var linkAnnot2 = new PdfLinkAnnotation(theDoc.Pages[0]);
            linkAnnot2.Rectangle = new Patagames.Pdf.FS_RECTF(100, 100, 100, 100);
            linkAnnot2.Dictionary["A"] = PdfTypeDictionary.Create();
            linkAnnot2.Dictionary["A"].As<PdfTypeDictionary>()["S"] = PdfTypeName.Create("GoTo");
            var test = new PdfDestination(theDoc);
            test.PageIndex = 1;
            test.DestinationType = Patagames.Pdf.Enums.DestinationTypes.Fit;
            linkAnnot2.Dictionary["A"].As<PdfTypeDictionary>()["D"] = test;

The last line obviously doesn't work, as you can't put a PdfDestination into a PdfBaseType field. Any suggestions?
Paul Rayman  
#7 Posted : Tuesday, June 4, 2019 11:46:28 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
You mau use destinations class instead of low-level dictionaries.

Something like this
Code:
            ////////////////////////// PdfLinkAnnotation ///////////////////
            var link = new PdfLinkAnnotation(annots.Page);
            link.Rectangle = new FS_RECTF(10, 790, 160, 760);
            link.Link.Destination = new PdfDestination(annots.Page.Document);
            link.Link.Destination.PageIndex = 2;

            link.Link.QuadPoints.Add(new FS_QUADPOINTSF(new FS_RECTF(20, 780, 150, 770)));

            annots.Add(link);
MeJonah  
#8 Posted : Wednesday, June 12, 2019 8:31:19 PM(UTC)
MeJonah

Rank: Newbie

Groups: Registered
Joined: 2/18/2019(UTC)
Posts: 2
United States
Location: Minnesota

Awesome, thanks! Was right in front of me.
Users browsing this topic
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.