summaryrefslogtreecommitdiff
path: root/fpdftrans.go
diff options
context:
space:
mode:
Diffstat (limited to 'fpdftrans.go')
-rw-r--r--fpdftrans.go178
1 files changed, 178 insertions, 0 deletions
diff --git a/fpdftrans.go b/fpdftrans.go
new file mode 100644
index 0000000..8c4e48c
--- /dev/null
+++ b/fpdftrans.go
@@ -0,0 +1,178 @@
+package gofpdf
+
+import (
+ "fmt"
+ "math"
+)
+
+// Routines in this file are translated from the work of Moritz Wagner and
+// Andreas Würmser.
+
+// The matrix used for generalized transformations of text, drawings and images.
+type TransformMatrix struct {
+ a, b, c, d, e, f float64
+}
+
+// Set up a transformation context for subsequent text, drawings and images.
+// The typical usage is to immediately follow a call to this method with a call
+// to one or more of the transformation methods such as TransformScale(),
+// TransformSkew(), etc. This is followed by text, drawing or image output and
+// finally a call to TransformEnd(). All transformation contexts must be
+// properly ended prior to outputting the document.
+//
+// See tutorial 17 for a transformation examples.
+func (f *Fpdf) TransformBegin() {
+ f.transformNest++
+ f.out("q")
+}
+
+// Scale the width of the following text, drawings and images. scaleWd is the
+// percentage scaling factor. (x, y) is center of scaling.
+func (f *Fpdf) TransformScaleX(scaleWd, x, y float64) {
+ f.TransformScale(scaleWd, 100, x, y)
+}
+
+// Scale the height of the following text, drawings and images. scaleHt is the
+// percentage scaling factor. (x, y) is center of scaling.
+func (f *Fpdf) TransformScaleY(scaleHt, x, y float64) {
+ f.TransformScale(100, scaleHt, x, y)
+}
+
+// Uniformly scale the width and height of the following text, drawings and
+// images. s is the percentage scaling factor for both width and height. (x, y)
+// is center of scaling.
+func (f *Fpdf) TransformScaleXY(s, x, y float64) {
+ f.TransformScale(s, s, x, y)
+}
+
+// Generally scale the following text, drawings and images. scaleWd and scaleHt
+// are the percentage scaling factors for width and height. (x, y) is center of
+// scaling.
+func (f *Fpdf) TransformScale(scaleWd, scaleHt, x, y float64) {
+ if scaleWd == 0 || scaleHt == 0 {
+ f.err = fmt.Errorf("Scale factor cannot be zero")
+ return
+ }
+ y = (f.h - y) * f.k
+ x *= f.k
+ scaleWd /= 100
+ scaleHt /= 100
+ f.Transform(TransformMatrix{scaleWd, 0, 0, scaleHt, x * (1 - scaleWd), y * (1 - scaleHt)})
+}
+
+// Horizontally mirror the following text, drawings and images. x is the axis
+// of reflection.
+func (f *Fpdf) TransformMirrorHorizontal(x float64) {
+ f.TransformScale(-100, 100, x, f.y)
+}
+
+// Vertically mirror the following text, drawings and images. y is the axis
+// of reflection.
+func (f *Fpdf) TransformMirrorVertical(y float64) {
+ f.TransformScale(100, -100, f.x, y)
+}
+
+// Symmetrically mirror the following text, drawings and images on the point
+// specified by (x, y).
+func (f *Fpdf) TransformMirrorPoint(x, y float64) {
+ f.TransformScale(-100, -100, x, y)
+}
+
+// Symmetrically mirror the following text, drawings and images on the line
+// defined by angle and the point (x, y). angles is specified in degrees and
+// measured counter-clockwise from the 3 o'clock position.
+func (f *Fpdf) TransformMirrorLine(angle, x, y float64) {
+ f.TransformScale(-100, 100, x, y)
+ f.TransformRotate(-2*(angle-90), x, y)
+}
+
+// Move the following text, drawings and images horizontally by the amount
+// specified by tx.
+func (f *Fpdf) TransformTranslateX(tx float64) {
+ f.TransformTranslate(tx, 0)
+}
+
+// Move the following text, drawings and images vertically by the amount
+// specified by ty.
+func (f *Fpdf) TransformTranslateY(ty float64) {
+ f.TransformTranslate(0, ty)
+}
+
+// Move the following text, drawings and images horizontally and vertically by
+// the amounts specified by tx and ty.
+func (f *Fpdf) TransformTranslate(tx, ty float64) {
+ f.Transform(TransformMatrix{1, 0, 0, 1, tx - f.k, -ty * f.k})
+}
+
+// Rotate the following text, drawings and images around the center point (x,
+// y). angle is specified in degrees and measured counter-clockwise from the 3
+// o'clock position.
+func (f *Fpdf) TransformRotate(angle, x, y float64) {
+ y = (f.h - y) * f.k
+ x *= f.k
+ angle = angle * math.Pi / 180
+ var tm TransformMatrix
+ tm.a = math.Cos(angle)
+ tm.b = math.Sin(angle)
+ tm.c = -tm.b
+ tm.d = tm.a
+ tm.e = x + tm.b*y - tm.a*x
+ tm.f = y - tm.a*y - tm.b*x
+ f.Transform(tm)
+}
+
+// Horizontally skew the following text, drawings and images keeping the point
+// (x, y) stationary. angleX ranges from -90 degrees (skew to the left) to 90
+// degrees (skew to the right).
+func (f *Fpdf) TransformSkewX(angleX, x, y float64) {
+ f.TransformSkew(angleX, 0, x, y)
+}
+
+// Vertically skew the following text, drawings and images keeping the point
+// (x, y) stationary. angleY ranges from -90 degrees (skew to the bottom) to 90
+// degrees (skew to the right).
+func (f *Fpdf) TransformSkewY(angleY, x, y float64) {
+ f.TransformSkew(0, angleY, x, y)
+}
+
+// Generally skew the following text, drawings and images keeping the point (x,
+// y) stationary. angleX ranges from -90 degrees (skew to the left) to 90
+// degrees (skew to the right). angleY ranges from -90 degrees (skew to the
+// bottom) to 90 degrees (skew to the right).
+func (f *Fpdf) TransformSkew(angleX, angleY, x, y float64) {
+ if angleX <= -90 || angleX >= 90 || angleY <= -90 || angleY >= 90 {
+ f.err = fmt.Errorf("Skew values must be between -90° and 90°")
+ return
+ }
+ x *= f.k
+ y = (f.h - y) * f.k
+ var tm TransformMatrix
+ tm.a = 1
+ tm.b = math.Tan(angleY * math.Pi / 180)
+ tm.c = math.Tan(angleX * math.Pi / 180)
+ tm.d = 1
+ tm.e = -tm.c * y
+ tm.f = -tm.b * x
+ f.Transform(tm)
+}
+
+// Generally transform the following text, drawings and images according to the
+// specified matrix. It is typically easier to use the various methods such as
+// TransformRotate() and TransformMirrorVertical() instead.
+func (f *Fpdf) Transform(tm TransformMatrix) {
+ if f.transformNest > 0 {
+ f.outf("%.3f %.3f %.3f %.3f %.3f %.3f cm", tm.a, tm.b, tm.c, tm.d, tm.e, tm.f)
+ } else if f.err == nil {
+ f.err = fmt.Errorf("Transformation context is not active")
+ }
+}
+
+// Apply a transformation that was begun with a call to TransformBegin().
+func (f *Fpdf) TransformEnd() {
+ if f.transformNest > 0 {
+ f.transformNest--
+ f.out("Q")
+ } else {
+ f.err = fmt.Errorf("Error attempting to end transformation operation out of sequence")
+ }
+}