From 80c5811b6b15479b473e814cad0aae7de9920bb3 Mon Sep 17 00:00:00 2001 From: David Fish Date: Mon, 8 Jan 2018 11:19:41 -0800 Subject: Added generic alias-replacement function to enable Table of Contents functionality --- def.go | 6 +++++- fpdf.go | 32 +++++++++++++++++++++++--------- fpdf_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/def.go b/def.go index 52e6474..936ca09 100644 --- a/def.go +++ b/def.go @@ -40,7 +40,10 @@ type gradientType struct { } const ( - OrientationPortrait = "portrait" + // OrientationPortrait represents the portrait orientation. + OrientationPortrait = "portrait" + + // OrientationLandscape represents the landscape orientation. OrientationLandscape = "landscape" ) @@ -243,6 +246,7 @@ type Fpdf struct { fontSize float64 // current font size in user unit ws float64 // word spacing images map[string]*ImageInfoType // array of used images + aliasMap map[string]string // map of alias->replacement pageLinks [][]linkType // pageLinks[page][link], both 1-based links []intLinkType // array of internal links outlines []outlineType // array of outlines diff --git a/fpdf.go b/fpdf.go index 567311d..ad29d18 100644 --- a/fpdf.go +++ b/fpdf.go @@ -88,6 +88,7 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) // pageLinks[0] is unused (1-based) f.links = make([]intLinkType, 0, 8) f.links = append(f.links, intLinkType{}) // links[0] is unused (1-based) + f.aliasMap = make(map[string]string) f.inHeader = false f.inFooter = false f.lasth = 0 @@ -3071,6 +3072,26 @@ func (f *Fpdf) SetJavascript(script string) { f.javascript = &script } +// RegisterAlias adds an (alias, replacement) pair to the document so we can +// replace all occurrences of that alias after writing but before the +// document is closed. +func (f *Fpdf) RegisterAlias(alias, replacement string) { + f.aliasMap[alias] = replacement +} + +func (f *Fpdf) replaceAliases() { + for alias, replacement := range f.aliasMap { + for n := 1; n <= f.page; n++ { + s := f.pages[n].String() + if strings.Contains(s, alias) { + s = strings.Replace(s, alias, replacement, -1) + f.pages[n].Truncate(0) + f.pages[n].WriteString(s) + } + } + } +} + func (f *Fpdf) putpages() { var wPt, hPt float64 var pageSize SizeType @@ -3079,16 +3100,9 @@ func (f *Fpdf) putpages() { nb := f.page if len(f.aliasNbPagesStr) > 0 { // Replace number of pages - nbStr := sprintf("%d", nb) - for n := 1; n <= nb; n++ { - s := f.pages[n].String() - if strings.Contains(s, f.aliasNbPagesStr) { - s = strings.Replace(s, f.aliasNbPagesStr, nbStr, -1) - f.pages[n].Truncate(0) - f.pages[n].WriteString(s) - } - } + f.RegisterAlias(f.aliasNbPagesStr, sprintf("%d", nb)) } + f.replaceAliases() if f.defOrientation == "P" { wPt = f.defPageSize.Wd * f.k hPt = f.defPageSize.Ht * f.k diff --git a/fpdf_test.go b/fpdf_test.go index ff41fd2..c7d843a 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2060,3 +2060,34 @@ func ExampleFpdf_AddSpotColor() { // Output: // Successfully generated pdf/Fpdf_AddSpotColor.pdf } + +// This example demonstrates how to use `RegisterAlias` to create a table of +// contents. +func ExampleFpdf_TableOfContents() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetFont("Arial", "", 12) + pdf.AddPage() + + // Write the table of contents. We use aliases instead of the page number + // because we don't know which page the section will begin on. + numSections := 3 + for i := 1; i <= numSections; i++ { + pdf.Cell(0, 10, fmt.Sprintf("Section %d begins on page {%d}", i, i)) + pdf.Ln(10) + } + + // Write the sections. Before we start writing, we use `RegisterAlias` to + // ensure that the alias written in the table of contents will be replaced + // by the current page number. + for i := 1; i <= numSections; i++ { + pdf.AddPage() + pdf.RegisterAlias(fmt.Sprintf("{%d}", i), fmt.Sprintf("%d", pdf.PageNo())) + pdf.Write(10, fmt.Sprintf("Section %d", i)) + } + + fileStr := example.Filename("Fpdf_TableOfContents") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_TableOfContents.pdf +} -- cgit v1.2.1-24-ge1ad