From cae789a4e309eb39bd6145f93361a3745effbb2d Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sat, 10 Oct 2015 06:23:36 -0400 Subject: Add method to fix document creation date --- fpdf.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index f1c6b58..efe5274 100644 --- a/fpdf.go +++ b/fpdf.go @@ -2986,6 +2986,14 @@ func (f *Fpdf) outf(fmtStr string, args ...interface{}) { f.out(sprintf(fmtStr, args...)) } +// SetCreationDate fixes the document's internal CreationDate value. By +// default, the time when the document is generated is used for this value. +// This method is typically only used for testing purposes. Specify a +// zero-value time to revert to the default behavior +func (f *Fpdf) SetCreationDate(tm time.Time) { + f.creationDate = tm +} + func (f *Fpdf) putpages() { var wPt, hPt float64 var pageSize SizeType @@ -3400,6 +3408,7 @@ func (f *Fpdf) putresources() { } func (f *Fpdf) putinfo() { + var tm time.Time f.outf("/Producer %s", f.textstring("FPDF "+cnFpdfVersion)) if len(f.title) > 0 { f.outf("/Title %s", f.textstring(f.title)) @@ -3416,7 +3425,12 @@ func (f *Fpdf) putinfo() { if len(f.creator) > 0 { f.outf("/Creator %s", f.textstring(f.creator)) } - f.outf("/CreationDate %s", f.textstring("D:"+time.Now().Format("20060102150405"))) + if f.creationDate.IsZero() { + tm = time.Now() + } else { + tm = f.creationDate + } + f.outf("/CreationDate %s", f.textstring("D:"+tm.Format("20060102150405"))) } func (f *Fpdf) putcatalog() { -- cgit v1.2.1-24-ge1ad From e924055b983321336e31f556f5235ea79fe72134 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sat, 10 Oct 2015 09:11:53 -0400 Subject: Implement conditional catalog sort feature --- fpdf.go | 230 +++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 135 insertions(+), 95 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index efe5274..d501574 100644 --- a/fpdf.go +++ b/fpdf.go @@ -36,6 +36,7 @@ import ( "math" "os" "path" + "sort" "strconv" "strings" "time" @@ -2986,6 +2987,13 @@ func (f *Fpdf) outf(fmtStr string, args ...interface{}) { f.out(sprintf(fmtStr, args...)) } +// SetCatalogSort sets a flag that will be used, if true, to consistently order +// the document's internal resource catalogs. This method is typically only +// used for test purposes. +func (f *Fpdf) SetCatalogSort(flag bool) { + f.catalogSort = flag +} + // SetCreationDate fixes the document's internal CreationDate value. By // default, the time when the document is generated is used for this value. // This method is typically only used for testing purposes. Specify a @@ -3100,107 +3108,131 @@ func (f *Fpdf) putfonts() { f.outf("<>", diff) f.out("endobj") } - for file, info := range f.fontFiles { - // foreach($this->fontFiles as $file=>$info) - // Font file embedding - f.newobj() - info.n = f.n - f.fontFiles[file] = info - font, err := f.loadFontFile(file) - if err != nil { - f.err = err - return - } - // dbg("font file [%s], ext [%s]", file, file[len(file)-2:]) - compressed := file[len(file)-2:] == ".z" - if !compressed && info.length2 > 0 { - buf := font[6:info.length1] - buf = append(buf, font[6+info.length1+6:info.length2]...) - font = buf + { + var fileList []string + var info fontFileType + var file string + for file = range f.fontFiles { + fileList = append(fileList, file) } - f.outf("< 0 { - f.outf("/Length2 %d /Length3 0", info.length2) - } - f.out(">>") - f.putstream(font) - f.out("endobj") - } - for k, font := range f.fonts { - // Font objects - font.N = f.n + 1 - f.fonts[k] = font - tp := font.Tp - name := font.Name - if tp == "Core" { - // Core font + for _, file = range fileList { + // for file, info := range f.fontFiles { + info = f.fontFiles[file] + // Font file embedding f.newobj() - f.out("<>") - f.out("endobj") - } else if tp == "Type1" || tp == "TrueType" { - // Additional Type1 or TrueType/OpenType font - f.newobj() - f.out("< 0 { - f.outf("/Encoding %d 0 R", nf+font.DiffN) - } else { - f.out("/Encoding /WinAnsiEncoding") + // dbg("font file [%s], ext [%s]", file, file[len(file)-2:]) + compressed := file[len(file)-2:] == ".z" + if !compressed && info.length2 > 0 { + buf := font[6:info.length1] + buf = append(buf, font[6+info.length1+6:info.length2]...) + font = buf } - f.out(">>") - f.out("endobj") - // Widths - f.newobj() - var s fmtBuffer - s.WriteString("[") - for j := 32; j < 256; j++ { - s.printf("%d ", font.Cw[j]) + f.outf("< 0 { + f.outf("/Length2 %d /Length3 0", info.length2) } - s.printf("/FontFile%s %d 0 R>>", suffix, f.fontFiles[font.File].n) - f.out(s.String()) + f.out(">>") + f.putstream(font) f.out("endobj") - } else { - f.err = fmt.Errorf("unsupported font type: %s", tp) - return - // Allow for additional types - // $mtd = 'put'.strtolower($type); - // if(!method_exists($this,$mtd)) - // $this->Error('Unsupported font type: '.$type); - // $this->$mtd($font); + } + } + { + var keyList []string + var font fontDefType + var key string + for key = range f.fonts { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + font = f.fonts[key] + // Font objects + font.N = f.n + 1 + f.fonts[key] = font + tp := font.Tp + name := font.Name + if tp == "Core" { + // Core font + f.newobj() + f.out("<>") + f.out("endobj") + } else if tp == "Type1" || tp == "TrueType" { + // Additional Type1 or TrueType/OpenType font + f.newobj() + f.out("< 0 { + f.outf("/Encoding %d 0 R", nf+font.DiffN) + } else { + f.out("/Encoding /WinAnsiEncoding") + } + f.out(">>") + f.out("endobj") + // Widths + f.newobj() + var s fmtBuffer + s.WriteString("[") + for j := 32; j < 256; j++ { + s.printf("%d ", font.Cw[j]) + } + s.WriteString("]") + f.out(s.String()) + f.out("endobj") + // Descriptor + f.newobj() + s.Truncate(0) + s.printf("<>", suffix, f.fontFiles[font.File].n) + f.out(s.String()) + f.out("endobj") + } else { + f.err = fmt.Errorf("unsupported font type: %s", tp) + return + // Allow for additional types + // $mtd = 'put'.strtolower($type); + // if(!method_exists($this,$mtd)) + // $this->Error('Unsupported font type: '.$type); + // $this->$mtd($font); + } } } return @@ -3221,8 +3253,16 @@ func (f *Fpdf) loadFontFile(name string) ([]byte, error) { } func (f *Fpdf) putimages() { - for _, img := range f.images { - f.putimage(img) + var keyList []string + var key string + for key = range f.images { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + f.putimage(f.images[key]) } } -- cgit v1.2.1-24-ge1ad From 5847afd8a205853a7effbf749b7a388ae325eb24 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sat, 10 Oct 2015 14:16:23 -0400 Subject: Introduce helper functions to set default catalog sort flag and creation date value. Remove regular expression scheme that effectively ignored the embedded creation date when comparing PDFs. --- fpdf.go | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index d501574..aeb0c3e 100644 --- a/fpdf.go +++ b/fpdf.go @@ -42,6 +42,11 @@ import ( "time" ) +var gl struct { + catalogSort bool + creationDate time.Time +} + type fmtBuffer struct { bytes.Buffer } @@ -180,6 +185,8 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) // Set default PDF version number f.pdfVersion = "1.3" f.layerInit() + f.catalogSort = gl.catalogSort + f.creationDate = gl.creationDate return } @@ -2987,6 +2994,13 @@ func (f *Fpdf) outf(fmtStr string, args ...interface{}) { f.out(sprintf(fmtStr, args...)) } +// SetDefaultCatalogSort sets the default value of the catalog sort flag that +// will be used when initializing a new Fpdf instance. See SetCatalogSort() for +// more details. +func SetDefaultCatalogSort(flag bool) { + gl.catalogSort = flag +} + // SetCatalogSort sets a flag that will be used, if true, to consistently order // the document's internal resource catalogs. This method is typically only // used for test purposes. @@ -2994,10 +3008,17 @@ func (f *Fpdf) SetCatalogSort(flag bool) { f.catalogSort = flag } +// SetDefaultCreationDate sets the default value of the document creation date +// that will be used when initializing a new Fpdf instance. See +// SetCreationDate() for more details. +func SetDefaultCreationDate(tm time.Time) { + gl.creationDate = tm +} + // SetCreationDate fixes the document's internal CreationDate value. By // default, the time when the document is generated is used for this value. // This method is typically only used for testing purposes. Specify a -// zero-value time to revert to the default behavior +// zero-value time to revert to the default behavior. func (f *Fpdf) SetCreationDate(tm time.Time) { f.creationDate = tm } @@ -3346,9 +3367,22 @@ func (f *Fpdf) putxobjectdict() { func (f *Fpdf) putresourcedict() { f.out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]") f.out("/Font <<") - for _, font := range f.fonts { - // foreach($this->fonts as $font) - f.outf("/F%d %d 0 R", font.I, font.N) + { + var keyList []string + var font fontDefType + var key string + for key = range f.fonts { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + font = f.fonts[key] + // for _, font := range f.fonts { + // foreach($this->fonts as $font) + f.outf("/F%d %d 0 R", font.I, font.N) + } } f.out(">>") f.out("/XObject <<") -- cgit v1.2.1-24-ge1ad From 92858a8b5ff04e4196597d9d517f3b2a0d651579 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sat, 10 Oct 2015 15:24:43 -0400 Subject: Conditionally sort image catalog. Correct small typos. --- fpdf.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index aeb0c3e..b5ed8e6 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3140,7 +3140,6 @@ func (f *Fpdf) putfonts() { sort.Strings(fileList) } for _, file = range fileList { - // for file, info := range f.fontFiles { info = f.fontFiles[file] // Font file embedding f.newobj() @@ -3352,9 +3351,20 @@ func (f *Fpdf) putimage(info *ImageInfoType) { } func (f *Fpdf) putxobjectdict() { - for _, image := range f.images { - // foreach($this->images as $image) - f.outf("/I%d %d 0 R", image.i, image.n) + { + var image *ImageInfoType + var key string + var keyList []string + for key = range f.images { + keyList = append(keyList, key) + } + if f.catalogSort { + sort.Strings(keyList) + } + for _, key = range keyList { + image = f.images[key] + f.outf("/I%d %d 0 R", image.i, image.n) + } } for _, tpl := range f.templates { id := tpl.ID() @@ -3379,8 +3389,6 @@ func (f *Fpdf) putresourcedict() { } for _, key = range keyList { font = f.fonts[key] - // for _, font := range f.fonts { - // foreach($this->fonts as $font) f.outf("/F%d %d 0 R", font.I, font.N) } } -- cgit v1.2.1-24-ge1ad From 13a5fda5f79f2c15eea512e6ec3de2ce60aa29ca Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sun, 11 Oct 2015 13:23:37 -0400 Subject: Conditionally sort two map iterations in template code; more to come. --- fpdf.go | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index b5ed8e6..08bcb2e 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3366,10 +3366,29 @@ func (f *Fpdf) putxobjectdict() { f.outf("/I%d %d 0 R", image.i, image.n) } } - for _, tpl := range f.templates { - id := tpl.ID() - if objID, ok := f.templateObjects[id]; ok { - f.outf("/TPL%d %d 0 R", id, objID) + { + var key int64 + var keyList []int64 + var tpl Template + for key = range f.templates { + keyList = append(keyList, key) + } + if f.catalogSort { + gensort(len(keyList), + func(a, b int) bool { + return keyList[a] < keyList[b] + }, + func(a, b int) { + keyList[a], keyList[b] = keyList[b], keyList[a] + }) + } + for _, key = range keyList { + tpl = f.templates[key] + // for _, tpl := range f.templates { + id := tpl.ID() + if objID, ok := f.templateObjects[id]; ok { + f.outf("/TPL%d %d 0 R", id, objID) + } } } } -- cgit v1.2.1-24-ge1ad From d51e132c6432f2c1bbff5d9516f77375bb5252e6 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Sun, 11 Oct 2015 21:06:01 -0400 Subject: Conditionally order another map iteration. Fix 'go vet' problem with unkeyed field in composite literal. --- fpdf.go | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index 08bcb2e..74489de 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3367,21 +3367,10 @@ func (f *Fpdf) putxobjectdict() { } } { - var key int64 var keyList []int64 + var key int64 var tpl Template - for key = range f.templates { - keyList = append(keyList, key) - } - if f.catalogSort { - gensort(len(keyList), - func(a, b int) bool { - return keyList[a] < keyList[b] - }, - func(a, b int) { - keyList[a], keyList[b] = keyList[b], keyList[a] - }) - } + keyList = templateKeyList(f.templates, f.catalogSort) for _, key = range keyList { tpl = f.templates[key] // for _, tpl := range f.templates { -- cgit v1.2.1-24-ge1ad From 31c1da203bd00ff9e9ba602257bab2b4282ca945 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Mon, 12 Oct 2015 10:34:43 -0400 Subject: Add reference PDFs for comparison purposes. Document comparison of example documents. --- fpdf.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fpdf.go') diff --git a/fpdf.go b/fpdf.go index 74489de..bc23674 100644 --- a/fpdf.go +++ b/fpdf.go @@ -3003,7 +3003,7 @@ func SetDefaultCatalogSort(flag bool) { // SetCatalogSort sets a flag that will be used, if true, to consistently order // the document's internal resource catalogs. This method is typically only -// used for test purposes. +// used for test purposes to facilitate PDF comparison. func (f *Fpdf) SetCatalogSort(flag bool) { f.catalogSort = flag } @@ -3017,8 +3017,8 @@ func SetDefaultCreationDate(tm time.Time) { // SetCreationDate fixes the document's internal CreationDate value. By // default, the time when the document is generated is used for this value. -// This method is typically only used for testing purposes. Specify a -// zero-value time to revert to the default behavior. +// This method is typically only used for testing purposes to facilitate PDF +// comparsion. Specify a zero-value time to revert to the default behavior. func (f *Fpdf) SetCreationDate(tm time.Time) { f.creationDate = tm } -- cgit v1.2.1-24-ge1ad