mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-26 13:48:55 +08:00
Add NewOutlineFromReaderOutline
This commit is contained in:
parent
8afe2c21ed
commit
9a553c30ba
@ -6,6 +6,9 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/unidoc/unipdf/v3/common"
|
||||||
"github.com/unidoc/unipdf/v3/core"
|
"github.com/unidoc/unipdf/v3/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,6 +30,53 @@ func NewOutlineDest(page int64, x, y float64) OutlineDest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newOutlineDestFromPdfObject creates a new outline destination from the
|
||||||
|
// specified PDF object.
|
||||||
|
func newOutlineDestFromPdfObject(o core.PdfObject, r *PdfReader) OutlineDest {
|
||||||
|
dest := OutlineDest{}
|
||||||
|
|
||||||
|
destArr, ok := core.GetArray(o)
|
||||||
|
if !ok {
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Covered destination formats:
|
||||||
|
// [pageObj|pageNum /Fit]
|
||||||
|
// [pageObj|pageNum /FitB]
|
||||||
|
// [pageObj|pageNum /FitH top]
|
||||||
|
// [pageObj|pageNum /FitV left]
|
||||||
|
// [pageObj|pageNum /FitBH top]
|
||||||
|
// [pageObj|pageNum /XYZ x y zoom]
|
||||||
|
// [pageObj|pageNum /FitR left bottom right top]
|
||||||
|
// See section 12.3.2.2 "Explicit Destinations" (page 374).
|
||||||
|
destArrLen := destArr.Len()
|
||||||
|
if destArrLen < 2 {
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract page number.
|
||||||
|
pageObj := destArr.Get(0)
|
||||||
|
if pageInd, ok := core.GetIndirect(pageObj); ok {
|
||||||
|
// Page object is provided. Identify page number using the reader.
|
||||||
|
if _, pageNum, err := r.PageFromIndirectObject(pageInd); err == nil {
|
||||||
|
dest.Page = int64(pageNum - 1)
|
||||||
|
}
|
||||||
|
} else if pageNum, ok := core.GetIntVal(pageObj); ok {
|
||||||
|
// Page number is provided.
|
||||||
|
dest.Page = int64(pageNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract destination coordinates.
|
||||||
|
if destArrLen == 5 {
|
||||||
|
if xyz, ok := core.GetName(destArr.Get(1)); ok && xyz.String() == "XYZ" {
|
||||||
|
dest.X, _ = core.GetFloatVal(destArr.Get(2))
|
||||||
|
dest.Y, _ = core.GetFloatVal(destArr.Get(3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
// ToPdfObject returns a PDF object representation of the outline destination.
|
// ToPdfObject returns a PDF object representation of the outline destination.
|
||||||
func (od OutlineDest) ToPdfObject() core.PdfObject {
|
func (od OutlineDest) ToPdfObject() core.PdfObject {
|
||||||
return core.MakeArray(
|
return core.MakeArray(
|
||||||
@ -49,7 +99,54 @@ func NewOutline() *Outline {
|
|||||||
return &Outline{}
|
return &Outline{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOutlineFromOutlineTree(node *PdfOutlineTreeNode) {
|
// NewOutlineFromReaderOutline returns a new outline from the outline tree of
|
||||||
|
// the passed in reader.
|
||||||
|
func NewOutlineFromReaderOutline(r *PdfReader) (*Outline, error) {
|
||||||
|
if r == nil {
|
||||||
|
return nil, errors.New("cannot create outline from nil reader")
|
||||||
|
}
|
||||||
|
|
||||||
|
outlineTree := r.GetOutlineTree()
|
||||||
|
if outlineTree == nil {
|
||||||
|
return nil, errors.New("the specified reader does not have an outline tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
var traverseFunc func(node *PdfOutlineTreeNode, entries *[]*OutlineItem)
|
||||||
|
traverseFunc = func(node *PdfOutlineTreeNode, entries *[]*OutlineItem) {
|
||||||
|
if node == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if node.context == nil {
|
||||||
|
common.Log.Debug("ERROR: missing outline entry context")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if node is an outline item.
|
||||||
|
var entry *OutlineItem
|
||||||
|
if item, ok := node.context.(*PdfOutlineItem); ok {
|
||||||
|
entry = NewOutlineItem(item.Title.Decoded(), newOutlineDestFromPdfObject(item.Dest, r))
|
||||||
|
*entries = append(*entries, entry)
|
||||||
|
|
||||||
|
// Traverse next node.
|
||||||
|
if item.Next != nil {
|
||||||
|
traverseFunc(item.Next, entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if node has children.
|
||||||
|
if node.First != nil {
|
||||||
|
if entry != nil {
|
||||||
|
entries = &entry.Entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverse node children.
|
||||||
|
traverseFunc(node.First, entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outline := NewOutline()
|
||||||
|
traverseFunc(outlineTree, &outline.Entries)
|
||||||
|
return outline, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add appends a top level outline item to the outline.
|
// Add appends a top level outline item to the outline.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user