diff --git a/model/outlines.go b/model/outlines.go index 15f2bce9..c8c12808 100644 --- a/model/outlines.go +++ b/model/outlines.go @@ -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). diff --git a/model/reader.go b/model/reader.go index 956fcb78..21463a3e 100644 --- a/model/reader.go +++ b/model/reader.go @@ -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) { diff --git a/model/writer.go b/model/writer.go index e32f0e97..9c76548b 100644 --- a/model/writer.go +++ b/model/writer.go @@ -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