unipdf/model/outline.go
2019-05-16 20:44:51 +00:00

194 lines
4.9 KiB
Go

/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package model
import (
"github.com/unidoc/unipdf/v3/core"
)
// OutlineDest represents the destination of an outline item.
// It holds the page and the position on the page an outline item points to.
type OutlineDest struct {
Page int64
X float64
Y float64
}
// NewOutlineDest returns a new outline destination which can be used
// with outline items.
func NewOutlineDest(page int64, x, y float64) OutlineDest {
return OutlineDest{
Page: page,
X: x,
Y: y,
}
}
// ToPdfObject returns a PDF object representation of the outline destination.
func (od OutlineDest) ToPdfObject() core.PdfObject {
return core.MakeArray(
core.MakeInteger(od.Page),
core.MakeName("XYZ"),
core.MakeFloat(od.X),
core.MakeFloat(od.Y),
core.MakeFloat(0),
)
}
// Outline represents a PDF outline dictionary (Table 152 - p. 376).
// Currently, the Outline object can only be used to construct PDF outlines.
type Outline struct {
items []*OutlineItem
}
// NewOutline returns a new outline instance.
func NewOutline() *Outline {
return &Outline{}
}
// Add appends a top level outline item to the outline.
func (o *Outline) Add(item *OutlineItem) {
o.items = append(o.items, item)
}
// Insert adds a top level outline item in the outline,
// at the specified index.
func (o *Outline) Insert(index uint, item *OutlineItem) {
l := uint(len(o.items))
if index > l {
index = l
}
o.items = append(o.items[:index], append([]*OutlineItem{item}, o.items[index:]...)...)
}
// Items returns all children outline items.
func (o *Outline) Items() []*OutlineItem {
return o.items
}
// ToPdfOutline returns a low level PdfOutline object, based on the current
// instance.
func (o *Outline) ToPdfOutline() *PdfOutline {
// Create outline.
outline := NewPdfOutline()
// Create outline items.
var outlineItems []*PdfOutlineItem
var prev *PdfOutlineItem
for _, item := range o.items {
outlineItem, _ := item.ToPdfOutlineItem()
outlineItem.Parent = &outline.PdfOutlineTreeNode
if prev != nil {
prev.Next = &outlineItem.PdfOutlineTreeNode
outlineItem.Prev = &prev.PdfOutlineTreeNode
}
outlineItems = append(outlineItems, outlineItem)
prev = outlineItem
}
// Add outline linked list properties.
lenOutlineItems := int64(len(outlineItems))
if lenOutlineItems > 0 {
outline.First = &outlineItems[0].PdfOutlineTreeNode
outline.Last = &outlineItems[lenOutlineItems-1].PdfOutlineTreeNode
outline.Count = &lenOutlineItems
}
return outline
}
// ToPdfObject returns a PDF object representation of the outline.
func (o *Outline) ToPdfObject() core.PdfObject {
return o.ToPdfOutline().ToPdfObject()
}
// OutlineItem represents a PDF outline item dictionary (Table 153 - pp. 376 - 377).
type OutlineItem struct {
Title string
Dest OutlineDest
items []*OutlineItem
}
// NewOutlineItem returns a new outline item instance.
func NewOutlineItem(title string, dest OutlineDest) *OutlineItem {
return &OutlineItem{
Title: title,
Dest: dest,
}
}
// Add appends an outline item as a child of the current outline item.
func (oi *OutlineItem) Add(item *OutlineItem) {
oi.items = append(oi.items, item)
}
// Insert adds an outline item as a child of the current outline item,
// at the specified index.
func (oi *OutlineItem) Insert(index uint, item *OutlineItem) {
l := uint(len(oi.items))
if index > l {
index = l
}
oi.items = append(oi.items[:index], append([]*OutlineItem{item}, oi.items[index:]...)...)
}
// Items returns all children outline items.
func (oi *OutlineItem) Items() []*OutlineItem {
return oi.items
}
// ToPdfOutlineItem returns a low level PdfOutlineItem object,
// based on the current instance.
func (oi *OutlineItem) ToPdfOutlineItem() (*PdfOutlineItem, int64) {
// Create outline item.
currItem := NewPdfOutlineItem()
currItem.Title = core.MakeString(oi.Title)
currItem.Dest = oi.Dest.ToPdfObject()
// Create outline items.
var outlineItems []*PdfOutlineItem
var lenDescendants int64
var prev *PdfOutlineItem
for _, item := range oi.items {
outlineItem, lenChildren := item.ToPdfOutlineItem()
outlineItem.Parent = &currItem.PdfOutlineTreeNode
if prev != nil {
prev.Next = &outlineItem.PdfOutlineTreeNode
outlineItem.Prev = &prev.PdfOutlineTreeNode
}
outlineItems = append(outlineItems, outlineItem)
lenDescendants += lenChildren
prev = outlineItem
}
// Add outline item linked list properties.
lenOutlineItems := len(outlineItems)
lenDescendants += int64(lenOutlineItems)
if lenOutlineItems > 0 {
currItem.First = &outlineItems[0].PdfOutlineTreeNode
currItem.Last = &outlineItems[lenOutlineItems-1].PdfOutlineTreeNode
currItem.Count = &lenDescendants
}
return currItem, lenDescendants
}
// ToPdfObject returns a PDF object representation of the outline item.
func (oi *OutlineItem) ToPdfObject() core.PdfObject {
outlineItem, _ := oi.ToPdfOutlineItem()
return outlineItem.ToPdfObject()
}