Transformations

Add-On Transformations

Informations

Authors:Moritz Wagner&Andreas Würmser
License: FPDF

Description

Performs the following 2D transformations: scaling, mirroring, translation, rotation and skewing.
Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.

StartTransform()

Use this before calling any tranformation.

ScaleX(float s_x [, float x [, float y]])
ScaleY(float s_y [, float x [, float y]])
ScaleXY(float s [, float x [, float y]])
Scale(float s_x, float s_y [, float x [, float y]])

s_x: scaling factor for width as percent. 0 is not allowed.
s_y: scaling factor for height as percent. 0 is not allowed.
s: scaling factor for width and height as percent. 0 is not allowed.
x: abscissa of the scaling center. Default is current x position
y: ordinate of the scaling center. Default is current y position

MirrorH([float x])

Alias for scaling -100% in x-direction
x: abscissa of the axis of reflection

MirrorV([float y])

Alias for scaling -100% in y-direction
y: ordinate of the axis of reflection

MirrorP([float x, [float y]])

Point reflection on point (x, y). (alias for scaling -100 in x- and y-direction)
x: abscissa of the point. Default is current x position
y: ordinate of the point. Default is current y position

MirrorL([float angle [, float x [, float y]]])

Reflection against a straight line through point (x, y) with the gradient angle (angle).
angle: gradient angle of the straight line. Default is 0 (horizontal line).
x: abscissa of the point. Default is current x position
y: ordinate of the point. Default is current y position

TranslateX(float t_x)
TranslateY(float t_y)
Translate(float t_x, float t_y)

t_x: movement to the right
t_y: movement to the bottom

Rotate(float angle [, float x [, float y]])

angle: angle in degrees for counter-clockwise rotation
x: abscissa of the rotation center. Default is current x position
y: ordinate of the rotation center. Default is current y position

SkewX(float angle_x [, float x [, float y]])
SkewY(float angle_y [, float x [, float y]])
Skew(float angle_x, float angle_y [, float x [, float y]])

angle_x: angle in degrees between -90 (skew to the left) and 90 (skew to the right)
angle_y: angle in degrees between -90 (skew to the bottom) and 90 (skew to the top)
x: abscissa of the skewing center. default is current x position
y: ordinate of the skewing center. default is current y position

StopTransform()

Restores the normal painting and placing behavior as it was before calling StartTransform().

Source

<?php
/*
Version 2
Changes since version 1:
- added function MirrorP()
- added function MirrorL()
- fixed bug in Translate(): the movement is now performed in user units instead of pts
*/
require('fpdf.php');

class PDF_Transform extends FPDF{

    function StartTransform(){
        //save the current graphic state
        $this->_out('q');
    }

    function ScaleX($s_x, $x='', $y=''){
        $this->Scale($s_x, 100, $x, $y);
    }
    function ScaleY($s_y, $x='', $y=''){
        $this->Scale(100, $s_y, $x, $y);
    }
    function ScaleXY($s, $x='', $y=''){
        $this->Scale($s, $s, $x, $y);
    }
    function Scale($s_x, $s_y, $x='', $y=''){
        if($x === '')
            $x=$this->x;
        if($y === '')
            $y=$this->y;
        if($s_x == 0 || $s_y == 0)
            $this->Error('Please use values unequal to zero for Scaling');
        $y=($this->h-$y)*$this->k;
        $x*=$this->k;
        //calculate elements of transformation matrix
        $s_x/=100;
        $s_y/=100;
        $tm[0]=$s_x;
        $tm[1]=0;
        $tm[2]=0;
        $tm[3]=$s_y;
        $tm[4]=$x*(1-$s_x);
        $tm[5]=$y*(1-$s_y);
        //scale the coordinate system
        $this->Transform($tm);
    }

    function MirrorH($x=''){
        $this->Scale(-100, 100, $x);
    }
    function MirrorV($y=''){
        $this->Scale(100, -100, '', $y);
    }
    function MirrorP($x='', $y=''){
        $this->Scale(-100, -100, $x, $y);
    }
    function MirrorL($angle=0, $x='', $y=''){
        $this->Scale(-100, 100, $x, $y);
        $this->Rotate(-2*($angle-90), $x, $y);
    }

    function TranslateX($t_x){
        $this->Translate($t_x, 0, $x, $y);
    }
    function TranslateY($t_y){
        $this->Translate(0, $t_y, $x, $y);
    }
    function Translate($t_x, $t_y){
        //calculate elements of transformation matrix
        $tm[0]=1;
        $tm[1]=0;
        $tm[2]=0;
        $tm[3]=1;
        $tm[4]=$t_x*$this->k;
        $tm[5]=-$t_y*$this->k;
        //translate the coordinate system
        $this->Transform($tm);
    }

    function Rotate($angle, $x='', $y=''){
        if($x === '')
            $x=$this->x;
        if($y === '')
            $y=$this->y;
        $y=($this->h-$y)*$this->k;
        $x*=$this->k;
        //calculate elements of transformation matrix
        $tm[0]=cos(deg2rad($angle));
        $tm[1]=sin(deg2rad($angle));
        $tm[2]=-$tm[1];
        $tm[3]=$tm[0];
        $tm[4]=$x+$tm[1]*$y-$tm[0]*$x;
        $tm[5]=$y-$tm[0]*$y-$tm[1]*$x;
        //rotate the coordinate system around ($x, $y)
        $this->Transform($tm);
    }

