mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-26 13:48:55 +08:00
194 lines
4.9 KiB
Go
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.MakeEncodedString(oi.Title, true)
|
|
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()
|
|
}
|