diff options
-rw-r--r-- | fpdf_test.go | 36 | ||||
-rw-r--r-- | template.go | 3 | ||||
-rw-r--r-- | template_impl.go | 77 |
3 files changed, 99 insertions, 17 deletions
diff --git a/fpdf_test.go b/fpdf_test.go index 3e731fd..2fbca9c 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -64,6 +64,42 @@ func TestFpdfImplementPdf(t *testing.T) { var _ gofpdf.Pdf = (*gofpdf.Tpl)(nil) } +// TestPagedTemplate ensures new paged templates work +func TestPagedTemplate(t *testing.T) { + pdf := gofpdf.New("P", "mm", "A4", "") + tpl := pdf.CreateTemplate(func(t *gofpdf.Tpl) { + // this will be the second page, as a page is already + // created by default + t.AddPage() + t.AddPage() + t.AddPage() + }) + + if tpl.NumPages() != 4 { + t.Fatalf("The template does not have the correct number of pages %d", tpl.NumPages()) + } + + tplPages := tpl.FromPages() + for x := 0; x < len(tplPages); x++ { + pdf.AddPage() + pdf.UseTemplate(tplPages[x]) + } + + // get the last template + tpl2, err := tpl.FromPage(tpl.NumPages()) + if err != nil { + t.Fatal(err) + } + + // the objects should be the exact same, as the + // template will represent the last page by default + // therefore no new id should be set, and the object + // should be the same object + if fmt.Sprintf("%p", tpl2) != fmt.Sprintf("%p", tpl) { + t.Fatal("Template no longer respecting initial template object") + } +} + // TestIssue0116 addresses issue 116 in which library silently fails after // calling CellFormat when no font has been set. func TestIssue0116(t *testing.T) { diff --git a/template.go b/template.go index d27bc40..1bcd25d 100644 --- a/template.go +++ b/template.go @@ -124,6 +124,9 @@ type Template interface { Bytes() []byte Images() map[string]*ImageInfoType Templates() []Template + NumPages() int + FromPage(int) (Template, error) + FromPages() []Template Serialize() ([]byte, error) gob.GobDecoder gob.GobEncoder diff --git a/template_impl.go b/template_impl.go index 6a98e58..f7eeee1 100644 --- a/template_impl.go +++ b/template_impl.go @@ -3,6 +3,7 @@ package gofpdf import ( "bytes" "encoding/gob" + "errors" "fmt" ) @@ -32,10 +33,15 @@ func newTpl(corner PointType, size SizeType, orientationStr, unitStr, fontDirStr if copyFrom != nil { tpl.loadParamsFromFpdf(copyFrom) } - tpl.Fpdf.SetAutoPageBreak(false, 0) tpl.Fpdf.AddPage() fn(&tpl) - bytes := tpl.Fpdf.pages[tpl.Fpdf.page].Bytes() + + bytes := make([][]byte, len(tpl.Fpdf.pages)) + // skip the first page as it will always be empty + for x := 1; x < len(bytes); x++ { + bytes[x] = tpl.Fpdf.pages[x].Bytes() + } + templates := make([]Template, 0, len(tpl.Fpdf.templates)) for _, key := range templateKeyList(tpl.Fpdf.templates, true) { templates = append(templates, tpl.Fpdf.templates[key]) @@ -43,7 +49,7 @@ func newTpl(corner PointType, size SizeType, orientationStr, unitStr, fontDirStr images := tpl.Fpdf.images id := GenerateTemplateID() - template := FpdfTpl{id, corner, size, bytes, images, templates} + template := FpdfTpl{id, corner, size, bytes, images, templates, tpl.Fpdf.page} return &template } @@ -52,9 +58,10 @@ type FpdfTpl struct { id int64 corner PointType size SizeType - bytes []byte + bytes [][]byte images map[string]*ImageInfoType templates []Template + page int } // ID returns the global template identifier @@ -69,7 +76,42 @@ func (t *FpdfTpl) Size() (corner PointType, size SizeType) { // Bytes returns the actual template data, not including resources func (t *FpdfTpl) Bytes() []byte { - return t.bytes + return t.bytes[t.page] +} + +// FromPage creates a new template from a specific Page +func (t *FpdfTpl) FromPage(page int) (Template, error) { + // pages start at 1 + if page == 0 { + return nil, errors.New("Pages start at 1 No template will have a page 0") + } + + if page > t.NumPages() { + return nil, fmt.Errorf("The template does not have a page %d", page) + } + // if it is already pointing to the correct page + // there is no need to create a new template + if t.page == page { + return t, nil + } + + t2 := *t + t2.id = GenerateTemplateID() + t2.page = page + return &t2, nil +} + +// FromPages creates a template slice with all the pages within a template. +func (t *FpdfTpl) FromPages() []Template { + p := make([]Template, t.NumPages()) + for x := 1; x <= t.NumPages(); x++ { + // the only error is when accessing a + // non existing template... that can't happen + // here + p[x-1], _ = t.FromPage(x) + } + + return p } // Images returns a list of the images used in this template @@ -82,6 +124,13 @@ func (t *FpdfTpl) Templates() []Template { return t.templates } +// NumPages returns the number of available pages within the template. Look at FromPage and FromPages on access to that content. +func (t *FpdfTpl) NumPages() int { + // the first page is empty to + // make the pages begin at one + return len(t.bytes) - 1 +} + // Serialize turns a template into a byte string for later deserialization func (t *FpdfTpl) Serialize() ([]byte, error) { b := new(bytes.Buffer) @@ -160,6 +209,9 @@ func (t *FpdfTpl) GobEncode() ([]byte, error) { if err == nil { err = encoder.Encode(t.bytes) } + if err == nil { + err = encoder.Encode(t.page) + } return w.Bytes(), err } @@ -227,6 +279,9 @@ func (t *FpdfTpl) GobDecode(buf []byte) error { if err == nil { err = decoder.Decode(&t.bytes) } + if err == nil { + err = decoder.Decode(&t.page) + } return err } @@ -260,15 +315,3 @@ func (t *Tpl) loadParamsFromFpdf(f *Fpdf) { t.Fpdf.fontStyle = f.fontStyle t.Fpdf.ws = f.ws } - -// AddPage does nothing because you cannot add pages to a template -func (t *Tpl) AddPage() { -} - -// AddPageFormat does nothign because you cannot add pages to a template -func (t *Tpl) AddPageFormat(orientationStr string, size SizeType) { -} - -// SetAutoPageBreak does nothing because you cannot add pages to a template -func (t *Tpl) SetAutoPageBreak(auto bool, margin float64) { -} |