github.com/phpdave11/gofpdf@v1.4.2/fpdftrans.go (about)

     1  package gofpdf
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  )
     7  
     8  // Routines in this file are translated from the work of Moritz Wagner and
     9  // Andreas Würmser.
    10  
    11  // TransformMatrix is used for generalized transformations of text, drawings
    12  // and images.
    13  type TransformMatrix struct {
    14  	A, B, C, D, E, F float64
    15  }
    16  
    17  // TransformBegin sets up a transformation context for subsequent text,
    18  // drawings and images. The typical usage is to immediately follow a call to
    19  // this method with a call to one or more of the transformation methods such as
    20  // TransformScale(), TransformSkew(), etc. This is followed by text, drawing or
    21  // image output and finally a call to TransformEnd(). All transformation
    22  // contexts must be properly ended prior to outputting the document.
    23  func (f *Fpdf) TransformBegin() {
    24  	f.transformNest++
    25  	f.out("q")
    26  }
    27  
    28  // TransformScaleX scales the width of the following text, drawings and images.
    29  // scaleWd is the percentage scaling factor. (x, y) is center of scaling.
    30  //
    31  // The TransformBegin() example demonstrates this method.
    32  func (f *Fpdf) TransformScaleX(scaleWd, x, y float64) {
    33  	f.TransformScale(scaleWd, 100, x, y)
    34  }
    35  
    36  // TransformScaleY scales the height of the following text, drawings and
    37  // images. scaleHt is the percentage scaling factor. (x, y) is center of
    38  // scaling.
    39  //
    40  // The TransformBegin() example demonstrates this method.
    41  func (f *Fpdf) TransformScaleY(scaleHt, x, y float64) {
    42  	f.TransformScale(100, scaleHt, x, y)
    43  }
    44  
    45  // TransformScaleXY uniformly scales the width and height of the following
    46  // text, drawings and images. s is the percentage scaling factor for both width
    47  // and height. (x, y) is center of scaling.
    48  //
    49  // The TransformBegin() example demonstrates this method.
    50  func (f *Fpdf) TransformScaleXY(s, x, y float64) {
    51  	f.TransformScale(s, s, x, y)
    52  }
    53  
    54  // TransformScale generally scales the following text, drawings and images.
    55  // scaleWd and scaleHt are the percentage scaling factors for width and height.
    56  // (x, y) is center of scaling.
    57  //
    58  // The TransformBegin() example demonstrates this method.
    59  func (f *Fpdf) TransformScale(scaleWd, scaleHt, x, y float64) {
    60  	if scaleWd == 0 || scaleHt == 0 {
    61  		f.err = fmt.Errorf("scale factor cannot be zero")
    62  		return
    63  	}
    64  	y = (f.h - y) * f.k
    65  	x *= f.k
    66  	scaleWd /= 100
    67  	scaleHt /= 100
    68  	f.Transform(TransformMatrix{scaleWd, 0, 0,
    69  		scaleHt, x * (1 - scaleWd), y * (1 - scaleHt)})
    70  }
    71  
    72  // TransformMirrorHorizontal horizontally mirrors the following text, drawings
    73  // and images. x is the axis of reflection.
    74  //
    75  // The TransformBegin() example demonstrates this method.
    76  func (f *Fpdf) TransformMirrorHorizontal(x float64) {
    77  	f.TransformScale(-100, 100, x, f.y)
    78  }
    79  
    80  // TransformMirrorVertical vertically mirrors the following text, drawings and
    81  // images. y is the axis of reflection.
    82  //
    83  // The TransformBegin() example demonstrates this method.
    84  func (f *Fpdf) TransformMirrorVertical(y float64) {
    85  	f.TransformScale(100, -100, f.x, y)
    86  }
    87  
    88  // TransformMirrorPoint symmetrically mirrors the following text, drawings and
    89  // images on the point specified by (x, y).
    90  //
    91  // The TransformBegin() example demonstrates this method.
    92  func (f *Fpdf) TransformMirrorPoint(x, y float64) {
    93  	f.TransformScale(-100, -100, x, y)
    94  }
    95  
    96  // TransformMirrorLine symmetrically mirrors the following text, drawings and
    97  // images on the line defined by angle and the point (x, y). angles is
    98  // specified in degrees and measured counter-clockwise from the 3 o'clock
    99  // position.
   100  //
   101  // The TransformBegin() example demonstrates this method.
   102  func (f *Fpdf) TransformMirrorLine(angle, x, y float64) {
   103  	f.TransformScale(-100, 100, x, y)
   104  	f.TransformRotate(-2*(angle-90), x, y)
   105  }
   106  
   107  // TransformTranslateX moves the following text, drawings and images
   108  // horizontally by the amount specified by tx.
   109  //
   110  // The TransformBegin() example demonstrates this method.
   111  func (f *Fpdf) TransformTranslateX(tx float64) {
   112  	f.TransformTranslate(tx, 0)
   113  }
   114  
   115  // TransformTranslateY moves the following text, drawings and images vertically
   116  // by the amount specified by ty.
   117  //
   118  // The TransformBegin() example demonstrates this method.
   119  func (f *Fpdf) TransformTranslateY(ty float64) {
   120  	f.TransformTranslate(0, ty)
   121  }
   122  
   123  // TransformTranslate moves the following text, drawings and images
   124  // horizontally and vertically by the amounts specified by tx and ty.
   125  //
   126  // The TransformBegin() example demonstrates this method.
   127  func (f *Fpdf) TransformTranslate(tx, ty float64) {
   128  	f.Transform(TransformMatrix{1, 0, 0, 1, tx * f.k, -ty * f.k})
   129  }
   130  
   131  // TransformRotate rotates the following text, drawings and images around the
   132  // center point (x, y). angle is specified in degrees and measured
   133  // counter-clockwise from the 3 o'clock position.
   134  //
   135  // The TransformBegin() example demonstrates this method.
   136  func (f *Fpdf) TransformRotate(angle, x, y float64) {
   137  	y = (f.h - y) * f.k
   138  	x *= f.k
   139  	angle = angle * math.Pi / 180
   140  	var tm TransformMatrix
   141  	tm.A = math.Cos(angle)
   142  	tm.B = math.Sin(angle)
   143  	tm.C = -tm.B
   144  	tm.D = tm.A
   145  	tm.E = x + tm.B*y - tm.A*x
   146  	tm.F = y - tm.A*y - tm.B*x
   147  	f.Transform(tm)
   148  }
   149  
   150  // TransformSkewX horizontally skews the following text, drawings and images
   151  // keeping the point (x, y) stationary. angleX ranges from -90 degrees (skew to
   152  // the left) to 90 degrees (skew to the right).
   153  //
   154  // The TransformBegin() example demonstrates this method.
   155  func (f *Fpdf) TransformSkewX(angleX, x, y float64) {
   156  	f.TransformSkew(angleX, 0, x, y)
   157  }
   158  
   159  // TransformSkewY vertically skews the following text, drawings and images
   160  // keeping the point (x, y) stationary. angleY ranges from -90 degrees (skew to
   161  // the bottom) to 90 degrees (skew to the top).
   162  //
   163  // The TransformBegin() example demonstrates this method.
   164  func (f *Fpdf) TransformSkewY(angleY, x, y float64) {
   165  	f.TransformSkew(0, angleY, x, y)
   166  }
   167  
   168  // TransformSkew generally skews the following text, drawings and images
   169  // keeping the point (x, y) stationary. angleX ranges from -90 degrees (skew to
   170  // the left) to 90 degrees (skew to the right). angleY ranges from -90 degrees
   171  // (skew to the bottom) to 90 degrees (skew to the top).
   172  //
   173  // The TransformBegin() example demonstrates this method.
   174  func (f *Fpdf) TransformSkew(angleX, angleY, x, y float64) {
   175  	if angleX <= -90 || angleX >= 90 || angleY <= -90 || angleY >= 90 {
   176  		f.err = fmt.Errorf("skew values must be between -90° and 90°")
   177  		return
   178  	}
   179  	x *= f.k
   180  	y = (f.h - y) * f.k
   181  	var tm TransformMatrix
   182  	tm.A = 1
   183  	tm.B = math.Tan(angleY * math.Pi / 180)
   184  	tm.C = math.Tan(angleX * math.Pi / 180)
   185  	tm.D = 1
   186  	tm.E = -tm.C * y
   187  	tm.F = -tm.B * x
   188  	f.Transform(tm)
   189  }
   190  
   191  // Transform generally transforms the following text, drawings and images
   192  // according to the specified matrix. It is typically easier to use the various
   193  // methods such as TransformRotate() and TransformMirrorVertical() instead.
   194  func (f *Fpdf) Transform(tm TransformMatrix) {
   195  	if f.transformNest > 0 {
   196  		f.outf("%.5f %.5f %.5f %.5f %.5f %.5f cm",
   197  			tm.A, tm.B, tm.C, tm.D, tm.E, tm.F)
   198  	} else if f.err == nil {
   199  		f.err = fmt.Errorf("transformation context is not active")
   200  	}
   201  }
   202  
   203  // TransformEnd applies a transformation that was begun with a call to TransformBegin().
   204  //
   205  // The TransformBegin() example demonstrates this method.
   206  func (f *Fpdf) TransformEnd() {
   207  	if f.transformNest > 0 {
   208  		f.transformNest--
   209  		f.out("Q")
   210  	} else {
   211  		f.err = fmt.Errorf("error attempting to end transformation operation out of sequence")
   212  	}
   213  }