Interaction

Interactive PDF

Hyperlinks

Hyperlinks (such as a link to a website) or internal links to a PDF page. When they are stored in a StartStop node that has the action node.ActionHyperlink the hyperlink is extracted and added to the PDF.

type Hyperlink struct {
	URI   string
	Local string
}

If the Local field is set, the hyperlinks points to a named destination, if the URL field is set the hyperlink points to that URL. In PDF terms, the Local link creates a /GoTo action and the URL creates a /URI action.

Bookmarks

Bookmarks, or “outlines” in PDF jargon, are described in the PDF backend.

Depending on your application, it might be convenient to create an outline item in the StartStop node callback. This is especially true if you don’t know where the outline item should point to.

startstop := node.NewStartStop()
startstop.Action = node.ActionDest
startstop.Value = 123   // a unique id

When the backend encounters a StartStop node in the PDF output with the Action value of ActionDest, it creates a new Dest object from the value.

The idea now is to retrieve this Dest object and create an outline entry. This can be done using a callback:

startstop.Callback = func(n node.Node) string {
	startStop := n.(*node.StartStop)
	num := startStop.Value.(int)
	destObj := doc.GetNumDest(num)
	outline := &pdf.Outline{
		Title: "a bookmark",
		Dest:  fmt.Sprintf("[ %s /XYZ %f %f 0]", destObj.PageObjectnumber.Ref(), destObj.X, destObj.Y),
		Open:  true,
	}
	// add outline to the PDF writer
	curOutlines := doc.PDFWriter.Outlines
	for i := 1; i < attValues.Level; i++ {
		if len(*curOutlines) == 0 {
			slog.Error(fmt.Sprintf("level %d bookmark does not exist for new bookmark (title %s)", i, title))
		} else {
			curOutlines = &(*curOutlines)[len(*curOutlines)-1].Children
		}
	}
	*curOutlines = append(*curOutlines, outline)
	return ""
}