From a10ee5edb8fbe4edf56f06e58cba360044710517 Mon Sep 17 00:00:00 2001 From: Paul Montag Date: Thu, 8 Nov 2018 13:30:29 -0600 Subject: Added page boxes --- def.go | 178 +++++++++++++++++++++++++++++++++------------------------------- fpdf.go | 46 +++++++++++++++++ 2 files changed, 139 insertions(+), 85 deletions(-) diff --git a/def.go b/def.go index b4140a9..db69632 100644 --- a/def.go +++ b/def.go @@ -399,6 +399,7 @@ type Pdf interface { SetLineWidth(width float64) SetLink(link int, y float64, page int) SetMargins(left, top, right float64) + SetPageBox(t string, pb PageBox) SetProtection(actionFlag byte, userPassStr, ownerPassStr string) SetRightMargin(margin float64) SetSubject(subjectStr string, isUTF8 bool) @@ -442,93 +443,100 @@ type Pdf interface { Writef(h float64, fmtStr string, args ...interface{}) } +type PageBox struct { + SizeType + PointType +} + // Fpdf is the principal structure for creating a single PDF document type Fpdf struct { - page int // current page number - n int // current object number - offsets []int // array of object offsets - templates map[int64]Template // templates used in this document - templateObjects map[int64]int // template object IDs within this document - buffer fmtBuffer // buffer holding in-memory PDF - pages []*bytes.Buffer // slice[page] of page content; 1-based - state int // current document state - compress bool // compression flag - k float64 // scale factor (number of points in user unit) - defOrientation string // default orientation - curOrientation string // current orientation - stdPageSizes map[string]SizeType // standard page sizes - defPageSize SizeType // default page size - curPageSize SizeType // current page size - pageSizes map[int]SizeType // used for pages with non default sizes or orientations - unitStr string // unit of measure for all rendered objects except fonts - wPt, hPt float64 // dimensions of current page in points - w, h float64 // dimensions of current page in user unit - lMargin float64 // left margin - tMargin float64 // top margin - rMargin float64 // right margin - bMargin float64 // page break margin - cMargin float64 // cell margin - x, y float64 // current position in user unit - lasth float64 // height of last printed cell - lineWidth float64 // line width in user unit - fontpath string // path containing fonts - fontLoader FontLoader // used to load font files from arbitrary locations - coreFonts map[string]bool // array of core font names - fonts map[string]fontDefType // array of used fonts - fontFiles map[string]fontFileType // array of font files - diffs []string // array of encoding differences - fontFamily string // current font family - fontStyle string // current font style - underline bool // underlining flag - currentFont fontDefType // current font info - fontSizePt float64 // current font size in points - fontSize float64 // current font size in user unit - ws float64 // word spacing - images map[string]*ImageInfoType // array of used images - aliasMap map[string]string // map of alias->replacement - pageLinks [][]linkType // pageLinks[page][link], both 1-based - links []intLinkType // array of internal links - outlines []outlineType // array of outlines - outlineRoot int // root of outlines - autoPageBreak bool // automatic page breaking - acceptPageBreak func() bool // returns true to accept page break - pageBreakTrigger float64 // threshold used to trigger page breaks - inHeader bool // flag set when processing header - headerFnc func() // function provided by app and called to write header - headerHomeMode bool // set position to home after headerFnc is called - inFooter bool // flag set when processing footer - footerFnc func() // function provided by app and called to write footer - footerFncLpi func(bool) // function provided by app and called to write footer with last page flag - zoomMode string // zoom display mode - layoutMode string // layout display mode - xmp []byte // XMP metadata - title string // title - subject string // subject - author string // author - keywords string // keywords - creator string // creator - creationDate time.Time // override for dcoument CreationDate value - aliasNbPagesStr string // alias for total number of pages - pdfVersion string // PDF version number - fontDirStr string // location of font definition files - capStyle int // line cap style: butt 0, round 1, square 2 - joinStyle int // line segment join style: miter 0, round 1, bevel 2 - dashArray []float64 // dash array - dashPhase float64 // dash phase - blendList []blendModeType // slice[idx] of alpha transparency modes, 1-based - blendMap map[string]int // map into blendList - blendMode string // current blend mode - alpha float64 // current transpacency - gradientList []gradientType // slice[idx] of gradient records - clipNest int // Number of active clipping contexts - transformNest int // Number of active transformation contexts - err error // Set if error occurs during life cycle of instance - protect protectType // document protection structure - layer layerRecType // manages optional layers in document - catalogSort bool // sort resource catalogs in document - nJs int // JavaScript object number - javascript *string // JavaScript code to include in the PDF - colorFlag bool // indicates whether fill and text colors are different + page int // current page number + n int // current object number + offsets []int // array of object offsets + templates map[int64]Template // templates used in this document + templateObjects map[int64]int // template object IDs within this document + buffer fmtBuffer // buffer holding in-memory PDF + pages []*bytes.Buffer // slice[page] of page content; 1-based + state int // current document state + compress bool // compression flag + k float64 // scale factor (number of points in user unit) + defOrientation string // default orientation + curOrientation string // current orientation + stdPageSizes map[string]SizeType // standard page sizes + defPageSize SizeType // default page size + defPageBoxes map[string]PageBox // default page size + curPageSize SizeType // current page size + pageSizes map[int]SizeType // used for pages with non default sizes or orientations + pageBoxes map[int]map[string]PageBox // used to define the crop, trim, bleed and art boxes + unitStr string // unit of measure for all rendered objects except fonts + wPt, hPt float64 // dimensions of current page in points + w, h float64 // dimensions of current page in user unit + lMargin float64 // left margin + tMargin float64 // top margin + rMargin float64 // right margin + bMargin float64 // page break margin + cMargin float64 // cell margin + x, y float64 // current position in user unit + lasth float64 // height of last printed cell + lineWidth float64 // line width in user unit + fontpath string // path containing fonts + fontLoader FontLoader // used to load font files from arbitrary locations + coreFonts map[string]bool // array of core font names + fonts map[string]fontDefType // array of used fonts + fontFiles map[string]fontFileType // array of font files + diffs []string // array of encoding differences + fontFamily string // current font family + fontStyle string // current font style + underline bool // underlining flag + currentFont fontDefType // current font info + fontSizePt float64 // current font size in points + fontSize float64 // current font size in user unit + ws float64 // word spacing + images map[string]*ImageInfoType // array of used images + aliasMap map[string]string // map of alias->replacement + pageLinks [][]linkType // pageLinks[page][link], both 1-based + links []intLinkType // array of internal links + outlines []outlineType // array of outlines + outlineRoot int // root of outlines + autoPageBreak bool // automatic page breaking + acceptPageBreak func() bool // returns true to accept page break + pageBreakTrigger float64 // threshold used to trigger page breaks + inHeader bool // flag set when processing header + headerFnc func() // function provided by app and called to write header + headerHomeMode bool // set position to home after headerFnc is called + inFooter bool // flag set when processing footer + footerFnc func() // function provided by app and called to write footer + footerFncLpi func(bool) // function provided by app and called to write footer with last page flag + zoomMode string // zoom display mode + layoutMode string // layout display mode + xmp []byte // XMP metadata + title string // title + subject string // subject + author string // author + keywords string // keywords + creator string // creator + creationDate time.Time // override for dcoument CreationDate value + aliasNbPagesStr string // alias for total number of pages + pdfVersion string // PDF version number + fontDirStr string // location of font definition files + capStyle int // line cap style: butt 0, round 1, square 2 + joinStyle int // line segment join style: miter 0, round 1, bevel 2 + dashArray []float64 // dash array + dashPhase float64 // dash phase + blendList []blendModeType // slice[idx] of alpha transparency modes, 1-based + blendMap map[string]int // map into blendList + blendMode string // current blend mode + alpha float64 // current transpacency + gradientList []gradientType // slice[idx] of gradient records + clipNest int // Number of active clipping contexts + transformNest int // Number of active transformation contexts + err error // Set if error occurs during life cycle of instance + protect protectType // document protection structure + layer layerRecType // manages optional layers in document + catalogSort bool // sort resource catalogs in document + nJs int // JavaScript object number + javascript *string // JavaScript code to include in the PDF + colorFlag bool // indicates whether fill and text colors are different color struct { // Composite values of colors draw, fill, text colorType diff --git a/fpdf.go b/fpdf.go index 822d87f..d735269 100644 --- a/fpdf.go +++ b/fpdf.go @@ -77,6 +77,8 @@ func fpdfNew(orientationStr, unitStr, sizeStr, fontDirStr string, size SizeType) f.pages = make([]*bytes.Buffer, 0, 8) f.pages = append(f.pages, bytes.NewBufferString("")) // pages[0] is unused (1-based) f.pageSizes = make(map[int]SizeType) + f.pageBoxes = make(map[int]map[string]PageBox) + f.defPageBoxes = make(map[string]PageBox) f.state = 0 f.fonts = make(map[string]fontDefType) f.fontFiles = make(map[string]fontFileType) @@ -335,6 +337,42 @@ func (f *Fpdf) SetCellMargin(margin float64) { f.cMargin = margin } +// SetPageBox sets the page box for the current page, and any following pages. +// Allowable types are trim, trimbox, crop, cropbox, bleed, bleedbox, art and artbox +// box types are case insensitive. +func (f *Fpdf) SetPageBox(t string, pb PageBox) { + switch strings.ToLower(t) { + case "trim": + fallthrough + case "trimbox": + t = "TrimBox" + case "crop": + fallthrough + case "cropbox": + t = "CropBox" + case "bleed": + fallthrough + case "bleedbox": + t = "BleedBox" + case "art": + fallthrough + case "artbox": + t = "ArtBox" + } + + pb.X = pb.X * f.k + pb.Y = pb.Y * f.k + pb.Wd = (pb.Wd * f.k) + pb.X + pb.Ht = (pb.Ht * f.k) + pb.Y + + if f.page > 0 { + f.pageBoxes[f.page][t] = pb + } + + // always override. page defaults are supplied in addPage function + f.defPageBoxes[t] = pb +} + // SetFontLocation sets the location in the file system of the font and font // definition files. func (f *Fpdf) SetFontLocation(fontDirStr string) { @@ -2845,6 +2883,11 @@ func (f *Fpdf) beginpage(orientationStr string, size SizeType) { return } f.page++ + // add the default page boxes, if any exist, to the page + f.pageBoxes[f.page] = make(map[string]PageBox) + for box, pb := range f.defPageBoxes { + f.pageBoxes[f.page][box] = pb + } f.pages = append(f.pages, bytes.NewBufferString("")) f.pageLinks = append(f.pageLinks, make([]linkType, 0, 0)) f.state = 2 @@ -3185,6 +3228,9 @@ func (f *Fpdf) putpages() { if ok { f.outf("/MediaBox [0 0 %.2f %.2f]", pageSize.Wd, pageSize.Ht) } + for t, pb := range f.pageBoxes[n] { + f.outf("/%s [%.2f %.2f %.2f %.2f]", t, pb.X, pb.Y, pb.Wd, pb.Ht) + } f.out("/Resources 2 0 R") // Links if len(f.pageLinks[n]) > 0 { -- cgit v1.2.1-24-ge1ad From 91898b5ca557dbf88649ee45b12a484d3780b05f Mon Sep 17 00:00:00 2001 From: Paul Montag Date: Thu, 8 Nov 2018 14:29:38 -0600 Subject: Added an error if an invalid box type is passed in --- fpdf.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fpdf.go b/fpdf.go index d735269..9818aeb 100644 --- a/fpdf.go +++ b/fpdf.go @@ -358,6 +358,9 @@ func (f *Fpdf) SetPageBox(t string, pb PageBox) { fallthrough case "artbox": t = "ArtBox" + default: + f.err = fmt.Sprintf("%s is not a valid page box type") + return } pb.X = pb.X * f.k -- cgit v1.2.1-24-ge1ad From 2253c0aa4a1566727231123793a2eda56c571c8f Mon Sep 17 00:00:00 2001 From: Paul Montag Date: Thu, 8 Nov 2018 14:37:57 -0600 Subject: Fixed a stupid bug --- fpdf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpdf.go b/fpdf.go index 9818aeb..43688dd 100644 --- a/fpdf.go +++ b/fpdf.go @@ -359,7 +359,7 @@ func (f *Fpdf) SetPageBox(t string, pb PageBox) { case "artbox": t = "ArtBox" default: - f.err = fmt.Sprintf("%s is not a valid page box type") + f.err = fmt.Errorf("%s is not a valid page box type", t) return } -- cgit v1.2.1-24-ge1ad From 7c87ab704eb556bd5ec58197619c9f572d63486b Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 10 Nov 2018 11:03:08 -0500 Subject: Demonstrate page boxes --- fpdf_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/fpdf_test.go b/fpdf_test.go index 4774ec6..3618fc6 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2189,3 +2189,30 @@ func ExampleNewGrid() { // Output: // Successfully generated pdf/Fpdf_Grid.pdf } + +func pagebox(pdf *gofpdf.Fpdf, boxstr string, x, y, wd, ht float64) { + pdf.SetPageBox(boxstr, gofpdf.PageBox{gofpdf.SizeType{Wd: wd, Ht: ht}, gofpdf.PointType{X: x, Y: y}}) +} + +// This example demonstrates the use of a page box +func ExamplePageBox() { + const ( + wd = 210 + ht = 297 + boxmargin = 5 + ) + pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm + pagebox(pdf, "bleed", 0, 0, wd, ht) + pagebox(pdf, "trim", boxmargin, boxmargin, wd-2*boxmargin, ht-2*boxmargin) + pdf.SetFont("Arial", "", 12) + pdf.SetDrawColor(40, 40, 40) + pdf.AddPage() + pdf.Rect(0, 0, wd, ht, "D") + pdf.Line(0, 0, wd, ht) + pdf.Line(0, ht, wd, 0) + fileStr := example.Filename("Fpdf_PageBox") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_PageBox.pdf +} -- cgit v1.2.1-24-ge1ad From e86946141846a08ffb531a1f2c9625282cbc335a Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 10 Nov 2018 14:07:38 -0500 Subject: Simplify example and display output from 'pdfinfo -box' --- fpdf_test.go | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/fpdf_test.go b/fpdf_test.go index 3618fc6..036fe97 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -2196,20 +2196,37 @@ func pagebox(pdf *gofpdf.Fpdf, boxstr string, x, y, wd, ht float64) { // This example demonstrates the use of a page box func ExamplePageBox() { + // pdfinfo (from http://www.xpdfreader.com) reports the following for this example: + // ~ pdfinfo -box pdf/Fpdf_PageBox.pdf + // Producer: FPDF 1.7 + // CreationDate: Sat Jan 1 00:00:00 2000 + // Tagged: no + // Form: none + // Pages: 1 + // Encrypted: no + // Page size: 493.23 x 739.85 pts (rotated 0 degrees) + // MediaBox: 0.00 0.00 595.28 841.89 + // CropBox: 51.02 51.02 544.25 790.87 + // BleedBox: 51.02 51.02 544.25 790.87 + // TrimBox: 51.02 51.02 544.25 790.87 + // ArtBox: 51.02 51.02 544.25 790.87 + // File size: 1053 bytes + // Optimized: no + // PDF version: 1.3 const ( wd = 210 ht = 297 - boxmargin = 5 + fontsize = 6 + boxmargin = 3 * fontsize ) pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm - pagebox(pdf, "bleed", 0, 0, wd, ht) - pagebox(pdf, "trim", boxmargin, boxmargin, wd-2*boxmargin, ht-2*boxmargin) - pdf.SetFont("Arial", "", 12) - pdf.SetDrawColor(40, 40, 40) + pagebox(pdf, "crop", boxmargin, boxmargin, wd-2*boxmargin, ht-2*boxmargin) + pdf.SetFont("Arial", "", pdf.UnitToPointConvert(fontsize)) pdf.AddPage() - pdf.Rect(0, 0, wd, ht, "D") - pdf.Line(0, 0, wd, ht) - pdf.Line(0, ht, wd, 0) + pdf.MoveTo(fontsize, fontsize) + pdf.Write(fontsize, "This will be cropped from printed output") + pdf.MoveTo(boxmargin+fontsize, boxmargin+fontsize) + pdf.Write(fontsize, "This will be displayed in cropped output") fileStr := example.Filename("Fpdf_PageBox") err := pdf.OutputFileAndClose(fileStr) example.Summary(err, fileStr) -- cgit v1.2.1-24-ge1ad