I got it to work. Links don't jump to the exact location but to the top of the page, though.
This is the method that I call after I imported all pages from PDF2 to PDF1 (I simplified it a little).
I am quite new to C# and PDFsharp. I am sure this can be done more elegantly.
doc2_ is the second PDF. The one that is appended to PDF1.
pp_ is an object of a class that I wrote. It's basically just two PdfPage lists. When importing the pages from PDF2 into PDF1 I save here the original page in PDF2 and the newly imported page in PDF1. That way, when looking at pages in PDF2 I always know which is the corresponding page in PDF1. If someone needs the code just ask.
iPageOffset_ is the number of pages that were in PDF1 before anything was imported from PDF2.
Code:
private void FixLinks(PdfDocument doc2_, PagePairs pp_, int iPageOffset_)
{
int iPageCount = pp_.GetSize();
for (int j = 0; j < iPageCount; j++)
{
PdfPage? page1 = null;
PdfPage? page2 = null;
pp_.GetPagePair(j, out page1, out page2);
if ((page1 == null) || (page2 == null))
return;
List<PdfAnnotation> la2Remove = new();
List<PdfAnnotation> la2Add = new();
// Go through the annotations of the original page in PDF2
for (int i = 0; i < page2.Annotations.Count; i++)
{
PdfAnnotation annot = page2.Annotations[i];
if (annot.Elements.GetString(PdfAnnotation.Keys.Subtype) != "/Link")
continue; // Not a link
PdfArray? dest = annot.Elements.GetArray("/Dest");
if (dest == null)
continue; // Link without destination?
PdfRectangle rect = annot.Elements.GetRectangle(PdfAnnotation.Keys.Rect);
int i0basePageIndex2 = -1;
PdfReference? targetPage = dest.Elements.GetReference(0);
if (targetPage == null)
{ // This is a document link that points to a specific page with a 0-based index
try
{
i0basePageIndex2 = dest.Elements.GetInteger(0);
}
catch (InvalidCastException)
{
continue;
}
}
else
{ // This is a link that points to a specific location on a page.
// Try to find the referenced page in PDF2
for (int p = 0; p < doc2_.PageCount; p++)
{
if (doc2_.Pages[p].Reference == targetPage)
{ // This is the page that was referenced in PDF2. Remember the 0-based index
i0basePageIndex2 = p;
break;
}
}
}
if (i0basePageIndex2 > -1)
{ // Remember which annotation that was imported into PDF1 to remove
la2Remove.Add(page1.Annotations[i]);
// Then create a new annotation to add later
la2Add.Add(PdfLinkAnnotation.CreateDocumentLink(rect, i0basePageIndex2 + 1 + iPageOffset_));
}
}
// Remove the annotation to replace
foreach (PdfAnnotation a in la2Remove)
page1.Annotations.Remove(a);
// Then add the new one
foreach (PdfAnnotation a in la2Add)
page1.Annotations.Add(a);
}
}