summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--doc.go3
-rw-r--r--doc/document.md1
-rw-r--r--fpdf.go52
-rw-r--r--fpdf_test.go49
5 files changed, 106 insertions, 2 deletions
diff --git a/README.md b/README.md
index 811bbc3..38ef38d 100644
--- a/README.md
+++ b/README.md
@@ -248,7 +248,8 @@ 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. Dave Barnes added
-support for imported objects and templates.
+support for imported objects and templates. Brigham Thompson added
+support for rounded rectangles.
## Roadmap
diff --git a/doc.go b/doc.go
index 6ad0461..b3721e7 100644
--- a/doc.go
+++ b/doc.go
@@ -256,7 +256,8 @@ 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. Dave Barnes added
-support for imported objects and templates.
+support for imported objects and templates. Brigham Thompson added
+support for rounded rectangles.
Roadmap
diff --git a/doc/document.md b/doc/document.md
index fa544af..d7d84cd 100644
--- a/doc/document.md
+++ b/doc/document.md
@@ -228,6 +228,7 @@ 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. Dave Barnes added support for imported objects and templates.
+Brigham Thompson added support for rounded rectangles.
## Roadmap
diff --git a/fpdf.go b/fpdf.go
index ca48fb5..28f69cf 100644
--- a/fpdf.go
+++ b/fpdf.go
@@ -1103,6 +1103,58 @@ func (f *Fpdf) Rect(x, y, w, h float64, styleStr string) {
f.outf("%.2f %.2f %.2f %.2f re %s", x*f.k, (f.h-y)*f.k, w*f.k, -h*f.k, fillDrawOp(styleStr))
}
+// RoundedRect outputs a rectangle of width w and height h with the upper left
+// corner positioned at point (x, y). It can be drawn (border only), filled
+// (with no border) or both. styleStr can be "F" for filled, "D" for outlined
+// only, or "DF" or "FD" for outlined and filled. An empty string will be
+// replaced with "D". Drawing uses the current draw color and line width
+// centered on the rectangle's perimeter. Filling uses the current fill color.
+// The rounded corners of the rectangle are specified by radius r. corners is a
+// string that includes "1" to round the upper left corner, "2" to round the
+// upper right corner, "3" to round the lower right corner, and "4" to round
+// the lower left corner. The RoundedRect example demonstrates this method.
+func (f *Fpdf) RoundedRect(x, y, w, h, r float64, corners string, stylestr string) {
+ // This routine was adapted by Brigham Thompson from a script by Christophe Prugnaud
+ k := f.k
+ hp := f.h
+ myArc := r * (4.0 / 3.0) * (math.Sqrt2 - 1.0)
+ f.outf("q %.5f %.5f m", (x+r)*k, (hp-y)*k)
+ xc := x + w - r
+ yc := y + r
+ f.outf("%.5f %.5f l", xc*k, (hp-y)*k)
+ if strings.Contains(corners, "2") == false {
+ f.outf("%.5f %.5f l", (x+w)*k, (hp-y)*k)
+ } else {
+ f.clipArc(xc+myArc, yc-r, xc+r, yc-myArc, xc+r, yc)
+ }
+ xc = x + w - r
+ yc = y + h - r
+ f.outf("%.5f %.5f l", (x+w)*k, (hp-yc)*k)
+ if strings.Contains(corners, "3") == false {
+ f.outf("%.5f %.5f l", (x+w)*k, (hp-(y+h))*k)
+ } else {
+ f.clipArc(xc+r, yc+myArc, xc+myArc, yc+r, xc, yc+r)
+ }
+ xc = x + r
+ yc = y + h - r
+ f.outf("%.5f %.5f l", xc*k, (hp-(y+h))*k)
+ if strings.Contains(corners, "4") == false {
+ f.outf("%.5f %.5f l", x*k, (hp-(y+h))*k)
+ } else {
+ f.clipArc(xc-myArc, yc+r, xc-r, yc+myArc, xc-r, yc)
+ }
+ xc = x + r
+ yc = y + r
+ f.outf("%.5f %.5f l", x*k, (hp-yc)*k)
+ if strings.Contains(corners, "1") == false {
+ f.outf("%.5f %.5f l", x*k, (hp-y)*k)
+ f.outf("%.5f %.5f l", (x+r)*k, (hp-y)*k)
+ } else {
+ f.clipArc(xc-r, yc-myArc, xc-myArc, yc-r, xc, yc-r)
+ }
+ f.out(fillDrawOp(stylestr))
+}
+
// Circle draws a circle centered on point (x, y) with radius r.
//
// styleStr can be "F" for filled, "D" for outlined only, or "DF" or "FD" for
diff --git a/fpdf_test.go b/fpdf_test.go
index 63c28c5..c6020f3 100644
--- a/fpdf_test.go
+++ b/fpdf_test.go
@@ -2639,3 +2639,52 @@ func ExampleUTF8CutFont() {
// Output:
// Successfully generated pdf/Fpdf_UTF8CutFont.pdf
}
+
+func ExampleFpdf_RoundedRect() {
+ const (
+ wd = 40.0
+ hgap = 10.0
+ radius = 10.0
+ ht = 60.0
+ vgap = 10.0
+ )
+ corner := func(b1, b2, b3, b4 bool) (cstr string) {
+ if b1 {
+ cstr = "1"
+ }
+ if b2 {
+ cstr += "2"
+ }
+ if b3 {
+ cstr += "3"
+ }
+ if b4 {
+ cstr += "4"
+ }
+ return
+ }
+ pdf := gofpdf.New("P", "mm", "A4", "") // 210 x 297
+ pdf.AddPage()
+ pdf.SetLineWidth(0.5)
+ y := vgap
+ r := 40
+ g := 30
+ b := 20
+ for row := 0; row < 4; row++ {
+ x := hgap
+ for col := 0; col < 4; col++ {
+ pdf.SetFillColor(r, g, b)
+ pdf.RoundedRect(x, y, wd, ht, radius, corner(row&1 == 1, row&2 == 2, col&1 == 1, col&2 == 2), "FD")
+ r += 8
+ g += 10
+ b += 12
+ x += wd + hgap
+ }
+ y += ht + vgap
+ }
+ fileStr := example.Filename("Fpdf_RoundedRect")
+ err := pdf.OutputFileAndClose(fileStr)
+ example.Summary(err, fileStr)
+ // Output:
+ // Successfully generated pdf/Fpdf_RoundedRect.pdf
+}