summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Jung <kurt.w.jung@gmail.com>2015-07-06 17:21:32 -0400
committerKurt Jung <kurt.w.jung@gmail.com>2015-07-06 17:21:32 -0400
commit8cb193ab3b092002fea2d87dd180d0772cf32fe0 (patch)
treecfe55b858f720d5e313d5a09e98e2221ee59fdba
parentbc7edcc6a96f0232c6bb4f358bde13e146842242 (diff)
parent19ef571c9c8f0ea66120545e7280c264829cd66b (diff)
Stani Michiels' full support for fill styles and excellent tutorial to
demonstrate it.
-rw-r--r--fpdf.go32
-rw-r--r--fpdf_test.go76
2 files changed, 103 insertions, 5 deletions
diff --git a/fpdf.go b/fpdf.go
index ea4b384..55bb848 100644
--- a/fpdf.go
+++ b/fpdf.go
@@ -858,14 +858,26 @@ func (f *Fpdf) Line(x1, y1, x2, y2 float64) {
f.outf("%.2f %.2f m %.2f %.2f l S", x1*f.k, (f.h-y1)*f.k, x2*f.k, (f.h-y2)*f.k)
}
+// fillDrawOp corrects path painting operators
func fillDrawOp(styleStr string) (opStr string) {
switch strings.ToUpper(styleStr) {
+ case "", "D":
+ // Stroke the path.
+ opStr = "S"
case "F":
+ // fill the path, using the nonzero winding number rule
opStr = "f"
+ case "F*":
+ // fill the path, using the even-odd rule
+ opStr = "f*"
case "FD", "DF":
+ // fill and then stroke the path, using the nonzero winding number rule
opStr = "B"
+ case "FD*", "DF*":
+ // fill and then stroke the path, using the even-odd rule
+ opStr = "B*"
default:
- opStr = "S"
+ opStr = styleStr
}
return
}
@@ -931,7 +943,7 @@ func (f *Fpdf) Polygon(points []PointType, styleStr string) {
}
}
f.outf("%.5f %.5f l ", points[0].X*f.k, (f.h-points[0].Y)*f.k)
- f.outf(fillDrawOp(styleStr))
+ f.DrawPath(styleStr)
}
}
@@ -966,7 +978,7 @@ func (f *Fpdf) Beziergon(points []PointType, styleStr string) {
points = points[3:]
}
- f.outf(fillDrawOp(styleStr))
+ f.DrawPath(styleStr)
}
// Outputs current point
@@ -3507,8 +3519,18 @@ func (f *Fpdf) ClosePath() {
// DrawPath actually draws the path on the page.
//
// 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, line width, and cap style centered on the
+// outlined and filled. An empty string will be replaced with "D".
+// Path-painting operators as defined in the PDF specification are also
+// allowed: "S" (Stroke the path), "s" (Close and stroke the path),
+// "f" (fill the path, using the nonzero winding number), "f*"
+// (Fill the path, using the even-odd rule), "B" (Fill and then stroke
+// the path, using the nonzero winding number rule), "B*" (Fill and
+// then stroke the path, using the even-odd rule), "b" (Close, fill,
+// and then stroke the path, using the nonzero winding number rule) and
+// "b*" (Close, fill, and then stroke the path, using the even-odd
+// rule).
+// Drawing uses the current draw color, line width, and cap style
+// centered on the
// path. Filling uses the current fill color.
//
// See tutorial 30 for an example of this function.
diff --git a/fpdf_test.go b/fpdf_test.go
index 9ac1e18..3872331 100644
--- a/fpdf_test.go
+++ b/fpdf_test.go
@@ -26,6 +26,7 @@ import (
"net/http"
"os"
"path/filepath"
+ "strconv"
"strings"
"github.com/jung-kurt/gofpdf"
@@ -1516,3 +1517,78 @@ func ExampleFpdf_tutorial31() {
// Output:
// Successfully generated pdf/tutorial31.pdf
}
+
+// This example demonstrates the Path Drawing functions, such as: MoveTo,
+// LineTo, CurveTo, ..., ClosePath and DrawPath.
+func ExampleFpdf_tutorial32() {
+ pdf := gofpdf.New("P", "mm", "A4", "")
+ pdf.SetDrawColor(0xff, 0x00, 0x00)
+ pdf.SetFillColor(0x99, 0x99, 0x99)
+ pdf.SetFont("Helvetica", "", 15)
+ pdf.AddPage()
+ pdf.SetAlpha(1, "Multiply")
+ var (
+ polygon = func(cx, cy, r, n, dir float64) {
+ da := 2 * math.Pi / n
+ pdf.MoveTo(cx+r, cy)
+ pdf.Text(cx+r, cy, "0")
+ i := 1
+ for a := da; a < 2*math.Pi; a += da {
+ x, y := cx+r*math.Cos(dir*a), cy+r*math.Sin(dir*a)
+ pdf.LineTo(x, y)
+ pdf.Text(x, y, strconv.Itoa(i))
+ i++
+ }
+ pdf.ClosePath()
+ }
+ polygons = func(cx, cy, r, n, dir float64) {
+ d := 1.0
+ for rf := r; rf > 0; rf -= 10 {
+ polygon(cx, cy, rf, n, d)
+ d *= dir
+ }
+ }
+ star = func(cx, cy, r, n float64) {
+ da := 4 * math.Pi / n
+ pdf.MoveTo(cx+r, cy)
+ for a := da; a < 4*math.Pi+da; a += da {
+ x, y := cx+r*math.Cos(a), cy+r*math.Sin(a)
+ pdf.LineTo(x, y)
+ }
+ pdf.ClosePath()
+ }
+ )
+ // triangle
+ polygons(55, 45, 40, 3, 1)
+ pdf.DrawPath("B")
+ pdf.Text(15, 95, "B (same direction, non zero winding)")
+
+ // square
+ polygons(155, 45, 40, 4, 1)
+ pdf.DrawPath("B*")
+ pdf.Text(115, 95, "B* (same direction, even odd)")
+
+ // pentagon
+ polygons(55, 145, 40, 5, -1)
+ pdf.DrawPath("B")
+ pdf.Text(15, 195, "B (different direction, non zero winding)")
+
+ // hexagon
+ polygons(155, 145, 40, 6, -1)
+ pdf.DrawPath("B*")
+ pdf.Text(115, 195, "B* (different direction, even odd)")
+
+ // star
+ star(55, 245, 40, 5)
+ pdf.DrawPath("B")
+ pdf.Text(15, 290, "B (non zero winding)")
+
+ // star
+ star(155, 245, 40, 5)
+ pdf.DrawPath("B*")
+ pdf.Text(115, 290, "B* (even odd)")
+
+ pdf.OutputAndClose(docWriter(pdf, 32))
+ // Output:
+ // Successfully generated pdf/tutorial32.pdf
+}