Kurt Jungs Auslieferungszustand
This commit is contained in:
143
contrib/gofpdi/gofpdi.go
Normal file
143
contrib/gofpdi/gofpdi.go
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Package gofpdi wraps the gofpdi PDF library to import existing PDFs as templates. See github.com/phpdave11/gofpdi
|
||||
for further information and examples.
|
||||
|
||||
Users should call NewImporter() to obtain their own Importer instance to work with.
|
||||
To retain backwards compatibility, the package offers a default Importer that may be used via global functions. Note
|
||||
however that use of the default Importer is not thread safe.
|
||||
*/
|
||||
package gofpdi
|
||||
|
||||
import (
|
||||
realgofpdi "github.com/phpdave11/gofpdi"
|
||||
"io"
|
||||
)
|
||||
|
||||
// gofpdiPdf is a partial interface that only implements the functions we need
|
||||
// from the PDF generator to put the imported PDF templates on the PDF.
|
||||
type gofpdiPdf interface {
|
||||
ImportObjects(objs map[string][]byte)
|
||||
ImportObjPos(objs map[string]map[int]string)
|
||||
ImportTemplates(tpls map[string]string)
|
||||
UseImportedTemplate(tplName string, x float64, y float64, w float64, h float64)
|
||||
SetError(err error)
|
||||
}
|
||||
|
||||
// Importer wraps an Importer from the gofpdi library.
|
||||
type Importer struct {
|
||||
fpdi *realgofpdi.Importer
|
||||
}
|
||||
|
||||
// NewImporter creates a new Importer wrapping functionality from the gofpdi library.
|
||||
func NewImporter() *Importer {
|
||||
return &Importer{
|
||||
fpdi: realgofpdi.NewImporter(),
|
||||
}
|
||||
}
|
||||
|
||||
// ImportPage imports a page of a PDF file with the specified box (/MediaBox,
|
||||
// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can
|
||||
// be used with UseImportedTemplate to draw the template onto the page.
|
||||
func (i *Importer) ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int {
|
||||
// Set source file for fpdi
|
||||
i.fpdi.SetSourceFile(sourceFile)
|
||||
// return template id
|
||||
return i.getTemplateID(f, pageno, box)
|
||||
}
|
||||
|
||||
// ImportPageFromStream imports a page of a PDF with the specified box
|
||||
// (/MediaBox, TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id
|
||||
// that can be used with UseImportedTemplate to draw the template onto the
|
||||
// page.
|
||||
func (i *Importer) ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int {
|
||||
// Set source stream for fpdi
|
||||
i.fpdi.SetSourceStream(rs)
|
||||
// return template id
|
||||
return i.getTemplateID(f, pageno, box)
|
||||
}
|
||||
|
||||
func (i *Importer) getTemplateID(f gofpdiPdf, pageno int, box string) int {
|
||||
// Import page
|
||||
tpl := i.fpdi.ImportPage(pageno, box)
|
||||
|
||||
// Import objects into current pdf document
|
||||
// Unordered means that the objects will be returned with a sha1 hash instead of an integer
|
||||
// The objects themselves may have references to other hashes which will be replaced in ImportObjects()
|
||||
tplObjIDs := i.fpdi.PutFormXobjectsUnordered()
|
||||
|
||||
// Set template names and ids (hashes) in gofpdf
|
||||
f.ImportTemplates(tplObjIDs)
|
||||
|
||||
// Get a map[string]string of the imported objects.
|
||||
// The map keys will be the ID of each object.
|
||||
imported := i.fpdi.GetImportedObjectsUnordered()
|
||||
|
||||
// Import gofpdi objects into gofpdf
|
||||
f.ImportObjects(imported)
|
||||
|
||||
// Get a map[string]map[int]string of the object hashes and their positions within each object,
|
||||
// to be replaced with object ids (integers).
|
||||
importedObjPos := i.fpdi.GetImportedObjHashPos()
|
||||
|
||||
// Import gofpdi object hashes and their positions into gopdf
|
||||
f.ImportObjPos(importedObjPos)
|
||||
|
||||
return tpl
|
||||
}
|
||||
|
||||
// UseImportedTemplate draws the template onto the page at x,y. If w is 0, the
|
||||
// template will be scaled to fit based on h. If h is 0, the template will be
|
||||
// scaled to fit based on w.
|
||||
func (i *Importer) UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) {
|
||||
// Get values from fpdi
|
||||
tplName, scaleX, scaleY, tX, tY := i.fpdi.UseTemplate(tplid, x, y, w, h)
|
||||
|
||||
f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY)
|
||||
}
|
||||
|
||||
// GetPageSizes returns page dimensions for all pages of the imported pdf.
|
||||
// Result consists of map[<page number>]map[<box>]map[<dimension>]<value>.
|
||||
// <page number>: page number, note that page numbers start at 1
|
||||
// <box>: box identifier, e.g. "/MediaBox"
|
||||
// <dimension>: dimension string, either "w" or "h"
|
||||
func (i *Importer) GetPageSizes() map[int]map[string]map[string]float64 {
|
||||
return i.fpdi.GetPageSizes()
|
||||
}
|
||||
|
||||
// Default Importer used by global functions
|
||||
var fpdi = NewImporter()
|
||||
|
||||
// ImportPage imports a page of a PDF file with the specified box (/MediaBox,
|
||||
// /TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id that can
|
||||
// be used with UseImportedTemplate to draw the template onto the page.
|
||||
// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer.
|
||||
func ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int {
|
||||
return fpdi.ImportPage(f, sourceFile, pageno, box)
|
||||
}
|
||||
|
||||
// ImportPageFromStream imports a page of a PDF with the specified box
|
||||
// (/MediaBox, TrimBox, /ArtBox, /CropBox, or /BleedBox). Returns a template id
|
||||
// that can be used with UseImportedTemplate to draw the template onto the
|
||||
// page.
|
||||
// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer.
|
||||
func ImportPageFromStream(f gofpdiPdf, rs *io.ReadSeeker, pageno int, box string) int {
|
||||
return fpdi.ImportPageFromStream(f, rs, pageno, box)
|
||||
}
|
||||
|
||||
// UseImportedTemplate draws the template onto the page at x,y. If w is 0, the
|
||||
// template will be scaled to fit based on h. If h is 0, the template will be
|
||||
// scaled to fit based on w.
|
||||
// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer.
|
||||
func UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) {
|
||||
fpdi.UseImportedTemplate(f, tplid, x, y, w, h)
|
||||
}
|
||||
|
||||
// GetPageSizes returns page dimensions for all pages of the imported pdf.
|
||||
// Result consists of map[<page number>]map[<box>]map[<dimension>]<value>.
|
||||
// <page number>: page number, note that page numbers start at 1
|
||||
// <box>: box identifier, e.g. "/MediaBox"
|
||||
// <dimension>: dimension string, either "w" or "h"
|
||||
// Note: This uses the default Importer. Call NewImporter() to obtain a custom Importer.
|
||||
func GetPageSizes() map[int]map[string]map[string]float64 {
|
||||
return fpdi.GetPageSizes()
|
||||
}
|
76
contrib/gofpdi/gofpdi_test.go
Normal file
76
contrib/gofpdi/gofpdi_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package gofpdi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/jung-kurt/gofpdf"
|
||||
"github.com/jung-kurt/gofpdf/internal/example"
|
||||
"io"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func ExampleNewImporter() {
|
||||
// create new pdf
|
||||
pdf := gofpdf.New("P", "pt", "A4", "")
|
||||
|
||||
// for testing purposes, get an arbitrary template pdf as stream
|
||||
rs, _ := getTemplatePdf()
|
||||
|
||||
// create a new Importer instance
|
||||
imp := NewImporter()
|
||||
|
||||
// import first page and determine page sizes
|
||||
tpl := imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox")
|
||||
pageSizes := imp.GetPageSizes()
|
||||
nrPages := len(imp.GetPageSizes())
|
||||
|
||||
// add all pages from template pdf
|
||||
for i := 1; i <= nrPages; i++ {
|
||||
pdf.AddPage()
|
||||
if i > 1 {
|
||||
tpl = imp.ImportPageFromStream(pdf, &rs, i, "/MediaBox")
|
||||
}
|
||||
imp.UseImportedTemplate(pdf, tpl, 0, 0, pageSizes[i]["/MediaBox"]["w"], pageSizes[i]["/MediaBox"]["h"])
|
||||
}
|
||||
|
||||
// output
|
||||
fileStr := example.Filename("contrib_gofpdi_Importer")
|
||||
err := pdf.OutputFileAndClose(fileStr)
|
||||
example.Summary(err, fileStr)
|
||||
// Output:
|
||||
// Successfully generated ../../pdf/contrib_gofpdi_Importer.pdf
|
||||
}
|
||||
|
||||
func TestGofpdiConcurrent(t *testing.T) {
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < 100; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
pdf := gofpdf.New("P", "mm", "A4", "")
|
||||
pdf.AddPage()
|
||||
rs, _ := getTemplatePdf()
|
||||
imp := NewImporter()
|
||||
tpl := imp.ImportPageFromStream(pdf, &rs, 1, "/MediaBox")
|
||||
imp.UseImportedTemplate(pdf, tpl, 0, 0, 210.0, 297.0)
|
||||
// write to bytes buffer
|
||||
buf := bytes.Buffer{}
|
||||
if err := pdf.Output(&buf); err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func getTemplatePdf() (io.ReadSeeker, error) {
|
||||
tpdf := gofpdf.New("P", "pt", "A4", "")
|
||||
tpdf.AddPage()
|
||||
tpdf.SetFont("Arial", "", 12)
|
||||
tpdf.Text(20, 20, "Example Page 1")
|
||||
tpdf.AddPage()
|
||||
tpdf.Text(20, 20, "Example Page 2")
|
||||
tbuf := bytes.Buffer{}
|
||||
err := tpdf.Output(&tbuf)
|
||||
return bytes.NewReader(tbuf.Bytes()), err
|
||||
}
|
Reference in New Issue
Block a user