mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-26 13:48:55 +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")
|
||||
}
|
||||
|
||||
outline := PdfOutline{}
|
||||
outline.primitive = container
|
||||
outline.context = &outline
|
||||
outline := NewPdfOutline()
|
||||
|
||||
if obj := dict.Get("Type"); obj != nil {
|
||||
typeVal, ok := obj.(*core.PdfObjectName)
|
||||
@ -120,7 +118,7 @@ func newPdfOutlineFromIndirectObject(container *core.PdfIndirectObject) (*PdfOut
|
||||
outline.Count = &count
|
||||
}
|
||||
|
||||
return &outline, nil
|
||||
return outline, nil
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
item := PdfOutlineItem{}
|
||||
item.primitive = container
|
||||
item.context = &item
|
||||
item := NewPdfOutlineItem()
|
||||
|
||||
// Title (required).
|
||||
obj := dict.Get("Title")
|
||||
@ -186,7 +182,7 @@ func (r *PdfReader) newPdfOutlineItemFromIndirectObject(container *core.PdfIndir
|
||||
item.F = core.ResolveReference(obj)
|
||||
}
|
||||
|
||||
return &item, nil
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
first, last, err := r.buildOutlineTree(firstObj, &outlineItem.PdfOutlineTreeNode, 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 {
|
||||
next, last, err := r.buildOutlineTree(nextObj, parent, &outlineItem.PdfOutlineTreeNode)
|
||||
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 {
|
||||
first, last, err := r.buildOutlineTree(firstObj, &outline.PdfOutlineTreeNode, 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
|
||||
}
|
||||
|
||||
// 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
|
||||
// object type to number of instances of each.
|
||||
func (r *PdfReader) Inspect() (map[string]int, error) {
|
||||
|
@ -409,6 +409,19 @@ func (w *PdfWriter) SetOCProperties(ocProperties core.PdfObject) error {
|
||||
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.
|
||||
func (w *PdfWriter) SetOptimizer(optimizer Optimizer) {
|
||||
w.optimizer = optimizer
|
||||
|
Loading…
x
Reference in New Issue
Block a user