summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt <kurt.w.jung@gmail.com>2019-05-15 12:44:01 -0400
committerKurt <kurt.w.jung@gmail.com>2019-05-15 12:44:01 -0400
commit5a54c683de36b69f4a8bc4575f15fe6c1ecdebd9 (patch)
tree9cb1a09627c5340e6be7175aa7e90858ca1a61d2
parent8f080922446313698730071fd92ca15900e6a941 (diff)
parenteca8e8f3216d7e07f60db6cea8fd5067d99e3c27 (diff)
Merge branch 'phpdave11-master'
-rw-r--r--README.md4
-rw-r--r--contrib/gofpdi/gofpdi.go62
-rw-r--r--def.go4
-rw-r--r--doc.go5
-rw-r--r--doc/document.md3
-rw-r--r--fpdf.go91
6 files changed, 166 insertions, 3 deletions
diff --git a/README.md b/README.md
index 2d5d14e..811bbc3 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,7 @@ support for text, drawing and images.
- Templates
- Barcodes
- Charting facility
+ - Import PDFs as templates
gofpdf has no dependencies other than the Go standard library. All tests
pass on Linux, Mac and Windows platforms.
@@ -246,7 +247,8 @@ encoding and decoding functionality for templates, including images that
are embedded in templates; this allows templates to be stored
independently of gofpdf. Paul also added support for page boxes used in
printing PDF documents. Wojciech Matusiak added supported for word
-spacing. Artem Korotkiy added support of UTF-8 fonts.
+spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added
+support for imported objects and templates.
## Roadmap
diff --git a/contrib/gofpdi/gofpdi.go b/contrib/gofpdi/gofpdi.go
new file mode 100644
index 0000000..d1b98e9
--- /dev/null
+++ b/contrib/gofpdi/gofpdi.go
@@ -0,0 +1,62 @@
+package gofpdi
+
+import (
+ realgofpdi "github.com/phpdave11/gofpdi"
+)
+
+// Create new gofpdi instance
+var fpdi = realgofpdi.NewImporter()
+
+// 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)
+}
+
+// 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 ImportPage(f gofpdiPdf, sourceFile string, pageno int, box string) int {
+ // Set source file for fpdi
+ fpdi.SetSourceFile(sourceFile)
+
+ // Import page
+ tpl := 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 := 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 := 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 := fpdi.GetImportedObjHashPos()
+
+ // Import gofpdi object hashes and their positions into gopdf
+ f.ImportObjPos(importedObjPos)
+
+ return tpl
+}
+
+// Draw 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 UseImportedTemplate(f gofpdiPdf, tplid int, x float64, y float64, w float64, h float64) {
+ // Get values from fpdi
+ tplName, scaleX, scaleY, tX, tY := fpdi.UseTemplate(tplid, x, y, w, h)
+
+ f.UseImportedTemplate(tplName, scaleX, scaleY, tX, tY)
+}
diff --git a/def.go b/def.go
index ab4e81d..efa573e 100644
--- a/def.go
+++ b/def.go
@@ -504,6 +504,10 @@ type Fpdf struct {
offsets []int // array of object offsets
templates map[string]Template // templates used in this document
templateObjects map[string]int // template object IDs within this document
+ importedObjs map[string][]byte // imported template objects (gofpdi)
+ importedObjPos map[string]map[int]string // imported template objects hashes and their positions (gofpdi)
+ importedTplObjs map[string]string // imported template names and IDs (hashed) (gofpdi)
+ importedTplIDs map[string]int // imported template ids hash to object id int (gofpdi)
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/doc.go b/doc.go
index 2d6f49b..6ad0461 100644
--- a/doc.go
+++ b/doc.go
@@ -42,6 +42,8 @@ Features
- Charting facility
+- Import PDFs as templates
+
gofpdf has no dependencies other than the Go standard library. All tests
pass on Linux, Mac and Windows platforms.
@@ -253,7 +255,8 @@ encoding and decoding functionality for templates, including images that
are embedded in templates; this allows templates to be stored
independently of gofpdf. Paul also added support for page boxes used in
printing PDF documents. Wojciech Matusiak added supported for word
-spacing. Artem Korotkiy added support of UTF-8 fonts.
+spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added
+support for imported objects and templates.
Roadmap
diff --git a/doc/document.md b/doc/document.md
index 33f5dac..fa544af 100644
--- a/doc/document.md
+++ b/doc/document.md
@@ -29,6 +29,7 @@ text, drawing and images.
* Templates
* Barcodes
* Charting facility
+* Import PDFs as templates
gofpdf has no dependencies other than the Go standard library. All tests pass
on Linux, Mac and Windows platforms.
@@ -226,7 +227,7 @@ decoding functionality for templates, including images that are embedded in
templates; this allows templates to be stored independently of gofpdf. Paul
also added support for page boxes used in printing PDF documents. Wojciech
Matusiak added supported for word spacing. Artem Korotkiy added support of
-UTF-8 fonts.
+UTF-8 fonts. Dave Barnes added support for imported objects and templates.
## Roadmap
diff --git a/fpdf.go b/fpdf.go
index d3366ce..666f97f 100644
--- a/fpdf.go
+++ b/fpdf.go
@@ -85,6 +85,10 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType)
f.diffs = make([]string, 0, 8)
f.templates = make(map[string]Template)
f.templateObjects = make(map[string]int)
+ f.importedObjs = make(map[string][]byte, 0)
+ f.importedObjPos = make(map[string]map[int]string, 0)
+ f.importedTplObjs = make(map[string]string)
+ f.importedTplIDs = make(map[string]int, 0)
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)
@@ -3101,6 +3105,86 @@ func (f *Fpdf) GetImageInfo(imageStr string) (info *ImageInfoType) {
return f.images[imageStr]
}
+// ImportObjects imports objects from gofpdi into current document
+func (f *Fpdf) ImportObjects(objs map[string][]byte) {
+ for k, v := range objs {
+ f.importedObjs[k] = v
+ }
+}
+
+// ImportObjPos imports object hash positions from gofpdi
+func (f *Fpdf) ImportObjPos(objPos map[string]map[int]string) {
+ for k, v := range objPos {
+ f.importedObjPos[k] = v
+ }
+}
+
+// putImportedTemplates writes the imported template objects to the PDF
+func (f *Fpdf) putImportedTemplates() {
+ nOffset := f.n + 1
+
+ // keep track of list of sha1 hashes (to be replaced with integers)
+ objsIDHash := make([]string, len(f.importedObjs))
+
+ // actual object data with new id
+ objsIDData := make([][]byte, len(f.importedObjs))
+
+ // Populate hash slice and data slice
+ i := 0
+ for k, v := range f.importedObjs {
+ objsIDHash[i] = k
+ objsIDData[i] = v
+
+ i++
+ }
+
+ // Populate a lookup table to get an object id from a hash
+ hashToObjID := make(map[string]int, len(f.importedObjs))
+ for i = 0; i < len(objsIDHash); i++ {
+ hashToObjID[objsIDHash[i]] = i + nOffset
+ }
+
+ // Now, replace hashes inside data with %040d object id
+ for i = 0; i < len(objsIDData); i++ {
+ // get hash
+ hash := objsIDHash[i]
+
+ for pos, h := range f.importedObjPos[hash] {
+ // Convert object id into a 40 character string padded with spaces
+ objIDPadded := fmt.Sprintf("%40s", fmt.Sprintf("%d", hashToObjID[h]))
+
+ // Convert objIDPadded into []byte
+ objIDBytes := []byte(objIDPadded)
+
+ // Replace sha1 hash with object id padded
+ for j := pos; j < pos+40; j++ {
+ objsIDData[i][j] = objIDBytes[j-pos]
+ }
+ }
+
+ // Save objsIDHash so that procset dictionary has the correct object ids
+ f.importedTplIDs[hash] = i + nOffset
+ }
+
+ // Now, put objects
+ for i = 0; i < len(objsIDData); i++ {
+ f.newobj()
+ f.out(string(objsIDData[i]))
+ }
+}
+
+// UseImportedTemplate uses imported template from gofpdi - draws imported PDF page onto page
+func (f *Fpdf) UseImportedTemplate(tplName string, scaleX float64, scaleY float64, tX float64, tY float64) {
+ f.outf("q 0 J 1 w 0 j 0 G 0 g q %.4F 0 0 %.4F %.4F %.4F cm %s Do Q Q\n", scaleX*f.k, scaleY*f.k, tX*f.k, (tY+f.h)*f.k, tplName)
+}
+
+// ImportTemplates imports gofpdi template names into importedTplObjs - to be included in the procset dictionary
+func (f *Fpdf) ImportTemplates(tpls map[string]string) {
+ for tplName, tplID := range tpls {
+ f.importedTplObjs[tplName] = tplID
+ }
+}
+
// GetConversionRatio returns the conversion ratio based on the unit given when
// creating the PDF.
func (f *Fpdf) GetConversionRatio() float64 {
@@ -4173,6 +4257,12 @@ func (f *Fpdf) putxobjectdict() {
}
}
}
+ {
+ for tplName, objID := range f.importedTplObjs {
+ // here replace obj id hash with n
+ f.outf("%s %d 0 R", tplName, f.importedTplIDs[objID])
+ }
+ }
}
func (f *Fpdf) putresourcedict() {
@@ -4288,6 +4378,7 @@ func (f *Fpdf) putresources() {
}
f.putimages()
f.putTemplates()
+ f.putImportedTemplates() // gofpdi
// Resource dictionary
f.offsets[2] = f.buffer.Len()
f.out("2 0 obj")