    function SkewX($angle_x, $x='', $y=''){
        $this->Skew($angle_x, 0, $x, $y);
    }
    function SkewY($angle_y, $x='', $y=''){
        $this->Skew(0, $angle_y, $x, $y);
    }
    function Skew($angle_x, $angle_y, $x='', $y=''){
        if($x === '')
            $x=$this->x;
        if($y === '')
            $y=$this->y;
        if($angle_x <= -90 || $angle_x >= 90 || $angle_y <= -90 || $angle_y >= 90)
            $this->Error('Please use values between -90° and 90° for skewing');
        $x*=$this->k;
        $y=($this->h-$y)*$this->k;
        //calculate elements of transformation matrix
        $tm[0]=1;
        $tm[1]=tan(deg2rad($angle_y));
        $tm[2]=tan(deg2rad($angle_x));
        $tm[3]=1;
        $tm[4]=-$tm[2]*$y;
        $tm[5]=-$tm[1]*$x;
        //skew the coordinate system
        $this->Transform($tm);
    }

    function Transform($tm){
        $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
    }

    function StopTransform(){
        //restore previous graphic state
        $this->_out('Q');
    }
}
?>

Example

<?php
require('transform.php');

$pdf = new PDF_Transform();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 12);

//Scaling
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(50, 20, 40, 10, 'D');
$pdf->Text(50, 19, 'Scale');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//Scale by 150% centered by (50, 30) which is the lower left corner of the rectangle
$pdf->ScaleXY(150, 50, 30);
$pdf->Rect(50, 20, 40, 10, 'D');
$pdf->Text(50, 19, 'Scale');
//Stop Transformation
$pdf->StopTransform();

//Translation
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(125, 20, 40, 10, 'D');
$pdf->Text(125, 19, 'Translate');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//Translate 7 to the right, 5 to the bottom
$pdf->Translate(7, 5);
$pdf->Rect(125, 20, 40, 10, 'D');
$pdf->Text(125, 19, 'Translate');
//Stop Transformation
$pdf->StopTransform();

//Rotation
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(50, 50, 40, 10, 'D');
$pdf->Text(50, 49, 'Rotate');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//Rotate 20 degrees counter-clockwise centered by (50, 60) which is the lower left corner of the rectangle
$pdf->Rotate(20, 50, 60);
$pdf->Rect(50, 50, 40, 10, 'D');
$pdf->Text(50, 49, 'Rotate');
//Stop Transformation
$pdf->StopTransform();

//Skewing
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(125, 50, 40, 10, 'D');
$pdf->Text(125, 49, 'Skew');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//skew 30 degrees along the x-axis centered by (125, 60) which is the lower left corner of the rectangle
$pdf->SkewX(30, 125, 60);
$pdf->Rect(125, 50, 40, 10, 'D');
$pdf->Text(125, 49, 'Skew');
//Stop Transformation
$pdf->StopTransform();

//Mirroring horizontally
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(50, 80, 40, 10, 'D');
$pdf->Text(50, 79, 'MirrorH');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//mirror horizontally with axis of reflection at x-position 50 (left side of the rectangle)
$pdf->MirrorH(50);
$pdf->Rect(50, 80, 40, 10, 'D');
$pdf->Text(50, 79, 'MirrorH');
//Stop Transformation
$pdf->StopTransform();

//Mirroring vertically
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(125, 80, 40, 10, 'D');
$pdf->Text(125, 79, 'MirrorV');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//mirror vertically with axis of reflection at y-position 90 (bottom side of the rectangle)
$pdf->MirrorV(90);
$pdf->Rect(125, 80, 40, 10, 'D');
$pdf->Text(125, 79, 'MirrorV');
//Stop Transformation
$pdf->StopTransform();

//Point reflection
$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(50, 110, 40, 10, 'D');
$pdf->Text(50, 109, 'MirrorP');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//point reflection at the lower left point of rectangle
$pdf->MirrorP(50, 120);
$pdf->Rect(50, 110, 40, 10, 'D');
$pdf->Text(50, 109, 'MirrorP');
//Stop Transformation
$pdf->StopTransform();

//Mirroring against a straigth line described by a point (120, 120) and an angle -20°
$angle=-20;
$px=120;
$py=120;

/* */ //just vor visualisation: the straight line to mirror against
/* */ $pdf->SetDrawColor(200);
/* */ $pdf->Line($px-1, $py-1, $px+1, $py+1);
/* */ $pdf->Line($px-1, $py+1, $px+1, $py-1);
/* */ $pdf->StartTransform();
/* */ $pdf->Rotate($angle, $px, $py);
/* */ $pdf->Line($px-5, $py, $px+60, $py);
/* */ $pdf->StopTransform();

$pdf->SetDrawColor(200);
$pdf->SetTextColor(200);
$pdf->Rect(125, 110, 40, 10, 'D');
$pdf->Text(125, 109, 'MirrorL');
$pdf->SetDrawColor(0);
$pdf->SetTextColor(0);
//Start Transformation
$pdf->StartTransform();
//mirror against the straight line
$pdf->MirrorL($angle, $px, $py);
$pdf->Rect(125, 110, 40, 10, 'D');
$pdf->Text(125, 109, 'MirrorL');
//Stop Transformation
$pdf->StopTransform();

$pdf->Output();
?>
View the result here.

Download

ZIP | TGZ
An Error Occurred:Internal Server Error

Oops! An Error Occurred

The server returned a "500Internal Server Error".

Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.