简体   繁体   中英

Adding an Annotation to a PdfFormXObject so the Annotation is reusable

I'm using iText 7 to construct reusable PDF components that I reuse across multiple pages within a document. I'm using iText-do.net for this task (v7), using F# as the language. (This shouldn't be hard to follow for non-F# people as it's just iText calls:D)

I know how to add annotations to a Page, that isn't the issue. Adding the annotation to the page is as simple as page.AddAnnotation(newAnnotation).

Where I'm having difficulty, is that there is no "Page" associated with a Canvas when you are using a PdfFormXObject() to render a Pdf fragment.

let template = new PdfFormXObject(rect)
let templateCanvas = PdfCanvas(template, pageContext.Canvas.GetPdfDocument())
let newCanvas = new Canvas(templateCanvas, rect)

Once I have the new Canvas, I try to write to the Canvas and add the Annotation via Page.AddAnnotation(). The problem is that there is no Page attached to the PdfFormXObject!

// Create the destination and annotation (destPage is the pageNumber)
let dest = PdfExplicitDestination.CreateFitB(destPage)
let action = PdfAction.CreateGoTo(dest)

let annotation = PdfLinkAnnotation(rect)
let border = iText.Kernel.Pdf.PdfAnnotationBorder(0f, 0f, 0f)

// set up the Annotation with action and display information
annotation
    .SetHighlightMode(PdfAnnotation.HIGHLIGHT_PUSH)
    .SetAction(action)
    .SetBorder(border)
    |> ignore
    
// Try adding the annotation to the page BOOM! (There is *NO* page (null) associated with newCanvas)
newCanvas.GetPage().AddAnnotation(annotation) |> ignore  // HELP HERE: Is there another way to do this?

The issue is that I do not know of a different way to set the Annotation on the canvas. Is there a way to render the annotation and just add the annotation directly to the canvas as raw PDF instructions?

Alternatively, is there a way create a different reusable PDF fragment in iText so I can also reuse the GoTo annotation.

NB I could split off the annotations and then apply them every time I use the PdfFormXObject() on a new page, but that sort of defeats the purpose of reusing Pdf fragments (template) in my final PDF to reduce it's size.

If you can point me in the right direction, that would be great.

Again, this is not how to add an annotation to a Page(), that's easy. It's how to add an annotation to a PdfFormXObject (or similar mechanism that I'm unaware of for constructing rusable Pdf fragments).

-- As per John's comments below: I cannot seem to find any reference to single use annotations.

I'm aware of the following example link , so I modified it to look like this:

private static void Main(string[] args)
    {
        try
        {
            PdfDocument pdfDocument = new PdfDocument(new PdfWriter("TestMultiLink.pdf"));
            Document document = new Document(pdfDocument);

            string destinationName = "MyForwardDestination";

            // Create a PdfStringDestination to use more than once.
            var stringDestination = new PdfStringDestination(destinationName);

            for (int page = 1; page <= 50; page++)
            {
                document.Add(new Paragraph().SetFontSize(100).Add($"{page}"));
                switch (page)
                {
                    case 1:  // First use of PdfStringDestination
                        document.Add(new Paragraph(new Link("Click here for a forward jump", stringDestination).SetFontSize(20)));
                        break;
                    case 3:  // Re-use the stringDestination
                        document.Add(new Paragraph(new Link("Click here for a forward jump", stringDestination).SetFontSize(10)));
                        break;
                    case 42:
                        pdfDocument.AddNamedDestination(destinationName, PdfExplicitDestination.CreateFit(pdfDocument.GetLastPage()).GetPdfObject());
                        break;
                }
                if (page < 50)
                    document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
            }

            document.Close();            
        }
        catch (Exception e)
        {
            Console.WriteLine($"Ouch: {e.Message}");
        }
    }

If you dig into the iText source for iText.Layout.Link, you'll see that the String Destination is added as an Annotation. Therefore, I'm not sure if John's answer is true anymore.

Does anyone know how I can convert the Annotation to a Dictionary and how I would go about adding the PdfDictionary (raw) info into the PftFormXObject?

Thanks

@johnwhitington is correct.

Per PDF specification, annotations can only be added to a page, they cannot be added to a form XObject. It is not a limitation of iText or any other PDF library.

Annotations cannot be reused, each annotation is a distinct object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM