From edc850a162624adf8be75963942d1b00be79aecf Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Wed, 16 Jan 2019 21:49:41 +0200 Subject: [PATCH 1/7] Set context for PDF outline and outline items --- pdf/model/outlines.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pdf/model/outlines.go b/pdf/model/outlines.go index e1fa17c7..91051362 100644 --- a/pdf/model/outlines.go +++ b/pdf/model/outlines.go @@ -46,13 +46,13 @@ type PdfOutlineItem struct { // NewPdfOutline returns an initialized PdfOutline. func NewPdfOutline() *PdfOutline { - outline := &PdfOutline{} - - container := &PdfIndirectObject{} - container.PdfObject = MakeDict() - - outline.primitive = container + outline := &PdfOutline{ + primitive: &PdfIndirectObject{ + PdfObject: MakeDict(), + }, + } + outline.context = outline return outline } @@ -65,12 +65,13 @@ func NewPdfOutlineTree() *PdfOutline { // NewPdfOutlineItem returns an initialized PdfOutlineItem. func NewPdfOutlineItem() *PdfOutlineItem { - outlineItem := &PdfOutlineItem{} + outlineItem := &PdfOutlineItem{ + primitive: &PdfIndirectObject{ + PdfObject: MakeDict(), + }, + } - container := &PdfIndirectObject{} - container.PdfObject = MakeDict() - - outlineItem.primitive = container + outlineItem.context = outlineItem return outlineItem } @@ -253,6 +254,10 @@ func (o *PdfOutline) ToPdfObject() PdfObject { dict.Set("Parent", o.Parent.getOuter().GetContainingPdfObject()) } + if o.Count != nil { + dict.Set("Count", MakeInteger(*o.Count)) + } + return container } From f5046b885a8cd1178a01f797550282b62f2aabd8 Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Wed, 16 Jan 2019 21:50:00 +0200 Subject: [PATCH 2/7] Add higher level outlines interface --- pdf/model/outline.go | 156 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 pdf/model/outline.go diff --git a/pdf/model/outline.go b/pdf/model/outline.go new file mode 100644 index 00000000..ac19a5dd --- /dev/null +++ b/pdf/model/outline.go @@ -0,0 +1,156 @@ +/* + * 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/unidoc/pdf/core" + +/* +OutlineDest +*/ +type OutlineDest struct { + Page int64 + X float64 + Y float64 +} + +func NewOutlineDest(page int64, x, y float64) OutlineDest { + return OutlineDest{ + Page: page, + X: x, + Y: y, + } +} + +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 +*/ +type Outline struct { + items []*OutlineItem +} + +func NewOutline() *Outline { + return &Outline{} +} + +func (o *Outline) Add(item *OutlineItem) { + o.items = append(o.items, item) +} + +func (o *Outline) Items() []*OutlineItem { + return o.items +} + +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 +} + +func (o *Outline) ToPdfObject() core.PdfObject { + return o.ToPdfOutline().ToPdfObject() +} + +/* +OutlineItem +*/ +type OutlineItem struct { + Title string + Dest OutlineDest + + items []*OutlineItem +} + +func NewOutlineItem(title string, dest OutlineDest) *OutlineItem { + return &OutlineItem{ + Title: title, + Dest: dest, + } +} + +func (oi *OutlineItem) Add(item *OutlineItem) { + oi.items = append(oi.items, item) +} + +func (oi *OutlineItem) Items() []*OutlineItem { + return oi.items +} + +func (oi *OutlineItem) ToPdfOutlineItem() (*PdfOutlineItem, int64) { + // Create outline item. + currItem := NewPdfOutlineItem() + currItem.Title = core.MakeString(oi.Title) + 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) + if lenOutlineItems > 0 { + currItem.First = &outlineItems[0].PdfOutlineTreeNode + currItem.Last = &outlineItems[lenOutlineItems-1].PdfOutlineTreeNode + currItem.Count = &lenDescendants + } + + return currItem, lenDescendants +} + +func (oi *OutlineItem) ToPdfObject() core.PdfObject { + outlineItem, _ := oi.ToPdfOutlineItem() + return outlineItem.ToPdfObject() +} From 2d78c8bf5f27959565026390f0c3cd30f6ffbe18 Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Wed, 16 Jan 2019 21:50:10 +0200 Subject: [PATCH 3/7] Create outlines automatically for chapters and subchapters --- pdf/creator/chapters.go | 56 ++++++++++++++++++++++------- pdf/creator/creator.go | 48 ++++++++++++++++++++++--- pdf/creator/subchapter.go | 74 ++++++++++++++++++++++++++++----------- 3 files changed, 140 insertions(+), 38 deletions(-) diff --git a/pdf/creator/chapters.go b/pdf/creator/chapters.go index afe3e8f7..bff39f00 100644 --- a/pdf/creator/chapters.go +++ b/pdf/creator/chapters.go @@ -11,6 +11,7 @@ import ( "strconv" "github.com/unidoc/unidoc/common" + "github.com/unidoc/unidoc/pdf/model" ) // Chapter is used to arrange multiple drawables (paragraphs, images, etc) into a single section. @@ -39,12 +40,18 @@ type Chapter struct { // Margins to be applied around the block when drawing on Page. margins margins - // Reference to the creator's TOC. + // Reference to the TOC of the creator. toc *TOC + + // Reference to the outline of the creator. + outline *model.Outline + + // The item of the chapter in the outline. + outlineItem *model.OutlineItem } // newChapter creates a new chapter with the specified title as the heading. -func newChapter(toc *TOC, title string, number int, style TextStyle) *Chapter { +func newChapter(toc *TOC, outline *model.Outline, title string, number int, style TextStyle) *Chapter { p := newParagraph(fmt.Sprintf("%d. %s", number, title), style) p.SetFont(style.Font) p.SetFontSize(16) @@ -55,6 +62,7 @@ func newChapter(toc *TOC, title string, number int, style TextStyle) *Chapter { showNumbering: true, includeInTOC: true, toc: toc, + outline: outline, heading: p, contents: []Drawable{}, } @@ -141,21 +149,43 @@ func (chap *Chapter) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawContext, ctx.Page++ // Did not fit, moved to new Page block. } - if chap.includeInTOC { - // Add to TOC. - chapNumber := "" - if chap.showNumbering { - if chap.number != 0 { - chapNumber = strconv.Itoa(chap.number) + "." - } - } + // Generate chapter title and number. + chapTitle := chap.title + var chapNumber string + page := int64(ctx.Page) - line := chap.toc.Add(chapNumber, chap.title, strconv.Itoa(ctx.Page), 1) - if chap.toc.showLinks { - line.SetLink(int64(ctx.Page), origX, origY) + if chap.showNumbering { + if chap.number != 0 { + chapNumber = strconv.Itoa(chap.number) + "." } } + if chapNumber != "" { + chapTitle = fmt.Sprintf("%s %s", chapNumber, chapTitle) + } + + // Add to TOC. + if chap.includeInTOC { + line := chap.toc.Add(chapNumber, chap.title, strconv.FormatInt(page, 10), 1) + if chap.toc.showLinks { + line.SetLink(page, origX, origY) + } + } + + // Add to outline. + if chap.outlineItem == nil { + chap.outlineItem = model.NewOutlineItem( + chapTitle, + model.NewOutlineDest(page-1, origX, origY), + ) + chap.outline.Add(chap.outlineItem) + } else { + outlineDest := &chap.outlineItem.Dest + outlineDest.Page = page - 1 + outlineDest.X = origX + outlineDest.Y = origY + } + for _, d := range chap.contents { newBlocks, c, err := d.GeneratePageBlocks(ctx) if err != nil { diff --git a/pdf/creator/creator.go b/pdf/creator/creator.go index 118e4a21..ff6ced9d 100644 --- a/pdf/creator/creator.go +++ b/pdf/creator/creator.go @@ -43,11 +43,17 @@ type Creator struct { finalized bool + // Controls whether a table of contents will be generated. + AddTOC bool + // The table of contents. toc *TOC - // Controls whether a table of contents will be added. - AddTOC bool + // Controls whether outlines will be generated. + AddOutlines bool + + // Outline. + outline *model.Outline // Forms. acroForm *model.PdfAcroForm @@ -125,6 +131,10 @@ func New() *Creator { // Initialize creator table of contents. c.toc = c.NewTOC("Table of Contents") + // Initialize outline. + c.AddOutlines = true + c.outline = model.NewOutline() + return c } @@ -420,6 +430,31 @@ func (c *Creator) finalize() error { } } + // Account for the front page and the table of content pages. + if c.AddOutlines { + var adjustOutlineDest func(item *model.OutlineItem) + adjustOutlineDest = func(item *model.OutlineItem) { + item.Dest.Page += int64(genpages) + + // Reverse the Y axis of the destination coordinates. + // The user passes in the annotation coordinates as if + // position 0, 0 is at the top left of the page. + // However, position 0, 0 in the PDF is at the bottom + // left of the page. + item.Dest.Y = c.pageHeight - item.Dest.Y + + outlineItems := item.Items() + for _, outlineItem := range outlineItems { + adjustOutlineDest(outlineItem) + } + } + + outlineItems := c.outline.Items() + for _, outlineItem := range outlineItems { + adjustOutlineDest(outlineItem) + } + } + for idx, page := range c.pages { c.setActivePage(page) if c.drawHeaderFunc != nil { @@ -540,7 +575,12 @@ func (c *Creator) Write(ws io.Writer) error { } } - // Pdf Writer access hook. Can be used to encrypt, etc. via the PdfWriter instance. + // Outlines. + if c.outline != nil && c.AddOutlines { + pdfWriter.AddOutlineTree(&c.outline.ToPdfOutline().PdfOutlineTreeNode) + } + + // Pdf Writer access hook. Can be used to encrypt, etc. via the PdfWriter instance. if c.pdfWriterAccessFunc != nil { err := c.pdfWriterAccessFunc(&pdfWriter) if err != nil { @@ -661,7 +701,7 @@ func (c *Creator) NewStyledTOCLine(number, title, page TextChunk, level uint, st // NewChapter creates a new chapter with the specified title as the heading. func (c *Creator) NewChapter(title string) *Chapter { c.chapters++ - return newChapter(c.toc, title, c.chapters, c.NewTextStyle()) + return newChapter(c.toc, c.outline, title, c.chapters, c.NewTextStyle()) } // NewSubchapter creates a new Subchapter under Chapter ch with specified title. diff --git a/pdf/creator/subchapter.go b/pdf/creator/subchapter.go index f0839888..aaadfa93 100644 --- a/pdf/creator/subchapter.go +++ b/pdf/creator/subchapter.go @@ -10,12 +10,12 @@ import ( "strconv" "github.com/unidoc/unidoc/common" + "github.com/unidoc/unidoc/pdf/model" ) // Subchapter simply represents a sub chapter pertaining to a specific Chapter. It can contain // multiple Drawables, just like a chapter. type Subchapter struct { - chapterNum int subchapterNum int title string heading *Paragraph @@ -39,6 +39,15 @@ type Subchapter struct { // Reference to the creator's TOC. toc *TOC + + // Reference to the chapter the subchapter belongs to. + chapter *Chapter + + // Reference to the outline of the creator. + outline *model.Outline + + // The item of the subchapter in the outline. + outlineItem *model.OutlineItem } // newSubchapter creates a new Subchapter under Chapter ch with specified title. @@ -52,13 +61,14 @@ func newSubchapter(ch *Chapter, title string, style TextStyle) *Subchapter { subchapter := &Subchapter{ subchapterNum: ch.subchapters, - chapterNum: ch.number, title: title, showNumbering: true, includeInTOC: true, heading: p, contents: []Drawable{}, + chapter: ch, toc: ch.toc, + outline: ch.outline, } // Add subchapter to chapter. @@ -70,7 +80,7 @@ func newSubchapter(ch *Chapter, title string, style TextStyle) *Subchapter { // SetShowNumbering sets a flag to indicate whether or not to show chapter numbers as part of title. func (subchap *Subchapter) SetShowNumbering(show bool) { if show { - heading := fmt.Sprintf("%d.%d. %s", subchap.chapterNum, subchap.subchapterNum, subchap.title) + heading := fmt.Sprintf("%d.%d. %s", subchap.chapter.number, subchap.subchapterNum, subchap.title) subchap.heading.SetText(heading) } else { heading := fmt.Sprintf("%s", subchap.title) @@ -148,29 +158,51 @@ func (subchap *Subchapter) GeneratePageBlocks(ctx DrawContext) ([]*Block, DrawCo if len(blocks) > 1 { ctx.Page++ // did not fit - moved to next Page. } + + // Generate subchapter title and number. + subchapTitle := subchap.title + var subchapNumber string + page := int64(ctx.Page) + + if subchap.showNumbering { + if subchap.chapter.number != 0 { + subchapNumber = strconv.Itoa(subchap.chapter.number) + } + if subchap.subchapterNum != 0 { + if subchapNumber != "" { + subchapNumber += "." + } + + subchapNumber += strconv.Itoa(subchap.subchapterNum) + "." + } + } + + if subchapNumber != "" { + subchapTitle = fmt.Sprintf("%s %s", subchapNumber, subchapTitle) + } + + // Add to TOC. if subchap.includeInTOC { - // Add to TOC. - subchapNumber := "" - - if subchap.showNumbering { - if subchap.chapterNum != 0 { - subchapNumber = strconv.Itoa(subchap.chapterNum) - } - if subchap.subchapterNum != 0 { - if subchapNumber != "" { - subchapNumber += "." - } - - subchapNumber += strconv.Itoa(subchap.subchapterNum) + "." - } - } - - line := subchap.toc.Add(subchapNumber, subchap.title, strconv.Itoa(ctx.Page), 2) + line := subchap.toc.Add(subchapNumber, subchap.title, strconv.FormatInt(page, 10), 2) if subchap.toc.showLinks { - line.SetLink(int64(ctx.Page), origX, origY) + line.SetLink(page, origX, origY) } } + // Add to outline. + if subchap.outlineItem == nil { + subchap.outlineItem = model.NewOutlineItem( + subchapTitle, + model.NewOutlineDest(page-1, origX, origY), + ) + subchap.chapter.outlineItem.Add(subchap.outlineItem) + } else { + outlineDest := &subchap.outlineItem.Dest + outlineDest.Page = page - 1 + outlineDest.X = origX + outlineDest.Y = origY + } + for _, d := range subchap.contents { newBlocks, c, err := d.GeneratePageBlocks(ctx) if err != nil { From a89213f7c005225076205e976d139bfa7b41f258 Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Wed, 16 Jan 2019 22:14:51 +0200 Subject: [PATCH 4/7] Add insert method for Outline and OutlineItem structs --- pdf/model/outline.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/pdf/model/outline.go b/pdf/model/outline.go index ac19a5dd..f62cf6b4 100644 --- a/pdf/model/outline.go +++ b/pdf/model/outline.go @@ -5,7 +5,9 @@ package model -import "github.com/unidoc/unidoc/pdf/core" +import ( + "github.com/unidoc/unidoc/pdf/core" +) /* OutlineDest @@ -49,6 +51,15 @@ func (o *Outline) Add(item *OutlineItem) { o.items = append(o.items, item) } +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:]...)...) +} + func (o *Outline) Items() []*OutlineItem { return o.items } @@ -110,6 +121,15 @@ func (oi *OutlineItem) Add(item *OutlineItem) { oi.items = append(oi.items, item) } +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:]...)...) +} + func (oi *OutlineItem) Items() []*OutlineItem { return oi.items } @@ -141,6 +161,8 @@ func (oi *OutlineItem) ToPdfOutlineItem() (*PdfOutlineItem, int64) { // 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 From a9747036a1c530ccf2a02fb33f3b81e4bafd788c Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Wed, 16 Jan 2019 22:15:57 +0200 Subject: [PATCH 5/7] Add TOC page outline item --- pdf/creator/creator.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pdf/creator/creator.go b/pdf/creator/creator.go index ff6ced9d..338c52cd 100644 --- a/pdf/creator/creator.go +++ b/pdf/creator/creator.go @@ -453,6 +453,19 @@ func (c *Creator) finalize() error { for _, outlineItem := range outlineItems { adjustOutlineDest(outlineItem) } + + // Add outline TOC item. + if c.AddTOC { + var tocPage int64 + if hasFrontPage { + tocPage = 1 + } + + c.outline.Insert(0, model.NewOutlineItem( + "Table of Contents", + model.NewOutlineDest(tocPage, 0, c.pageHeight), + )) + } } for idx, page := range c.pages { From cb7e52d695b2d973d56e7f65b6e0cf8a3bd29c5a Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Thu, 17 Jan 2019 19:05:31 +0200 Subject: [PATCH 6/7] Fix golint notices and document Outline, OutlineItem and OutlineDest --- pdf/creator/creator.go | 2 +- pdf/model/outline.go | 32 +++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pdf/creator/creator.go b/pdf/creator/creator.go index 338c52cd..6d0c55e5 100644 --- a/pdf/creator/creator.go +++ b/pdf/creator/creator.go @@ -431,7 +431,7 @@ func (c *Creator) finalize() error { } // Account for the front page and the table of content pages. - if c.AddOutlines { + if c.outline != nil && c.AddOutlines { var adjustOutlineDest func(item *model.OutlineItem) adjustOutlineDest = func(item *model.OutlineItem) { item.Dest.Page += int64(genpages) diff --git a/pdf/model/outline.go b/pdf/model/outline.go index f62cf6b4..cfd8871e 100644 --- a/pdf/model/outline.go +++ b/pdf/model/outline.go @@ -9,15 +9,16 @@ import ( "github.com/unidoc/unidoc/pdf/core" ) -/* -OutlineDest -*/ +// 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, @@ -26,6 +27,7 @@ func NewOutlineDest(page int64, x, y float64) OutlineDest { } } +// ToPdfObject returns a PDF object representation of the outline destination. func (od OutlineDest) ToPdfObject() core.PdfObject { return core.MakeArray( core.MakeInteger(od.Page), @@ -36,21 +38,23 @@ func (od OutlineDest) ToPdfObject() core.PdfObject { ) } -/* -Outline -*/ +// Outline represents a PDF outline dictionary (Table 152 - p. 376). 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 { @@ -60,10 +64,13 @@ func (o *Outline) Insert(index uint, item *OutlineItem) { 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() @@ -96,13 +103,12 @@ func (o *Outline) ToPdfOutline() *PdfOutline { return outline } +// ToPdfObject returns a PDF object representation of the outline. func (o *Outline) ToPdfObject() core.PdfObject { return o.ToPdfOutline().ToPdfObject() } -/* -OutlineItem -*/ +// OutlineItem represents a PDF outline item dictionary (Table 153 - pp. 376 - 377). type OutlineItem struct { Title string Dest OutlineDest @@ -110,6 +116,7 @@ type OutlineItem struct { items []*OutlineItem } +// NewOutlineItem returns a new outline item instance. func NewOutlineItem(title string, dest OutlineDest) *OutlineItem { return &OutlineItem{ Title: title, @@ -117,10 +124,13 @@ func NewOutlineItem(title string, dest OutlineDest) *OutlineItem { } } +// 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 { @@ -130,10 +140,13 @@ func (oi *OutlineItem) Insert(index uint, item *OutlineItem) { 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() @@ -172,6 +185,7 @@ func (oi *OutlineItem) ToPdfOutlineItem() (*PdfOutlineItem, int64) { 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() From f6ab87c50e1849560eba76393ab513c4b69736d0 Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Fri, 18 Jan 2019 15:48:54 +0200 Subject: [PATCH 7/7] Minor refactoring --- pdf/model/outline.go | 1 + pdf/model/outlines.go | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pdf/model/outline.go b/pdf/model/outline.go index cfd8871e..72186596 100644 --- a/pdf/model/outline.go +++ b/pdf/model/outline.go @@ -39,6 +39,7 @@ func (od OutlineDest) ToPdfObject() core.PdfObject { } // 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 } diff --git a/pdf/model/outlines.go b/pdf/model/outlines.go index 91051362..612a82bf 100644 --- a/pdf/model/outlines.go +++ b/pdf/model/outlines.go @@ -47,9 +47,7 @@ type PdfOutlineItem struct { // NewPdfOutline returns an initialized PdfOutline. func NewPdfOutline() *PdfOutline { outline := &PdfOutline{ - primitive: &PdfIndirectObject{ - PdfObject: MakeDict(), - }, + primitive: MakeIndirectObject(MakeDict()), } outline.context = outline @@ -66,9 +64,7 @@ func NewPdfOutlineTree() *PdfOutline { // NewPdfOutlineItem returns an initialized PdfOutlineItem. func NewPdfOutlineItem() *PdfOutlineItem { outlineItem := &PdfOutlineItem{ - primitive: &PdfIndirectObject{ - PdfObject: MakeDict(), - }, + primitive: MakeIndirectObject(MakeDict()), } outlineItem.context = outlineItem