Example_22

Linking a contents page to chapters and back with "Destinations" and "Go To" actions on text, a box and an image, in a PDF/UA document.

Example_22.pdf — the PDF this example creates.

using System;
using System.IO;
using System.Diagnostics;
using PDFjet.NET;

/**
 * Example_22.cs
 * This example links a contents page to three chapters, and each chapter
 * back to the contents, with destinations and "Go To" actions.
 */
public class Example_22 {
    public Example_22() {
        PDF pdf = new PDF(new BufferedStream(
            new FileStream("Example_22.pdf", FileMode.Create)));
        pdf.SetCompliance(Compliance.PDF_UA_1);
        pdf.SetTitle("Internal links and destinations");

        Font f1 = new Font(pdf, IBMPlexSans.Regular);
        Font f2 = new Font(pdf, IBMPlexSans.SemiBold);

        String[] chapters = {
            "Destinations",
            "Go To actions",
            "Links on shapes and images",
        };
        String[] texts = {
            "A destination is a named place in a document. The title of this chapter "
                + "is the destination \"chapter1\", set with setDestination.",
            "A Go To action makes something a link to a destination. The chapter titles "
                + "on the contents page are text lines with a Go To action.",
            "Rectangles and images can be links too. Click the arrow in the top left "
                + "corner, or the arrow image next to it, to go back to the contents.",
        };

        // The contents page. The destination is the top of the page.
        Page page = new Page(pdf, Letter.PORTRAIT);
        page.AddDestination("contents", 0f, 0f);

        TextLine text = new TextLine(f2, "Contents");
        text.SetStructureType(StructElem.H1);
        text.SetFontSize(24f);
        text.SetLocation(90f, 100f);
        text.DrawOn(page);

        // The contents are a list: each item is the number of its chapter,
        // which labels the item, and the title of the chapter, which is the
        // body of the item and the link to it. A reader reads them as the
        // items of a list and not as lines of text that follow one another.
        float y = 150f;
        page.BeginStructElement(StructElem.L);
        for (int i = 0; i < chapters.Length; i++) {
            page.BeginStructElement(StructElem.LI);
            String label = "Chapter " + (i + 1) + ":";
            text = new TextLine(f1, label);
            text.SetStructureType(StructElem.LBL);
            text.SetFontSize(14f);
            text.SetLocation(90f, y);
            text.DrawOn(page);

            // The title, its underline and its link are the body of the item,
            // which is what an LI may hold beside its label.
            page.BeginStructElement(StructElem.LBODY);
            text = new TextLine(f1, chapters[i]);
            text.SetFontSize(14f);
            text.SetTextColor(Color.blue);
            text.SetUnderline(true);
            text.SetGoToAction("chapter" + (i + 1));
            text.SetLocation(90f + f1.StringWidth(14f, label + " "), y);
            text.DrawOn(page);
            page.EndStructElement();
            page.EndStructElement();
            y += 30f;
        }
        page.EndStructElement();

        for (int i = 0; i < chapters.Length; i++) {
            page = new Page(pdf, Letter.PORTRAIT);

            // The title of the chapter is its destination.
            text = new TextLine(f2, "Chapter " + (i + 1) + ": " + chapters[i]);
            text.SetFontSize(20f);
            text.SetDestination("chapter" + (i + 1));
            text.SetLocation(90f, 100f);
            text.DrawOn(page);

            TextBlock textBlock = new TextBlock(f1, texts[i]);
            textBlock.SetFontSize(12f);
            textBlock.SetLineSpacing(1.5f);
            textBlock.SetLocation(90f, 125f);
            textBlock.SetWidth(430f);
            textBlock.DrawOn(page);

            text = new TextLine(f1, "Back to the contents");
            text.SetFontSize(12f);
            text.SetTextColor(Color.blue);
            text.SetUnderline(true);
            text.SetGoToAction("contents");
            text.SetLocation(90f, 250f);
            text.DrawOn(page);
        }

        // On the last page, a rect with no border links to the contents too.
        Rect rect = new Rect(20f, 20f, 20f, 20f);
        rect.SetGoToAction("contents");
        rect.DrawOn(page);

        // Create an up arrow and place it in the rect
        PDFjet.NET.Path path = new PDFjet.NET.Path();
        path.Add(new Point(30f, 21f));
        path.Add(new Point(37f, 29f));
        path.Add(new Point(33f, 29f));
        path.Add(new Point(33f, 39f));
        path.Add(new Point(27f, 39f));
        path.Add(new Point(27f, 29f));
        path.Add(new Point(23f, 29f));
        path.SetClosed(true);
        path.SetStrokeColor(Color.deepskyblue);
        path.SetFillShape(true);
        path.DrawOn(page);

        // And so does an image of an arrow.
        Image image = new Image(pdf, "images/up-arrow.png");
        image.SetAltDescription(
                "An arrow pointing up, which goes back to the contents of the document when it is clicked.");
        image.SetLocation(50f, 20f);
        image.SetGoToAction("contents");
        image.DrawOn(page);

        pdf.Complete();
    }

    public static void Main(String[] args) {
        Stopwatch sw = Stopwatch.StartNew();
        long time0 = sw.ElapsedMilliseconds;
        new Example_22();
        long time1 = sw.ElapsedMilliseconds;
        sw.Stop();
        Console.WriteLine($"Example_22 => {time1 - time0,4} ms");
    }
}   // End of Example_22.cs

©2026 PDFjet Software.