gopdf/fpdftrans.go

214 lines
7.1 KiB
Go

package gofpdf
import (
"fmt"
"math"
)
// Routines in this file are translated from the work of Moritz Wagner and
// Andreas Würmser.
// TransformMatrix is used for generalized transformations of text, drawings
// and images.
type TransformMatrix struct {
A, B, C, D, E, F float64
}
// TransformBegin sets 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.
func (f *Fpdf) TransformBegin() {
f.transformNest++
f.out("q")
}
// TransformScaleX scales the width of the following text, drawings and images.
// scaleWd is the percentage scaling factor. (x, y) is center of scaling.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformScaleX(scaleWd, x, y float64) {
f.TransformScale(scaleWd, 100, x, y)
}
// TransformScaleY scales the height of the following text, drawings and
// images. scaleHt is the percentage scaling factor. (x, y) is center of
// scaling.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformScaleY(scaleHt, x, y float64) {
f.TransformScale(100, scaleHt, x, y)
}
// TransformScaleXY uniformly scales 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.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformScaleXY(s, x, y float64) {
f.TransformScale(s, s, x, y)
}
// TransformScale generally scales the following text, drawings and images.
// scaleWd and scaleHt are the percentage scaling factors for width and height.
// (x, y) is center of scaling.
//
// The TransformBegin() example demonstrates this method.
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)})
}
// TransformMirrorHorizontal horizontally mirrors the following text, drawings
// and images. x is the axis of reflection.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformMirrorHorizontal(x float64) {
f.TransformScale(-100, 100, x, f.y)
}
// TransformMirrorVertical vertically mirrors the following text, drawings and
// images. y is the axis of reflection.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformMirrorVertical(y float64) {
f.TransformScale(100, -100, f.x, y)
}
// TransformMirrorPoint symmetrically mirrors the following text, drawings and
// images on the point specified by (x, y).
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformMirrorPoint(x, y float64) {
f.TransformScale(-100, -100, x, y)
}
// TransformMirrorLine symmetrically mirrors 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.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformMirrorLine(angle, x, y float64) {
f.TransformScale(-100, 100, x, y)
f.TransformRotate(-2*(angle-90), x, y)
}
// TransformTranslateX moves the following text, drawings and images
// horizontally by the amount specified by tx.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformTranslateX(tx float64) {
f.TransformTranslate(tx, 0)
}
// TransformTranslateY moves the following text, drawings and images vertically
// by the amount specified by ty.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformTranslateY(ty float64) {
f.TransformTranslate(0, ty)
}
// TransformTranslate moves the following text, drawings and images
// horizontally and vertically by the amounts specified by tx and ty.
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformTranslate(tx, ty float64) {
f.Transform(TransformMatrix{1, 0, 0, 1, tx * f.k, -ty * f.k})
}
// TransformRotate rotates 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.
//
// The TransformBegin() example demonstrates this method.
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)
}
// TransformSkewX horizontally skews 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).
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformSkewX(angleX, x, y float64) {
f.TransformSkew(angleX, 0, x, y)
}
// TransformSkewY vertically skews 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 top).
//
// The TransformBegin() example demonstrates this method.
func (f *Fpdf) TransformSkewY(angleY, x, y float64) {
f.TransformSkew(0, angleY, x, y)
}
// TransformSkew generally skews 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 top).
//
// The TransformBegin() example demonstrates this method.
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)
}
// Transform generally transforms 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("%.5f %.5f %.5f %.5f %.5f %.5f 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")
}
}
// TransformEnd applies a transformation that was begun with a call to TransformBegin().
//
// The TransformBegin() example demonstrates this method.
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")
}
}