diff options
| author | Kurt <kurt.w.jung@gmail.com> | 2018-11-10 11:03:29 -0500 | 
|---|---|---|
| committer | Kurt <kurt.w.jung@gmail.com> | 2018-11-10 11:03:29 -0500 | 
| commit | 8d469f984ef048ff3547911bede39b7b651e8c8c (patch) | |
| tree | cec153cf2688291b2ee3a694defaaf42449a1122 | |
| parent | e200d3e7c7ef20b29a47b67e58b7561f4099e7ae (diff) | |
| parent | 01381ea7603b12304064fcd01a49b1cc4434b4ca (diff) | |
Merge branch 'ftr/gob' of https://github.com/d1ngd0/gofpdf into d1ngd0-ftr/gob
| -rw-r--r-- | def.go | 96 | ||||
| -rw-r--r-- | fpdf_test.go | 10 | ||||
| -rw-r--r-- | template.go | 4 | ||||
| -rw-r--r-- | template_impl.go | 151 | 
4 files changed, 258 insertions, 3 deletions
| @@ -18,6 +18,7 @@ package gofpdf  import (  	"bytes" +	"encoding/gob"  	"io"  	"time"  ) @@ -175,6 +176,101 @@ type ImageInfoType struct {  	dpi   float64  } +func (info *ImageInfoType) GobEncode() ([]byte, error) { +	w := new(bytes.Buffer) +	encoder := gob.NewEncoder(w) + +	err := encoder.Encode(info.data) +	if err == nil { +		err = encoder.Encode(info.smask) +	} +	if err == nil { +		err = encoder.Encode(info.i) +	} +	if err == nil { +		err = encoder.Encode(info.n) +	} +	if err == nil { +		err = encoder.Encode(info.w) +	} +	if err == nil { +		err = encoder.Encode(info.h) +	} +	if err == nil { +		err = encoder.Encode(info.cs) +	} +	if err == nil { +		err = encoder.Encode(info.pal) +	} +	if err == nil { +		err = encoder.Encode(info.bpc) +	} +	if err == nil { +		err = encoder.Encode(info.f) +	} +	if err == nil { +		err = encoder.Encode(info.dp) +	} +	if err == nil { +		err = encoder.Encode(info.trns) +	} +	if err == nil { +		err = encoder.Encode(info.scale) +	} +	if err == nil { +		err = encoder.Encode(info.dpi) +	} + +	return w.Bytes(), err +} + +func (info *ImageInfoType) GobDecode(buf []byte) error { +	r := bytes.NewBuffer(buf) +	decoder := gob.NewDecoder(r) + +	err := decoder.Decode(&info.data) +	if err == nil { +		err = decoder.Decode(&info.smask) +	} +	if err == nil { +		err = decoder.Decode(&info.i) +	} +	if err == nil { +		err = decoder.Decode(&info.n) +	} +	if err == nil { +		err = decoder.Decode(&info.w) +	} +	if err == nil { +		err = decoder.Decode(&info.h) +	} +	if err == nil { +		err = decoder.Decode(&info.cs) +	} +	if err == nil { +		err = decoder.Decode(&info.pal) +	} +	if err == nil { +		err = decoder.Decode(&info.bpc) +	} +	if err == nil { +		err = decoder.Decode(&info.f) +	} +	if err == nil { +		err = decoder.Decode(&info.dp) +	} +	if err == nil { +		err = decoder.Decode(&info.trns) +	} +	if err == nil { +		err = decoder.Decode(&info.scale) +	} +	if err == nil { +		err = decoder.Decode(&info.dpi) +	} +	return err +} +  // PointConvert returns the value of pt, expressed in points (1/72 inch), as a  // value expressed in the unit of measure specified in New(). Since font  // management in Fpdf uses points, this method can help with line height diff --git a/fpdf_test.go b/fpdf_test.go index 4774ec6..19bc533 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -1950,10 +1950,14 @@ func ExampleFpdf_CreateTemplate() {  	pdf.SetLineWidth(2.5)  	pdf.SetFont("Arial", "B", 16) +	// serialize and deserialize template +	b, _ := template2.Serialize() +	template3, _ := gofpdf.DeserializeTemplate(b) +  	pdf.AddPage() -	pdf.UseTemplate(template) -	pdf.UseTemplateScaled(template, gofpdf.PointType{X: 0, Y: 30}, tplSize) -	pdf.UseTemplateScaled(template, gofpdf.PointType{X: 0, Y: 60}, tplSize.ScaleBy(1.4)) +	pdf.UseTemplate(template3) +	pdf.UseTemplateScaled(template3, gofpdf.PointType{X: 0, Y: 30}, tplSize) +	pdf.UseTemplateScaled(template3, gofpdf.PointType{X: 0, Y: 60}, tplSize.ScaleBy(1.4))  	pdf.Line(40, 210, 60, 210)  	pdf.Text(40, 200, "Template example page 1") diff --git a/template.go b/template.go index 0bb7f75..d27bc40 100644 --- a/template.go +++ b/template.go @@ -18,6 +18,7 @@ package gofpdf   */  import ( +	"encoding/gob"  	"sort"  ) @@ -123,6 +124,9 @@ type Template interface {  	Bytes() []byte  	Images() map[string]*ImageInfoType  	Templates() []Template +	Serialize() ([]byte, error) +	gob.GobDecoder +	gob.GobEncoder  }  func (f *Fpdf) templateFontCatalog() { diff --git a/template_impl.go b/template_impl.go index 76c5019..1a91112 100644 --- a/template_impl.go +++ b/template_impl.go @@ -1,5 +1,11 @@  package gofpdf +import ( +	"bytes" +	"encoding/gob" +	"fmt" +) +  /*   * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung),   *   Marcus Downing, Jan Slabon (Setasign) @@ -76,6 +82,151 @@ func (t *FpdfTpl) Templates() []Template {  	return t.templates  } +// Turn a template into a byte string for later deserialization +func (t *FpdfTpl) Serialize() ([]byte, error) { +	b := new(bytes.Buffer) +	enc := gob.NewEncoder(b) +	err := enc.Encode(t) + +	return b.Bytes(), err +} + +// Create a template from a previously serialized template +func DeserializeTemplate(b []byte) (Template, error) { +	tpl := new(FpdfTpl) +	dec := gob.NewDecoder(bytes.NewBuffer(b)) +	err := dec.Decode(tpl) +	return tpl, err +} + +// returns the next layer of children images, it doesn't dig into +// children of children. Applies template namespace to keys to ensure +// no collisions. See UseTemplateScaled +func (t *FpdfTpl) childrenImages() map[string]*ImageInfoType { +	childrenImgs := make(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) +			childrenImgs[name] = val +		} +	} + +	return childrenImgs +} + +func (t *FpdfTpl) GobEncode() ([]byte, error) { +	w := new(bytes.Buffer) +	encoder := gob.NewEncoder(w) + +	err := encoder.Encode(t.templates) +	childrenImgs := t.childrenImages() + +	if err == nil { +		encoder.Encode(len(t.images)) +	} + +	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) + +		if err != nil { +			break +		} + +		if _, ok := childrenImgs[key]; ok { +			err = encoder.Encode("p") +		} else { +			err = encoder.Encode("o") +			if err == nil { +				err = encoder.Encode(img) +			} +		} +	} +	if err == nil { +		err = encoder.Encode(t.id) +	} +	if err == nil { +		err = encoder.Encode(t.corner) +	} +	if err == nil { +		err = encoder.Encode(t.size) +	} +	if err == nil { +		err = encoder.Encode(t.bytes) +	} + +	return w.Bytes(), err +} + +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] +	} + +	var numImgs int +	if err == nil { +		err = decoder.Decode(&numImgs) +	} + +	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) +		} + +		if err == nil { +			err = decoder.Decode(&tpe) +		} + +		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 +				} +			} +		} +	} +	if err == nil { +		err = decoder.Decode(&t.id) +	} +	if err == nil { +		err = decoder.Decode(&t.corner) +	} +	if err == nil { +		err = decoder.Decode(&t.size) +	} +	if err == nil { +		err = decoder.Decode(&t.bytes) +	} + +	return err +} +  // Tpl is an Fpdf used for writing a template. It has most of the facilities of  // an Fpdf, but cannot add more pages. Tpl is used directly only during the  // limited time a template is writable. | 
