From f9941ced55be6fca307fec19bad2d81bd4fb7831 Mon Sep 17 00:00:00 2001 From: Kurt Jung Date: Tue, 10 Sep 2013 15:30:35 -0400 Subject: =?UTF-8?q?Transformation=20functionality=20adapted=20from=20Morit?= =?UTF-8?q?z=20Wagner=20and=20Andreas=20W=C3=BCrmser.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- def.go | 1 + doc.go | 6 ++- fpdf.go | 4 +- fpdf_test.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/def.go b/def.go index ed37f11..45ec09a 100644 --- a/def.go +++ b/def.go @@ -171,6 +171,7 @@ type Fpdf struct { blendMap map[string]int // map into blendList 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 } diff --git a/doc.go b/doc.go index 85f34d4..6f960d9 100644 --- a/doc.go +++ b/doc.go @@ -23,7 +23,9 @@ directly from it. Drawing support is adapted from the FPDF geometric figures script by David Hernández Sanz. Transparency support is adapted from the FPDF transparency script by Martin Hall-May. Support for gradients and clipping is adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is -adapted from Olivier Plathey by Manuel Cornes. +adapted from Olivier Plathey by Manuel Cornes. Support for transformations is +adapted from the FPDF transformation script by Moritz Wagner and Andreas +Würmser. The FPDF website is http://www.fpdf.org/. @@ -51,6 +53,8 @@ Features • Drawing support (lines, Bézier curves, arcs, ellipses) +• Transformation support (rotation, scaling, skewing, translation, mirroring) + • Clipping gofpdf has no dependencies other than the Go standard library. All tests pass diff --git a/fpdf.go b/fpdf.go index 50d1763..51dfad1 100644 --- a/fpdf.go +++ b/fpdf.go @@ -428,6 +428,8 @@ func (f *Fpdf) Close() { if f.err == nil { if f.clipNest > 0 { f.err = fmt.Errorf("Clip procedure must be explicitly ended") + } else if f.transformNest > 0 { + f.err = fmt.Errorf("Transformation procedure must be explicitly ended") } } if f.err != nil { @@ -1148,7 +1150,7 @@ func (f *Fpdf) ClipEnd() { f.clipNest-- f.out("Q") } else { - f.err = fmt.Errorf("Error attempting to end clip operation") + f.err = fmt.Errorf("Error attempting to end clip operation out of sequence") } } } diff --git a/fpdf_test.go b/fpdf_test.go index fad67bc..ccdf1bf 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -964,3 +964,122 @@ func ExampleFpdf_tutorial16() { // Output: // Successfully generated pdf/tutorial16.pdf } + +// Transformation test adapted from an example script by Moritz Wagner and +// Andreas Würmser. +func ExampleFpdf_tutorial17() { + const ( + light = 200 + dark = 0 + ) + var refX, refY float64 + var refStr string + pdf := gofpdf.New("P", "mm", "A4", FONT_DIR) + pdf.AddPage() + color := func(val int) { + pdf.SetDrawColor(val, val, val) + pdf.SetTextColor(val, val, val) + } + reference := func(str string, x, y float64, val int) { + color(val) + pdf.Rect(x, y, 40, 10, "D") + pdf.Text(x, y-1, str) + } + refDraw := func(str string, x, y float64) { + refStr = str + refX = x + refY = y + reference(str, x, y, light) + } + refDupe := func() { + reference(refStr, refX, refY, dark) + } + + titleStr := "Transformations" + titlePt := 36.0 + titleHt := titlePt * 25.4 / 72.0 + pdf.SetFont("Helvetica", "", titlePt) + titleWd := pdf.GetStringWidth(titleStr) + titleX := (210 - titleWd) / 2 + pdf.Text(titleX, 10+titleHt, titleStr) + pdf.TransformBegin() + pdf.TransformMirrorVertical(10 + titleHt + 0.5) + pdf.ClipText(titleX, 10+titleHt, titleStr, false) + // Remember that the transform will mirror the gradient box too + pdf.LinearGradient(titleX, 10, titleWd, titleHt+4, 120, 120, 120, 255, 255, 255, 0, 0, 0, 0.6) + pdf.ClipEnd() + pdf.TransformEnd() + + pdf.SetFont("Helvetica", "", 12) + + // Scale by 150% centered by lower left corner of the rectangle + refDraw("Scale", 50, 60) + pdf.TransformBegin() + pdf.TransformScaleXY(150, 50, 70) + refDupe() + pdf.TransformEnd() + + // Translate 7 to the right, 5 to the bottom + refDraw("Translate", 125, 60) + pdf.TransformBegin() + pdf.TransformTranslate(7, 5) + refDupe() + pdf.TransformEnd() + + // Rotate 20 degrees counter-clockwise centered by the lower left corner of + // the rectangle + refDraw("Rotate", 50, 110) + pdf.TransformBegin() + pdf.TransformRotate(20, 50, 120) + refDupe() + pdf.TransformEnd() + + // Skew 30 degrees along the x-axis centered by the lower left corner of the + // rectangle + refDraw("Skew", 125, 110) + pdf.TransformBegin() + pdf.TransformSkewX(30, 125, 110) + refDupe() + pdf.TransformEnd() + + // Mirror horizontally with axis of reflection at left side of the rectangle + refDraw("Mirror horizontal", 50, 160) + pdf.TransformBegin() + pdf.TransformMirrorHorizontal(50) + refDupe() + pdf.TransformEnd() + + // Mirror vertically with axis of reflection at bottom side of the rectangle + refDraw("Mirror vertical", 125, 160) + pdf.TransformBegin() + pdf.TransformMirrorVertical(170) + refDupe() + pdf.TransformEnd() + + // Reflect against a point at the lower left point of rectangle + refDraw("Mirror point", 50, 210) + pdf.TransformBegin() + pdf.TransformMirrorPoint(50, 220) + refDupe() + pdf.TransformEnd() + + // Mirror against a straight line described by a point and an angle + angle := -20.0 + px := 120.0 + py := 220.0 + refDraw("Mirror line", 125, 210) + pdf.TransformBegin() + pdf.TransformRotate(angle, px, py) + pdf.Line(px-1, py-1, px+1, py+1) + pdf.Line(px-1, py+1, px+1, py-1) + pdf.Line(px-5, py, px+60, py) + pdf.TransformEnd() + pdf.TransformBegin() + pdf.TransformMirrorLine(angle, px, py) + refDupe() + pdf.TransformEnd() + + pdf.OutputAndClose(docWriter(pdf, 17)) + // Output: + // Successfully generated pdf/tutorial17.pdf +} -- cgit v1.2.1-24-ge1ad