summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Montag <pmontag@iseeme.com>2018-12-14 11:34:00 -0600
committerPaul Montag <pmontag@iseeme.com>2018-12-17 08:32:16 -0600
commitc27eea9fd19b65f75c4326c12446e829b39ab66d (patch)
treeb29dd73fd266a9199fb4107ee78bde91340f8353
parenta8d8f9e6a80f014f8f5a2388fbf7f409fe9cf263 (diff)
Refactored Encode and Decode functions, Fixed Template ID Conflicts
- Updated Encode and Decode to ensure templates and images are pointers to the original objects - Refactored so encoding no longer has to create p and o labels for images - removed id from template and generate it using Bytes instead.
-rw-r--r--def.go4
-rw-r--r--fpdf.go10
-rw-r--r--template.go35
-rw-r--r--template_impl.go120
4 files changed, 67 insertions, 102 deletions
diff --git a/def.go b/def.go
index b1dbc8c..3c4d902 100644
--- a/def.go
+++ b/def.go
@@ -486,8 +486,8 @@ type Fpdf struct {
page int // current page number
n int // current object number
offsets []int // array of object offsets
- templates map[int64]Template // templates used in this document
- templateObjects map[int64]int // template object IDs within this document
+ templates map[string]Template // templates used in this document
+ templateObjects map[string]int // template object IDs within this document
buffer fmtBuffer // buffer holding in-memory PDF
pages []*bytes.Buffer // slice[page] of page content; 1-based
state int // current document state
diff --git a/fpdf.go b/fpdf.go
index 99c087e..46fe007 100644
--- a/fpdf.go
+++ b/fpdf.go
@@ -83,8 +83,8 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType)
f.fonts = make(map[string]fontDefType)
f.fontFiles = make(map[string]fontFileType)
f.diffs = make([]string, 0, 8)
- f.templates = make(map[int64]Template)
- f.templateObjects = make(map[int64]int)
+ f.templates = make(map[string]Template)
+ f.templateObjects = make(map[string]int)
f.images = make(map[string]*ImageInfoType)
f.pageLinks = make([][]linkType, 0, 8)
f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) // pageLinks[0] is unused (1-based)
@@ -3559,8 +3559,8 @@ func (f *Fpdf) putxobjectdict() {
}
}
{
- var keyList []int64
- var key int64
+ var keyList []string
+ var key string
var tpl Template
keyList = templateKeyList(f.templates, f.catalogSort)
for _, key = range keyList {
@@ -3568,7 +3568,7 @@ func (f *Fpdf) putxobjectdict() {
// for _, tpl := range f.templates {
id := tpl.ID()
if objID, ok := f.templateObjects[id]; ok {
- f.outf("/TPL%d %d 0 R", id, objID)
+ f.outf("/TPL%s %d 0 R", id, objID)
}
}
}
diff --git a/template.go b/template.go
index 1bcd25d..fc6e29c 100644
--- a/template.go
+++ b/template.go
@@ -85,7 +85,7 @@ func (f *Fpdf) UseTemplateScaled(t Template, corner PointType, size SizeType) {
f.templates[tt.ID()] = tt
}
for name, ti := range t.Images() {
- name = sprintf("t%d-%s", t.ID(), name)
+ name = sprintf("t%s-%s", t.ID(), name)
f.images[name] = ti
}
@@ -97,29 +97,12 @@ func (f *Fpdf) UseTemplateScaled(t Template, corner PointType, size SizeType) {
ty := (f.curPageSize.Ht - corner.Y - size.Ht) * f.k
f.outf("q %.4f 0 0 %.4f %.4f %.4f cm", scaleX, scaleY, tx, ty) // Translate
- f.outf("/TPL%d Do Q", t.ID())
-}
-
-var nextTemplateIDChannel = func() chan int64 {
- ch := make(chan int64)
- go func() {
- var nextID int64 = 1
- for {
- ch <- nextID
- nextID++
- }
- }()
- return ch
-}()
-
-// GenerateTemplateID gives the next template ID. These numbers are global so that they can never clash.
-func GenerateTemplateID() int64 {
- return <-nextTemplateIDChannel
+ f.outf("/TPL%s Do Q", t.ID())
}
// Template is an object that can be written to, then used and re-used any number of times within a document.
type Template interface {
- ID() int64
+ ID() string
Size() (PointType, SizeType)
Bytes() []byte
Images() map[string]*ImageInfoType
@@ -201,7 +184,7 @@ func (f *Fpdf) putTemplates() {
for _, tt := range tTemplates {
id := tt.ID()
if objID, ok := f.templateObjects[id]; ok {
- f.outf("/TPL%d %d 0 R", id, objID)
+ f.outf("/TPL%s %d 0 R", id, objID)
}
}
f.out(">>")
@@ -221,8 +204,8 @@ func (f *Fpdf) putTemplates() {
}
}
-func templateKeyList(mp map[int64]Template, sort bool) (keyList []int64) {
- var key int64
+func templateKeyList(mp map[string]Template, sort bool) (keyList []string) {
+ var key string
for key = range mp {
keyList = append(keyList, key)
}
@@ -239,12 +222,12 @@ func templateKeyList(mp map[int64]Template, sort bool) (keyList []int64) {
}
// sortTemplates puts templates in a suitable order based on dependices
-func sortTemplates(templates map[int64]Template, catalogSort bool) []Template {
+func sortTemplates(templates map[string]Template, catalogSort bool) []Template {
chain := make([]Template, 0, len(templates)*2)
// build a full set of dependency chains
- var keyList []int64
- var key int64
+ var keyList []string
+ var key string
var t Template
keyList = templateKeyList(templates, catalogSort)
for _, key = range keyList {
diff --git a/template_impl.go b/template_impl.go
index f7eeee1..c5d7be8 100644
--- a/template_impl.go
+++ b/template_impl.go
@@ -2,6 +2,7 @@ package gofpdf
import (
"bytes"
+ "crypto/sha1"
"encoding/gob"
"errors"
"fmt"
@@ -48,14 +49,12 @@ func newTpl(corner PointType, size SizeType, orientationStr, unitStr, fontDirStr
}
images := tpl.Fpdf.images
- id := GenerateTemplateID()
- template := FpdfTpl{id, corner, size, bytes, images, templates, tpl.Fpdf.page}
+ template := FpdfTpl{corner, size, bytes, images, templates, tpl.Fpdf.page}
return &template
}
// FpdfTpl is a concrete implementation of the Template interface.
type FpdfTpl struct {
- id int64
corner PointType
size SizeType
bytes [][]byte
@@ -65,8 +64,8 @@ type FpdfTpl struct {
}
// ID returns the global template identifier
-func (t *FpdfTpl) ID() int64 {
- return t.id
+func (t *FpdfTpl) ID() string {
+ return fmt.Sprintf("%x", sha1.Sum(t.Bytes()))
}
// Size gives the bounding dimensions of this template
@@ -96,7 +95,6 @@ func (t *FpdfTpl) FromPage(page int) (Template, error) {
}
t2 := *t
- t2.id = GenerateTemplateID()
t2.page = page
return &t2, nil
}
@@ -158,7 +156,7 @@ func (t *FpdfTpl) childrenImages() map[string]*ImageInfoType {
for x := 0; x < len(t.templates); x++ {
imgs := t.templates[x].Images()
for key, val := range imgs {
- name := sprintf("t%d-%s", t.templates[x].ID(), key)
+ name := sprintf("t%s-%s", t.templates[x].ID(), key)
childrenImgs[name] = val
}
}
@@ -166,39 +164,51 @@ func (t *FpdfTpl) childrenImages() map[string]*ImageInfoType {
return childrenImgs
}
+// childrensTemplates returns the next layer of children templates, it doesn't dig into
+// children of children.
+func (t *FpdfTpl) childrensTemplates() []Template {
+ childrenTmpls := make([]Template, 0)
+
+ for x := 0; x < len(t.templates); x++ {
+ tmpls := t.templates[x].Templates()
+ childrenTmpls = append(childrenTmpls, tmpls...)
+ }
+
+ return childrenTmpls
+}
+
// GobEncode encodes the receiving template into a byte buffer. Use GobDecode
// to decode the byte buffer back to a template.
func (t *FpdfTpl) GobEncode() ([]byte, error) {
w := new(bytes.Buffer)
encoder := gob.NewEncoder(w)
- err := encoder.Encode(t.templates)
- childrenImgs := t.childrenImages()
+ childrensTemplates := t.childrensTemplates()
+ firstClassTemplates := make([]Template, 0)
- if err == nil {
- encoder.Encode(len(t.images))
- }
+found_continue:
+ for x := 0; x < len(t.templates); x++ {
+ for y := 0; y < len(childrensTemplates); y++ {
+ if childrensTemplates[y].ID() == t.templates[x].ID() {
+ continue found_continue
+ }
+ }
- for key, img := range t.images {
- // if the image has already been saved as a child, then
- // save nil so we don't duplicate data
- err = encoder.Encode(key)
+ firstClassTemplates = append(firstClassTemplates, t.templates[x])
+ }
+ err := encoder.Encode(firstClassTemplates)
- if err != nil {
- break
- }
+ childrenImgs := t.childrenImages()
+ firstClassImgs := make(map[string]*ImageInfoType)
- if _, ok := childrenImgs[key]; ok {
- err = encoder.Encode("p")
- } else {
- err = encoder.Encode("o")
- if err == nil {
- err = encoder.Encode(img)
- }
+ for key, img := range t.images {
+ if _, ok := childrenImgs[key]; !ok {
+ firstClassImgs[key] = img
}
}
+
if err == nil {
- err = encoder.Encode(t.id)
+ err = encoder.Encode(firstClassImgs)
}
if err == nil {
err = encoder.Encode(t.corner)
@@ -221,55 +231,27 @@ func (t *FpdfTpl) GobDecode(buf []byte) error {
r := bytes.NewBuffer(buf)
decoder := gob.NewDecoder(r)
- templates := make([]*FpdfTpl, 0)
- err := decoder.Decode(&templates)
- t.templates = make([]Template, len(templates))
-
- for x := 0; x < len(templates); x++ {
- t.templates[x] = templates[x]
- }
+ firstClassTemplates := make([]*FpdfTpl, 0)
+ err := decoder.Decode(&firstClassTemplates)
+ t.templates = make([]Template, len(firstClassTemplates))
- var numImgs int
- if err == nil {
- err = decoder.Decode(&numImgs)
+ for x := 0; x < len(t.templates); x++ {
+ t.templates[x] = Template(firstClassTemplates[x])
}
- t.images = make(map[string]*ImageInfoType)
- childrenImgs := t.childrenImages()
-
- for x := 0; x < numImgs; x++ {
- var key string
- var tpe string
-
- if err == nil {
- err = decoder.Decode(&key)
- }
+ firstClassImages := t.childrenImages()
- if err == nil {
- err = decoder.Decode(&tpe)
- }
+ t.templates = append(t.childrensTemplates(), t.templates...)
- if err == nil {
- switch tpe {
- case "p":
- if _, ok := childrenImgs[key]; !ok {
- err = fmt.Errorf("Encoded template is corrupt, could not find image %s", key)
- } else {
- t.images[key] = childrenImgs[key]
- }
- case "o":
- var img *ImageInfoType
- err = decoder.Decode(&img)
-
- if err == nil {
- t.images[key] = img
- }
- }
- }
- }
+ t.images = make(map[string]*ImageInfoType)
if err == nil {
- err = decoder.Decode(&t.id)
+ err = decoder.Decode(&t.images)
+ }
+
+ for k, v := range firstClassImages {
+ t.images[k] = v
}
+
if err == nil {
err = decoder.Decode(&t.corner)
}