mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-02 22:17:06 +08:00
Skip invalid outline nodes (#101)
* Skip invalid outline nodes when building outline tree * Add methods for accessing and writing named destinations
This commit is contained in:
parent
f5989ea574
commit
13e08e064c
@ -95,9 +95,7 @@ func newPdfOutlineFromIndirectObject(container *core.PdfIndirectObject) (*PdfOut
|
|||||||
return nil, fmt.Errorf("outline object not a dictionary")
|
return nil, fmt.Errorf("outline object not a dictionary")
|
||||||
}
|
}
|
||||||
|
|
||||||
outline := PdfOutline{}
|
outline := NewPdfOutline()
|
||||||
outline.primitive = container
|
|
||||||
outline.context = &outline
|
|
||||||
|
|
||||||
if obj := dict.Get("Type"); obj != nil {
|
if obj := dict.Get("Type"); obj != nil {
|
||||||
typeVal, ok := obj.(*core.PdfObjectName)
|
typeVal, ok := obj.(*core.PdfObjectName)
|
||||||
@ -120,7 +118,7 @@ func newPdfOutlineFromIndirectObject(container *core.PdfIndirectObject) (*PdfOut
|
|||||||
outline.Count = &count
|
outline.Count = &count
|
||||||
}
|
}
|
||||||
|
|
||||||
return &outline, nil
|
return outline, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does not traverse the tree.
|
// Does not traverse the tree.
|
||||||
@ -130,9 +128,7 @@ func (r *PdfReader) newPdfOutlineItemFromIndirectObject(container *core.PdfIndir
|
|||||||
return nil, fmt.Errorf("outline object not a dictionary")
|
return nil, fmt.Errorf("outline object not a dictionary")
|
||||||
}
|
}
|
||||||
|
|
||||||
item := PdfOutlineItem{}
|
item := NewPdfOutlineItem()
|
||||||
item.primitive = container
|
|
||||||
item.context = &item
|
|
||||||
|
|
||||||
// Title (required).
|
// Title (required).
|
||||||
obj := dict.Get("Title")
|
obj := dict.Get("Title")
|
||||||
@ -186,7 +182,7 @@ func (r *PdfReader) newPdfOutlineItemFromIndirectObject(container *core.PdfIndir
|
|||||||
item.F = core.ResolveReference(obj)
|
item.F = core.ResolveReference(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the outer object of the tree node (Outline or OutlineItem).
|
// Get the outer object of the tree node (Outline or OutlineItem).
|
||||||
|
@ -338,10 +338,11 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
|
|||||||
if !core.IsNullObject(firstObj) {
|
if !core.IsNullObject(firstObj) {
|
||||||
first, last, err := r.buildOutlineTree(firstObj, &outlineItem.PdfOutlineTreeNode, nil)
|
first, last, err := r.buildOutlineTree(firstObj, &outlineItem.PdfOutlineTreeNode, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
common.Log.Debug("DEBUG: could not build outline item tree: %v. Skipping node children.", err)
|
||||||
|
} else {
|
||||||
|
outlineItem.First = first
|
||||||
|
outlineItem.Last = last
|
||||||
}
|
}
|
||||||
outlineItem.First = first
|
|
||||||
outlineItem.Last = last
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,10 +352,11 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
|
|||||||
if _, isNull := nextObj.(*core.PdfObjectNull); !isNull {
|
if _, isNull := nextObj.(*core.PdfObjectNull); !isNull {
|
||||||
next, last, err := r.buildOutlineTree(nextObj, parent, &outlineItem.PdfOutlineTreeNode)
|
next, last, err := r.buildOutlineTree(nextObj, parent, &outlineItem.PdfOutlineTreeNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
common.Log.Debug("DEBUG: could not build outline tree for Next node: %v. Skipping node.", err)
|
||||||
|
} else {
|
||||||
|
outlineItem.Next = next
|
||||||
|
return &outlineItem.PdfOutlineTreeNode, last, nil
|
||||||
}
|
}
|
||||||
outlineItem.Next = next
|
|
||||||
return &outlineItem.PdfOutlineTreeNode, last, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,10 +377,11 @@ func (r *PdfReader) buildOutlineTree(obj core.PdfObject, parent *PdfOutlineTreeN
|
|||||||
if _, isNull := firstObjDirect.(*core.PdfObjectNull); !isNull && firstObjDirect != nil {
|
if _, isNull := firstObjDirect.(*core.PdfObjectNull); !isNull && firstObjDirect != nil {
|
||||||
first, last, err := r.buildOutlineTree(firstObj, &outline.PdfOutlineTreeNode, nil)
|
first, last, err := r.buildOutlineTree(firstObj, &outline.PdfOutlineTreeNode, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
common.Log.Debug("DEBUG: could not build outline tree: %v. Skipping node children.", err)
|
||||||
|
} else {
|
||||||
|
outline.First = first
|
||||||
|
outline.Last = last
|
||||||
}
|
}
|
||||||
outline.First = first
|
|
||||||
outline.Last = last
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,6 +739,25 @@ func (r *PdfReader) GetOCProperties() (core.PdfObject, error) {
|
|||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNamedDestinations returns the Names entry in the PDF catalog.
|
||||||
|
// See section 12.3.2.3 "Named Destinations" (p. 367 PDF32000_2008).
|
||||||
|
func (r *PdfReader) GetNamedDestinations() (core.PdfObject, error) {
|
||||||
|
obj := core.ResolveReference(r.catalog.Get("Names"))
|
||||||
|
if obj == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve references.
|
||||||
|
if !r.isLazy {
|
||||||
|
err := r.traverseObjectData(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Inspect inspects the object types, subtypes and content in the PDF file returning a map of
|
// Inspect inspects the object types, subtypes and content in the PDF file returning a map of
|
||||||
// object type to number of instances of each.
|
// object type to number of instances of each.
|
||||||
func (r *PdfReader) Inspect() (map[string]int, error) {
|
func (r *PdfReader) Inspect() (map[string]int, error) {
|
||||||
|
@ -409,6 +409,19 @@ func (w *PdfWriter) SetOCProperties(ocProperties core.PdfObject) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNamedDestinations sets the Names entry in the PDF catalog.
|
||||||
|
// See section 12.3.2.3 "Named Destinations" (p. 367 PDF32000_2008).
|
||||||
|
func (w *PdfWriter) SetNamedDestinations(names core.PdfObject) error {
|
||||||
|
if names == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
common.Log.Trace("Setting catalog Names...")
|
||||||
|
w.catalog.Set("Names", names)
|
||||||
|
w.addObjects(names)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetOptimizer sets the optimizer to optimize PDF before writing.
|
// SetOptimizer sets the optimizer to optimize PDF before writing.
|
||||||
func (w *PdfWriter) SetOptimizer(optimizer Optimizer) {
|
func (w *PdfWriter) SetOptimizer(optimizer Optimizer) {
|
||||||
w.optimizer = optimizer
|
w.optimizer = optimizer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user