web/lib/Zend/Pdf/Canvas/Abstract.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Pdf
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: Style.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    20  */
       
    21 
       
    22 require_once 'Zend/Pdf/Canvas/Interface.php';
       
    23 
       
    24 /** Internally used classes */
       
    25 require_once 'Zend/Pdf/Element.php';
       
    26 require_once 'Zend/Pdf/Element/Array.php';
       
    27 require_once 'Zend/Pdf/Element/String/Binary.php';
       
    28 require_once 'Zend/Pdf/Element/Boolean.php';
       
    29 require_once 'Zend/Pdf/Element/Dictionary.php';
       
    30 require_once 'Zend/Pdf/Element/Name.php';
       
    31 require_once 'Zend/Pdf/Element/Null.php';
       
    32 require_once 'Zend/Pdf/Element/Numeric.php';
       
    33 require_once 'Zend/Pdf/Element/String.php';
       
    34 
       
    35 
       
    36 /**
       
    37  * Canvas is an abstract rectangle drawing area which can be dropped into
       
    38  * page object at specified place.
       
    39  *
       
    40  * @package    Zend_Pdf
       
    41  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    42  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    43  */
       
    44 abstract class Zend_Pdf_Canvas_Abstract implements Zend_Pdf_Canvas_Interface
       
    45 {
       
    46     /**
       
    47      * Drawing instructions
       
    48      *
       
    49      * @var string
       
    50      */
       
    51     protected $_contents = '';
       
    52 
       
    53     /**
       
    54      * Current font
       
    55      *
       
    56      * @var Zend_Pdf_Resource_Font
       
    57      */
       
    58     protected $_font = null;
       
    59 
       
    60     /**
       
    61      * Current font size
       
    62      *
       
    63      * @var float
       
    64      */
       
    65     protected $_fontSize;
       
    66 
       
    67     /**
       
    68      * Current style
       
    69      *
       
    70      * @var Zend_Pdf_Style
       
    71      */
       
    72     protected $_style = null;
       
    73 
       
    74 
       
    75     /**
       
    76      * Counter for the "Save" operations
       
    77      *
       
    78      * @var integer
       
    79      */
       
    80     protected $_saveCount = 0;
       
    81 
       
    82 
       
    83     /**
       
    84      * Add procedureSet to the Page description
       
    85      *
       
    86      * @param string $procSetName
       
    87      */
       
    88     abstract protected function _addProcSet($procSetName);
       
    89 
       
    90     /**
       
    91      * Attach resource to the canvas
       
    92      *
       
    93      * Method returns a name of the resource which can be used
       
    94      * as a resource reference within drawing instructions stream
       
    95      * Allowed types: 'ExtGState', 'ColorSpace', 'Pattern', 'Shading',
       
    96      * 'XObject', 'Font', 'Properties'
       
    97      *
       
    98      * @param string $type
       
    99      * @param Zend_Pdf_Resource $resource
       
   100      * @return string
       
   101      */
       
   102     abstract protected function _attachResource($type, Zend_Pdf_Resource $resource);
       
   103 
       
   104     /**
       
   105      * Draw a canvas at the specified location
       
   106      *
       
   107      * If upper right corner is not specified then canvas heght and width
       
   108      * are used.
       
   109      *
       
   110      * @param Zend_Pdf_Canvas_Interface $canvas
       
   111      * @param float $x1
       
   112      * @param float $y1
       
   113      * @param float $x2
       
   114      * @param float $y2
       
   115      * @return Zend_Pdf_Canvas_Interface
       
   116      */
       
   117     public function drawCanvas(Zend_Pdf_Canvas_Interface $canvas, $x1, $y1, $x2 = null, $y2 = null)
       
   118     {
       
   119         $this->saveGS();
       
   120 
       
   121         $this->translate($x1, $y1);
       
   122 
       
   123         if ($x2 === null) {
       
   124             $with = $canvas->getWidth();
       
   125         } else {
       
   126             $with = $x2 - $x1;
       
   127         }
       
   128         if ($y2 === null) {
       
   129             $height = $canvas->getHeight();
       
   130         } else {
       
   131             $height = $y2 - $y1;
       
   132         }
       
   133 
       
   134         $this->clipRectangle(0, 0, $with, $height);
       
   135 
       
   136         if ($x2 !== null  ||  $y2 !== null) {
       
   137             // Drawn canvas has to be scaled.
       
   138             if ($x2 !== null) {
       
   139                 $xScale = $with/$canvas->getWidth();
       
   140             } else {
       
   141                 $xScale = 1;
       
   142             }
       
   143 
       
   144             if ($y2 !== null) {
       
   145                 $yScale = $height/$canvas->getHeight();
       
   146             } else {
       
   147                 $yScale = 1;
       
   148             }
       
   149 
       
   150             $this->scale($xScale, $yScale);
       
   151         }
       
   152 
       
   153         $contentsToDraw = $canvas->getContents();
       
   154         /** @todo implementation */
       
   155 
       
   156         $this->restoreGS();
       
   157 
       
   158         return $this;
       
   159     }
       
   160 
       
   161     /**
       
   162      * Set fill color.
       
   163      *
       
   164      * @param Zend_Pdf_Color $color
       
   165      * @return Zend_Pdf_Canvas_Interface
       
   166      */
       
   167     public function setFillColor(Zend_Pdf_Color $color)
       
   168     {
       
   169         $this->_addProcSet('PDF');
       
   170         $this->_contents .= $color->instructions(false);
       
   171 
       
   172         return $this;
       
   173     }
       
   174 
       
   175     /**
       
   176      * Set line color.
       
   177      *
       
   178      * @param Zend_Pdf_Color $color
       
   179      * @return Zend_Pdf_Canvas_Interface
       
   180      */
       
   181     public function setLineColor(Zend_Pdf_Color $color)
       
   182     {
       
   183         $this->_addProcSet('PDF');
       
   184         $this->_contents .= $color->instructions(true);
       
   185 
       
   186         return $this;
       
   187     }
       
   188 
       
   189     /**
       
   190      * Set line width.
       
   191      *
       
   192      * @param float $width
       
   193      * @return Zend_Pdf_Canvas_Interface
       
   194      */
       
   195     public function setLineWidth($width)
       
   196     {
       
   197         $this->_addProcSet('PDF');
       
   198         $widthObj = new Zend_Pdf_Element_Numeric($width);
       
   199         $this->_contents .= $widthObj->toString() . " w\n";
       
   200 
       
   201         return $this;
       
   202     }
       
   203 
       
   204     /**
       
   205      * Set line dashing pattern
       
   206      *
       
   207      * Pattern is an array of floats: array(on_length, off_length, on_length, off_length, ...)
       
   208      * or Zend_Pdf_Page::LINE_DASHING_SOLID constant
       
   209      * Phase is shift from the beginning of line.
       
   210      *
       
   211      * @param mixed $pattern
       
   212      * @param array $phase
       
   213      * @return Zend_Pdf_Canvas_Interface
       
   214      */
       
   215     public function setLineDashingPattern($pattern, $phase = 0)
       
   216     {
       
   217         $this->_addProcSet('PDF');
       
   218 
       
   219         require_once 'Zend/Pdf/Page.php';
       
   220         if ($pattern === Zend_Pdf_Page::LINE_DASHING_SOLID) {
       
   221             $pattern = array();
       
   222             $phase   = 0;
       
   223         }
       
   224 
       
   225         $dashPattern  = new Zend_Pdf_Element_Array();
       
   226         $phaseEleemnt = new Zend_Pdf_Element_Numeric($phase);
       
   227 
       
   228         foreach ($pattern as $dashItem) {
       
   229             $dashElement = new Zend_Pdf_Element_Numeric($dashItem);
       
   230             $dashPattern->items[] = $dashElement;
       
   231         }
       
   232 
       
   233         $this->_contents .= $dashPattern->toString() . ' '
       
   234                          . $phaseEleemnt->toString() . " d\n";
       
   235 
       
   236         return $this;
       
   237     }
       
   238 
       
   239     /**
       
   240      * Set current font.
       
   241      *
       
   242      * @param Zend_Pdf_Resource_Font $font
       
   243      * @param float $fontSize
       
   244      * @return Zend_Pdf_Canvas_Interface
       
   245      */
       
   246     public function setFont(Zend_Pdf_Resource_Font $font, $fontSize)
       
   247     {
       
   248         $this->_addProcSet('Text');
       
   249         $fontName = $this->_attachResource('Font', $font);
       
   250 
       
   251         $this->_font     = $font;
       
   252         $this->_fontSize = $fontSize;
       
   253 
       
   254         $fontNameObj = new Zend_Pdf_Element_Name($fontName);
       
   255         $fontSizeObj = new Zend_Pdf_Element_Numeric($fontSize);
       
   256         $this->_contents .= $fontNameObj->toString() . ' ' . $fontSizeObj->toString() . " Tf\n";
       
   257 
       
   258         return $this;
       
   259     }
       
   260 
       
   261     /**
       
   262      * Set the style to use for future drawing operations on this page
       
   263      *
       
   264      * @param Zend_Pdf_Style $style
       
   265      * @return Zend_Pdf_Canvas_Interface
       
   266      */
       
   267     public function setStyle(Zend_Pdf_Style $style)
       
   268     {
       
   269         $this->_addProcSet('Text');
       
   270         $this->_addProcSet('PDF');
       
   271         if ($style->getFont() !== null) {
       
   272             $this->setFont($style->getFont(), $style->getFontSize());
       
   273         }
       
   274         $this->_contents .= $style->instructions($this->_dictionary->Resources);
       
   275 
       
   276         $this->_style = $style;
       
   277 
       
   278         return $this;
       
   279     }
       
   280 
       
   281     /**
       
   282      * Get current font.
       
   283      *
       
   284      * @return Zend_Pdf_Resource_Font $font
       
   285      */
       
   286     public function getFont()
       
   287     {
       
   288         return $this->_font;
       
   289     }
       
   290 
       
   291     /**
       
   292      * Get current font size
       
   293      *
       
   294      * @return float $fontSize
       
   295      */
       
   296     public function getFontSize()
       
   297     {
       
   298         return $this->_fontSize;
       
   299     }
       
   300 
       
   301     /**
       
   302      * Return the style, applied to the page.
       
   303      *
       
   304      * @return Zend_Pdf_Style
       
   305      */
       
   306     public function getStyle()
       
   307     {
       
   308         return $this->_style;
       
   309     }
       
   310 
       
   311     /**
       
   312      * Save the graphics state of this page.
       
   313      * This takes a snapshot of the currently applied style, position, clipping area and
       
   314      * any rotation/translation/scaling that has been applied.
       
   315      *
       
   316      * @todo check for the open paths
       
   317      * @throws Zend_Pdf_Exception    - if a save is performed with an open path
       
   318      * @return Zend_Pdf_Canvas_Interface
       
   319      */
       
   320     public function saveGS()
       
   321     {
       
   322         $this->_saveCount++;
       
   323 
       
   324         $this->_addProcSet('PDF');
       
   325         $this->_contents .= " q\n";
       
   326 
       
   327         return $this;
       
   328     }
       
   329 
       
   330     /**
       
   331      * Restore the graphics state that was saved with the last call to saveGS().
       
   332      *
       
   333      * @throws Zend_Pdf_Exception   - if there is no previously saved state
       
   334      * @return Zend_Pdf_Canvas_Interface
       
   335      */
       
   336     public function restoreGS()
       
   337     {
       
   338         if ($this->_saveCount-- <= 0) {
       
   339             require_once 'Zend/Pdf/Exception.php';
       
   340             throw new Zend_Pdf_Exception('Restoring graphics state which is not saved');
       
   341         }
       
   342         $this->_contents .= " Q\n";
       
   343 
       
   344         return $this;
       
   345     }
       
   346 
       
   347     /**
       
   348      * Set the transparancy
       
   349      *
       
   350      * $alpha == 0  - transparent
       
   351      * $alpha == 1  - opaque
       
   352      *
       
   353      * Transparency modes, supported by PDF:
       
   354      * Normal (default), Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight,
       
   355      * SoftLight, Difference, Exclusion
       
   356      *
       
   357      * @param float $alpha
       
   358      * @param string $mode
       
   359      * @return Zend_Pdf_Canvas_Interface
       
   360      */
       
   361     public function setAlpha($alpha, $mode = 'Normal')
       
   362     {
       
   363         $this->_addProcSet('Text');
       
   364         $this->_addProcSet('PDF');
       
   365 
       
   366         $graphicsState = new Zend_Pdf_Resource_GraphicsState();
       
   367 
       
   368         $graphicsState->setAlpha($alpha, $mode);
       
   369         $gStateName = $this->_attachResource('ExtGState', $graphicsState);
       
   370 
       
   371         $gStateNameObject = new Zend_Pdf_Element_Name($gStateName);
       
   372         $this->_contents .= $gStateNameObject->toString() . " gs\n";
       
   373 
       
   374         return $this;
       
   375     }
       
   376 
       
   377     /**
       
   378      * Intersect current clipping area with a circle.
       
   379      *
       
   380      * @param float $x
       
   381      * @param float $y
       
   382      * @param float $radius
       
   383      * @param float $startAngle
       
   384      * @param float $endAngle
       
   385      * @return Zend_Pdf_Canvas_Interface
       
   386      */
       
   387     public function clipCircle($x, $y, $radius, $startAngle = null, $endAngle = null)
       
   388     {
       
   389         $this->clipEllipse($x - $radius, $y - $radius,
       
   390                            $x + $radius, $y + $radius,
       
   391                            $startAngle, $endAngle);
       
   392 
       
   393         return $this;
       
   394     }
       
   395 
       
   396     /**
       
   397      * Intersect current clipping area with a polygon.
       
   398      *
       
   399      * Method signatures:
       
   400      * drawEllipse($x1, $y1, $x2, $y2);
       
   401      * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle);
       
   402      *
       
   403      * @todo process special cases with $x2-$x1 == 0 or $y2-$y1 == 0
       
   404      *
       
   405      * @param float $x1
       
   406      * @param float $y1
       
   407      * @param float $x2
       
   408      * @param float $y2
       
   409      * @param float $startAngle
       
   410      * @param float $endAngle
       
   411      * @return Zend_Pdf_Canvas_Interface
       
   412      */
       
   413     public function clipEllipse($x1, $y1, $x2, $y2, $startAngle = null, $endAngle = null)
       
   414     {
       
   415         $this->_addProcSet('PDF');
       
   416 
       
   417         if ($x2 < $x1) {
       
   418             $temp = $x1;
       
   419             $x1   = $x2;
       
   420             $x2   = $temp;
       
   421         }
       
   422         if ($y2 < $y1) {
       
   423             $temp = $y1;
       
   424             $y1   = $y2;
       
   425             $y2   = $temp;
       
   426         }
       
   427 
       
   428         $x = ($x1 + $x2)/2.;
       
   429         $y = ($y1 + $y2)/2.;
       
   430 
       
   431         $xC = new Zend_Pdf_Element_Numeric($x);
       
   432         $yC = new Zend_Pdf_Element_Numeric($y);
       
   433 
       
   434         if ($startAngle !== null) {
       
   435             if ($startAngle != 0) { $startAngle = fmod($startAngle, M_PI*2); }
       
   436             if ($endAngle   != 0) { $endAngle   = fmod($endAngle,   M_PI*2); }
       
   437 
       
   438             if ($startAngle > $endAngle) {
       
   439                 $endAngle += M_PI*2;
       
   440             }
       
   441 
       
   442             $clipPath    = $xC->toString() . ' ' . $yC->toString() . " m\n";
       
   443             $clipSectors = (int)ceil(($endAngle - $startAngle)/M_PI_4);
       
   444             $clipRadius  = max($x2 - $x1, $y2 - $y1);
       
   445 
       
   446             for($count = 0; $count <= $clipSectors; $count++) {
       
   447                 $pAngle = $startAngle + ($endAngle - $startAngle)*$count/(float)$clipSectors;
       
   448 
       
   449                 $pX = new Zend_Pdf_Element_Numeric($x + cos($pAngle)*$clipRadius);
       
   450                 $pY = new Zend_Pdf_Element_Numeric($y + sin($pAngle)*$clipRadius);
       
   451                 $clipPath .= $pX->toString() . ' ' . $pY->toString() . " l\n";
       
   452             }
       
   453 
       
   454             $this->_contents .= $clipPath . "h\nW\nn\n";
       
   455         }
       
   456 
       
   457         $xLeft  = new Zend_Pdf_Element_Numeric($x1);
       
   458         $xRight = new Zend_Pdf_Element_Numeric($x2);
       
   459         $yUp    = new Zend_Pdf_Element_Numeric($y2);
       
   460         $yDown  = new Zend_Pdf_Element_Numeric($y1);
       
   461 
       
   462         $xDelta  = 2*(M_SQRT2 - 1)*($x2 - $x1)/3.;
       
   463         $yDelta  = 2*(M_SQRT2 - 1)*($y2 - $y1)/3.;
       
   464         $xr = new Zend_Pdf_Element_Numeric($x + $xDelta);
       
   465         $xl = new Zend_Pdf_Element_Numeric($x - $xDelta);
       
   466         $yu = new Zend_Pdf_Element_Numeric($y + $yDelta);
       
   467         $yd = new Zend_Pdf_Element_Numeric($y - $yDelta);
       
   468 
       
   469         $this->_contents .= $xC->toString() . ' ' . $yUp->toString() . " m\n"
       
   470                          .  $xr->toString() . ' ' . $yUp->toString() . ' '
       
   471                          .    $xRight->toString() . ' ' . $yu->toString() . ' '
       
   472                          .      $xRight->toString() . ' ' . $yC->toString() . " c\n"
       
   473                          .  $xRight->toString() . ' ' . $yd->toString() . ' '
       
   474                          .    $xr->toString() . ' ' . $yDown->toString() . ' '
       
   475                          .      $xC->toString() . ' ' . $yDown->toString() . " c\n"
       
   476                          .  $xl->toString() . ' ' . $yDown->toString() . ' '
       
   477                          .    $xLeft->toString() . ' ' . $yd->toString() . ' '
       
   478                          .      $xLeft->toString() . ' ' . $yC->toString() . " c\n"
       
   479                          .  $xLeft->toString() . ' ' . $yu->toString() . ' '
       
   480                          .    $xl->toString() . ' ' . $yUp->toString() . ' '
       
   481                          .      $xC->toString() . ' ' . $yUp->toString() . " c\n"
       
   482                          .  "h\nW\nn\n";
       
   483 
       
   484         return $this;
       
   485     }
       
   486 
       
   487     /**
       
   488      * Intersect current clipping area with a polygon.
       
   489      *
       
   490      * @param array $x  - array of float (the X co-ordinates of the vertices)
       
   491      * @param array $y  - array of float (the Y co-ordinates of the vertices)
       
   492      * @param integer $fillMethod
       
   493      * @return Zend_Pdf_Canvas_Interface
       
   494      */
       
   495     public function clipPolygon($x, $y, $fillMethod = Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING)
       
   496     {
       
   497         $this->_addProcSet('PDF');
       
   498 
       
   499         $firstPoint = true;
       
   500         foreach ($x as $id => $xVal) {
       
   501             $xObj = new Zend_Pdf_Element_Numeric($xVal);
       
   502             $yObj = new Zend_Pdf_Element_Numeric($y[$id]);
       
   503 
       
   504             if ($firstPoint) {
       
   505                 $path = $xObj->toString() . ' ' . $yObj->toString() . " m\n";
       
   506                 $firstPoint = false;
       
   507             } else {
       
   508                 $path .= $xObj->toString() . ' ' . $yObj->toString() . " l\n";
       
   509             }
       
   510         }
       
   511 
       
   512         $this->_contents .= $path;
       
   513 
       
   514         if ($fillMethod == Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING) {
       
   515             $this->_contents .= " h\n W\nn\n";
       
   516         } else {
       
   517             // Even-Odd fill method.
       
   518             $this->_contents .= " h\n W*\nn\n";
       
   519         }
       
   520 
       
   521         return $this;
       
   522     }
       
   523 
       
   524     /**
       
   525      * Intersect current clipping area with a rectangle.
       
   526      *
       
   527      * @param float $x1
       
   528      * @param float $y1
       
   529      * @param float $x2
       
   530      * @param float $y2
       
   531      * @return Zend_Pdf_Canvas_Interface
       
   532      */
       
   533     public function clipRectangle($x1, $y1, $x2, $y2)
       
   534     {
       
   535         $this->_addProcSet('PDF');
       
   536 
       
   537         $x1Obj      = new Zend_Pdf_Element_Numeric($x1);
       
   538         $y1Obj      = new Zend_Pdf_Element_Numeric($y1);
       
   539         $widthObj   = new Zend_Pdf_Element_Numeric($x2 - $x1);
       
   540         $height2Obj = new Zend_Pdf_Element_Numeric($y2 - $y1);
       
   541 
       
   542         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
   543                          .      $widthObj->toString() . ' ' . $height2Obj->toString() . " re\n"
       
   544                          .  " W\nn\n";
       
   545 
       
   546         return $this;
       
   547     }
       
   548 
       
   549 // ------------------------------------------------------------------------------------------
       
   550     /**
       
   551      * Draw a circle centered on x, y with a radius of radius.
       
   552      *
       
   553      * Method signatures:
       
   554      * drawCircle($x, $y, $radius);
       
   555      * drawCircle($x, $y, $radius, $fillType);
       
   556      * drawCircle($x, $y, $radius, $startAngle, $endAngle);
       
   557      * drawCircle($x, $y, $radius, $startAngle, $endAngle, $fillType);
       
   558      *
       
   559      *
       
   560      * It's not a really circle, because PDF supports only cubic Bezier curves.
       
   561      * But _very_ good approximation.
       
   562      * It differs from a real circle on a maximum 0.00026 radiuses
       
   563      * (at PI/8, 3*PI/8, 5*PI/8, 7*PI/8, 9*PI/8, 11*PI/8, 13*PI/8 and 15*PI/8 angles).
       
   564      * At 0, PI/4, PI/2, 3*PI/4, PI, 5*PI/4, 3*PI/2 and 7*PI/4 it's exactly a tangent to a circle.
       
   565      *
       
   566      * @param float $x
       
   567      * @param float $y
       
   568      * @param float $radius
       
   569      * @param mixed $param4
       
   570      * @param mixed $param5
       
   571      * @param mixed $param6
       
   572      * @return Zend_Pdf_Canvas_Interface
       
   573      */
       
   574     public function  drawCircle($x, $y, $radius, $param4 = null, $param5 = null, $param6 = null)
       
   575     {
       
   576         $this->drawEllipse($x - $radius, $y - $radius,
       
   577                            $x + $radius, $y + $radius,
       
   578                            $param4, $param5, $param6);
       
   579 
       
   580         return $this;
       
   581     }
       
   582 
       
   583     /**
       
   584      * Draw an ellipse inside the specified rectangle.
       
   585      *
       
   586      * Method signatures:
       
   587      * drawEllipse($x1, $y1, $x2, $y2);
       
   588      * drawEllipse($x1, $y1, $x2, $y2, $fillType);
       
   589      * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle);
       
   590      * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle, $fillType);
       
   591      *
       
   592      * @todo process special cases with $x2-$x1 == 0 or $y2-$y1 == 0
       
   593      *
       
   594      * @param float $x1
       
   595      * @param float $y1
       
   596      * @param float $x2
       
   597      * @param float $y2
       
   598      * @param mixed $param5
       
   599      * @param mixed $param6
       
   600      * @param mixed $param7
       
   601      * @return Zend_Pdf_Canvas_Interface
       
   602      */
       
   603     public function drawEllipse($x1, $y1, $x2, $y2, $param5 = null, $param6 = null, $param7 = null)
       
   604     {
       
   605         if ($param5 === null) {
       
   606             // drawEllipse($x1, $y1, $x2, $y2);
       
   607             $startAngle = null;
       
   608             $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE;
       
   609         } else if ($param6 === null) {
       
   610             // drawEllipse($x1, $y1, $x2, $y2, $fillType);
       
   611             $startAngle = null;
       
   612             $fillType = $param5;
       
   613         } else {
       
   614             // drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle);
       
   615             // drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle, $fillType);
       
   616             $startAngle = $param5;
       
   617             $endAngle   = $param6;
       
   618 
       
   619             if ($param7 === null) {
       
   620                 $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE;
       
   621             } else {
       
   622                 $fillType = $param7;
       
   623             }
       
   624         }
       
   625 
       
   626         $this->_addProcSet('PDF');
       
   627 
       
   628         if ($x2 < $x1) {
       
   629             $temp = $x1;
       
   630             $x1   = $x2;
       
   631             $x2   = $temp;
       
   632         }
       
   633         if ($y2 < $y1) {
       
   634             $temp = $y1;
       
   635             $y1   = $y2;
       
   636             $y2   = $temp;
       
   637         }
       
   638 
       
   639         $x = ($x1 + $x2)/2.;
       
   640         $y = ($y1 + $y2)/2.;
       
   641 
       
   642         $xC = new Zend_Pdf_Element_Numeric($x);
       
   643         $yC = new Zend_Pdf_Element_Numeric($y);
       
   644 
       
   645         if ($startAngle !== null) {
       
   646             if ($startAngle != 0) { $startAngle = fmod($startAngle, M_PI*2); }
       
   647             if ($endAngle   != 0) { $endAngle   = fmod($endAngle,   M_PI*2); }
       
   648 
       
   649             if ($startAngle > $endAngle) {
       
   650                 $endAngle += M_PI*2;
       
   651             }
       
   652 
       
   653             $clipPath    = $xC->toString() . ' ' . $yC->toString() . " m\n";
       
   654             $clipSectors = (int)ceil(($endAngle - $startAngle)/M_PI_4);
       
   655             $clipRadius  = max($x2 - $x1, $y2 - $y1);
       
   656 
       
   657             for($count = 0; $count <= $clipSectors; $count++) {
       
   658                 $pAngle = $startAngle + ($endAngle - $startAngle)*$count/(float)$clipSectors;
       
   659 
       
   660                 $pX = new Zend_Pdf_Element_Numeric($x + cos($pAngle)*$clipRadius);
       
   661                 $pY = new Zend_Pdf_Element_Numeric($y + sin($pAngle)*$clipRadius);
       
   662                 $clipPath .= $pX->toString() . ' ' . $pY->toString() . " l\n";
       
   663             }
       
   664 
       
   665             $this->_contents .= "q\n" . $clipPath . "h\nW\nn\n";
       
   666         }
       
   667 
       
   668         $xLeft  = new Zend_Pdf_Element_Numeric($x1);
       
   669         $xRight = new Zend_Pdf_Element_Numeric($x2);
       
   670         $yUp    = new Zend_Pdf_Element_Numeric($y2);
       
   671         $yDown  = new Zend_Pdf_Element_Numeric($y1);
       
   672 
       
   673         $xDelta  = 2*(M_SQRT2 - 1)*($x2 - $x1)/3.;
       
   674         $yDelta  = 2*(M_SQRT2 - 1)*($y2 - $y1)/3.;
       
   675         $xr = new Zend_Pdf_Element_Numeric($x + $xDelta);
       
   676         $xl = new Zend_Pdf_Element_Numeric($x - $xDelta);
       
   677         $yu = new Zend_Pdf_Element_Numeric($y + $yDelta);
       
   678         $yd = new Zend_Pdf_Element_Numeric($y - $yDelta);
       
   679 
       
   680         $this->_contents .= $xC->toString() . ' ' . $yUp->toString() . " m\n"
       
   681                          .  $xr->toString() . ' ' . $yUp->toString() . ' '
       
   682                          .    $xRight->toString() . ' ' . $yu->toString() . ' '
       
   683                          .      $xRight->toString() . ' ' . $yC->toString() . " c\n"
       
   684                          .  $xRight->toString() . ' ' . $yd->toString() . ' '
       
   685                          .    $xr->toString() . ' ' . $yDown->toString() . ' '
       
   686                          .      $xC->toString() . ' ' . $yDown->toString() . " c\n"
       
   687                          .  $xl->toString() . ' ' . $yDown->toString() . ' '
       
   688                          .    $xLeft->toString() . ' ' . $yd->toString() . ' '
       
   689                          .      $xLeft->toString() . ' ' . $yC->toString() . " c\n"
       
   690                          .  $xLeft->toString() . ' ' . $yu->toString() . ' '
       
   691                          .    $xl->toString() . ' ' . $yUp->toString() . ' '
       
   692                          .      $xC->toString() . ' ' . $yUp->toString() . " c\n";
       
   693 
       
   694         switch ($fillType) {
       
   695             case Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE:
       
   696                 $this->_contents .= " B*\n";
       
   697                 break;
       
   698             case Zend_Pdf_Page::SHAPE_DRAW_FILL:
       
   699                 $this->_contents .= " f*\n";
       
   700                 break;
       
   701             case Zend_Pdf_Page::SHAPE_DRAW_STROKE:
       
   702                 $this->_contents .= " S\n";
       
   703                 break;
       
   704         }
       
   705 
       
   706         if ($startAngle !== null) {
       
   707             $this->_contents .= "Q\n";
       
   708         }
       
   709 
       
   710         return $this;
       
   711     }
       
   712 
       
   713     /**
       
   714      * Draw an image at the specified position on the page.
       
   715      *
       
   716      * @param Zend_Pdf_Image $image
       
   717      * @param float $x1
       
   718      * @param float $y1
       
   719      * @param float $x2
       
   720      * @param float $y2
       
   721      * @return Zend_Pdf_Canvas_Interface
       
   722      */
       
   723     public function drawImage(Zend_Pdf_Resource_Image $image, $x1, $y1, $x2, $y2)
       
   724     {
       
   725         $this->_addProcSet('PDF');
       
   726 
       
   727         $imageName    = $this->_attachResource('XObject', $image);
       
   728         $imageNameObj = new Zend_Pdf_Element_Name($imageName);
       
   729 
       
   730         $x1Obj     = new Zend_Pdf_Element_Numeric($x1);
       
   731         $y1Obj     = new Zend_Pdf_Element_Numeric($y1);
       
   732         $widthObj  = new Zend_Pdf_Element_Numeric($x2 - $x1);
       
   733         $heightObj = new Zend_Pdf_Element_Numeric($y2 - $y1);
       
   734 
       
   735         $this->_contents .= "q\n"
       
   736                          .  '1 0 0 1 ' . $x1Obj->toString() . ' ' . $y1Obj->toString() . " cm\n"
       
   737                          .  $widthObj->toString() . ' 0 0 ' . $heightObj->toString() . " 0 0 cm\n"
       
   738                          .  $imageNameObj->toString() . " Do\n"
       
   739                          .  "Q\n";
       
   740 
       
   741         return $this;
       
   742     }
       
   743 
       
   744     /**
       
   745      * Draw a LayoutBox at the specified position on the page.
       
   746      *
       
   747      * @internal (not implemented now)
       
   748      *
       
   749      * @param Zend_Pdf_Element_LayoutBox $box
       
   750      * @param float $x
       
   751      * @param float $y
       
   752      * @return Zend_Pdf_Canvas_Interface
       
   753      */
       
   754     public function drawLayoutBox($box, $x, $y)
       
   755     {
       
   756         /** @todo implementation */
       
   757         return $this;
       
   758     }
       
   759 
       
   760     /**
       
   761      * Draw a line from x1,y1 to x2,y2.
       
   762      *
       
   763      * @param float $x1
       
   764      * @param float $y1
       
   765      * @param float $x2
       
   766      * @param float $y2
       
   767      * @return Zend_Pdf_Canvas_Interface
       
   768      */
       
   769     public function drawLine($x1, $y1, $x2, $y2)
       
   770     {
       
   771         $this->_addProcSet('PDF');
       
   772 
       
   773         $x1Obj = new Zend_Pdf_Element_Numeric($x1);
       
   774         $y1Obj = new Zend_Pdf_Element_Numeric($y1);
       
   775         $x2Obj = new Zend_Pdf_Element_Numeric($x2);
       
   776         $y2Obj = new Zend_Pdf_Element_Numeric($y2);
       
   777 
       
   778         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " m\n"
       
   779                          .  $x2Obj->toString() . ' ' . $y2Obj->toString() . " l\n S\n";
       
   780 
       
   781         return $this;
       
   782     }
       
   783 
       
   784     /**
       
   785      * Draw a polygon.
       
   786      *
       
   787      * If $fillType is Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE or
       
   788      * Zend_Pdf_Page::SHAPE_DRAW_FILL, then polygon is automatically closed.
       
   789      * See detailed description of these methods in a PDF documentation
       
   790      * (section 4.4.2 Path painting Operators, Filling)
       
   791      *
       
   792      * @param array $x  - array of float (the X co-ordinates of the vertices)
       
   793      * @param array $y  - array of float (the Y co-ordinates of the vertices)
       
   794      * @param integer $fillType
       
   795      * @param integer $fillMethod
       
   796      * @return Zend_Pdf_Canvas_Interface
       
   797      */
       
   798     public function drawPolygon($x, $y,
       
   799                                 $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE,
       
   800                                 $fillMethod = Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING)
       
   801     {
       
   802         $this->_addProcSet('PDF');
       
   803 
       
   804         $firstPoint = true;
       
   805         foreach ($x as $id => $xVal) {
       
   806             $xObj = new Zend_Pdf_Element_Numeric($xVal);
       
   807             $yObj = new Zend_Pdf_Element_Numeric($y[$id]);
       
   808 
       
   809             if ($firstPoint) {
       
   810                 $path = $xObj->toString() . ' ' . $yObj->toString() . " m\n";
       
   811                 $firstPoint = false;
       
   812             } else {
       
   813                 $path .= $xObj->toString() . ' ' . $yObj->toString() . " l\n";
       
   814             }
       
   815         }
       
   816 
       
   817         $this->_contents .= $path;
       
   818 
       
   819         switch ($fillType) {
       
   820             case Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE:
       
   821                 if ($fillMethod == Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING) {
       
   822                     $this->_contents .= " b\n";
       
   823                 } else {
       
   824                     // Even-Odd fill method.
       
   825                     $this->_contents .= " b*\n";
       
   826                 }
       
   827                 break;
       
   828             case Zend_Pdf_Page::SHAPE_DRAW_FILL:
       
   829                 if ($fillMethod == Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING) {
       
   830                     $this->_contents .= " h\n f\n";
       
   831                 } else {
       
   832                     // Even-Odd fill method.
       
   833                     $this->_contents .= " h\n f*\n";
       
   834                 }
       
   835                 break;
       
   836             case Zend_Pdf_Page::SHAPE_DRAW_STROKE:
       
   837                 $this->_contents .= " S\n";
       
   838                 break;
       
   839         }
       
   840 
       
   841         return $this;
       
   842     }
       
   843 
       
   844     /**
       
   845      * Draw a rectangle.
       
   846      *
       
   847      * Fill types:
       
   848      * Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - fill rectangle and stroke (default)
       
   849      * Zend_Pdf_Page::SHAPE_DRAW_STROKE      - stroke rectangle
       
   850      * Zend_Pdf_Page::SHAPE_DRAW_FILL        - fill rectangle
       
   851      *
       
   852      * @param float $x1
       
   853      * @param float $y1
       
   854      * @param float $x2
       
   855      * @param float $y2
       
   856      * @param integer $fillType
       
   857      * @return Zend_Pdf_Canvas_Interface
       
   858      */
       
   859     public function drawRectangle($x1, $y1, $x2, $y2, $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE)
       
   860     {
       
   861         $this->_addProcSet('PDF');
       
   862 
       
   863         $x1Obj      = new Zend_Pdf_Element_Numeric($x1);
       
   864         $y1Obj      = new Zend_Pdf_Element_Numeric($y1);
       
   865         $widthObj   = new Zend_Pdf_Element_Numeric($x2 - $x1);
       
   866         $height2Obj = new Zend_Pdf_Element_Numeric($y2 - $y1);
       
   867 
       
   868         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
   869                              .  $widthObj->toString() . ' ' . $height2Obj->toString() . " re\n";
       
   870 
       
   871         switch ($fillType) {
       
   872             case Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE:
       
   873                 $this->_contents .= " B*\n";
       
   874                 break;
       
   875             case Zend_Pdf_Page::SHAPE_DRAW_FILL:
       
   876                 $this->_contents .= " f*\n";
       
   877                 break;
       
   878             case Zend_Pdf_Page::SHAPE_DRAW_STROKE:
       
   879                 $this->_contents .= " S\n";
       
   880                 break;
       
   881         }
       
   882 
       
   883         return $this;
       
   884     }
       
   885 
       
   886     /**
       
   887      * Draw a rounded rectangle.
       
   888      *
       
   889      * Fill types:
       
   890      * Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - fill rectangle and stroke (default)
       
   891      * Zend_Pdf_Page::SHAPE_DRAW_STROKE      - stroke rectangle
       
   892      * Zend_Pdf_Page::SHAPE_DRAW_FILL        - fill rectangle
       
   893      *
       
   894      * radius is an integer representing radius of the four corners, or an array
       
   895      * of four integers representing the radius starting at top left, going
       
   896      * clockwise
       
   897      *
       
   898      * @param float $x1
       
   899      * @param float $y1
       
   900      * @param float $x2
       
   901      * @param float $y2
       
   902      * @param integer|array $radius
       
   903      * @param integer $fillType
       
   904      * @return Zend_Pdf_Canvas_Interface
       
   905      */
       
   906     public function drawRoundedRectangle($x1, $y1, $x2, $y2, $radius,
       
   907                                          $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE)
       
   908     {
       
   909 
       
   910         $this->_addProcSet('PDF');
       
   911 
       
   912         if(!is_array($radius)) {
       
   913             $radius = array($radius, $radius, $radius, $radius);
       
   914         } else {
       
   915             for ($i = 0; $i < 4; $i++) {
       
   916                 if(!isset($radius[$i])) {
       
   917                     $radius[$i] = 0;
       
   918                 }
       
   919             }
       
   920         }
       
   921 
       
   922         $topLeftX      = $x1;
       
   923         $topLeftY      = $y2;
       
   924         $topRightX     = $x2;
       
   925         $topRightY     = $y2;
       
   926         $bottomRightX  = $x2;
       
   927         $bottomRightY  = $y1;
       
   928         $bottomLeftX   = $x1;
       
   929         $bottomLeftY   = $y1;
       
   930 
       
   931         //draw top side
       
   932         $x1Obj = new Zend_Pdf_Element_Numeric($topLeftX + $radius[0]);
       
   933         $y1Obj = new Zend_Pdf_Element_Numeric($topLeftY);
       
   934         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " m\n";
       
   935         $x1Obj = new Zend_Pdf_Element_Numeric($topRightX - $radius[1]);
       
   936         $y1Obj = new Zend_Pdf_Element_Numeric($topRightY);
       
   937         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " l\n";
       
   938 
       
   939         //draw top right corner if needed
       
   940         if ($radius[1] != 0) {
       
   941             $x1Obj = new Zend_Pdf_Element_Numeric($topRightX);
       
   942             $y1Obj = new Zend_Pdf_Element_Numeric($topRightY);
       
   943             $x2Obj = new Zend_Pdf_Element_Numeric($topRightX);
       
   944             $y2Obj = new Zend_Pdf_Element_Numeric($topRightY);
       
   945             $x3Obj = new Zend_Pdf_Element_Numeric($topRightX);
       
   946             $y3Obj = new Zend_Pdf_Element_Numeric($topRightY - $radius[1]);
       
   947             $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
   948                               . $x2Obj->toString() . ' ' . $y2Obj->toString() . ' '
       
   949                               . $x3Obj->toString() . ' ' . $y3Obj->toString() . ' '
       
   950                               . " c\n";
       
   951         }
       
   952 
       
   953         //draw right side
       
   954         $x1Obj = new Zend_Pdf_Element_Numeric($bottomRightX);
       
   955         $y1Obj = new Zend_Pdf_Element_Numeric($bottomRightY + $radius[2]);
       
   956         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " l\n";
       
   957 
       
   958         //draw bottom right corner if needed
       
   959         if ($radius[2] != 0) {
       
   960             $x1Obj = new Zend_Pdf_Element_Numeric($bottomRightX);
       
   961             $y1Obj = new Zend_Pdf_Element_Numeric($bottomRightY);
       
   962             $x2Obj = new Zend_Pdf_Element_Numeric($bottomRightX);
       
   963             $y2Obj = new Zend_Pdf_Element_Numeric($bottomRightY);
       
   964             $x3Obj = new Zend_Pdf_Element_Numeric($bottomRightX - $radius[2]);
       
   965             $y3Obj = new Zend_Pdf_Element_Numeric($bottomRightY);
       
   966             $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
   967                               . $x2Obj->toString() . ' ' . $y2Obj->toString() . ' '
       
   968                               . $x3Obj->toString() . ' ' . $y3Obj->toString() . ' '
       
   969                               . " c\n";
       
   970         }
       
   971 
       
   972         //draw bottom side
       
   973         $x1Obj = new Zend_Pdf_Element_Numeric($bottomLeftX + $radius[3]);
       
   974         $y1Obj = new Zend_Pdf_Element_Numeric($bottomLeftY);
       
   975         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " l\n";
       
   976 
       
   977         //draw bottom left corner if needed
       
   978         if ($radius[3] != 0) {
       
   979             $x1Obj = new Zend_Pdf_Element_Numeric($bottomLeftX);
       
   980             $y1Obj = new Zend_Pdf_Element_Numeric($bottomLeftY);
       
   981             $x2Obj = new Zend_Pdf_Element_Numeric($bottomLeftX);
       
   982             $y2Obj = new Zend_Pdf_Element_Numeric($bottomLeftY);
       
   983             $x3Obj = new Zend_Pdf_Element_Numeric($bottomLeftX);
       
   984             $y3Obj = new Zend_Pdf_Element_Numeric($bottomLeftY + $radius[3]);
       
   985             $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
   986                               . $x2Obj->toString() . ' ' . $y2Obj->toString() . ' '
       
   987                               . $x3Obj->toString() . ' ' . $y3Obj->toString() . ' '
       
   988                               . " c\n";
       
   989         }
       
   990 
       
   991         //draw left side
       
   992         $x1Obj = new Zend_Pdf_Element_Numeric($topLeftX);
       
   993         $y1Obj = new Zend_Pdf_Element_Numeric($topLeftY - $radius[0]);
       
   994         $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . " l\n";
       
   995 
       
   996         //draw top left corner if needed
       
   997         if ($radius[0] != 0) {
       
   998             $x1Obj = new Zend_Pdf_Element_Numeric($topLeftX);
       
   999             $y1Obj = new Zend_Pdf_Element_Numeric($topLeftY);
       
  1000             $x2Obj = new Zend_Pdf_Element_Numeric($topLeftX);
       
  1001             $y2Obj = new Zend_Pdf_Element_Numeric($topLeftY);
       
  1002             $x3Obj = new Zend_Pdf_Element_Numeric($topLeftX + $radius[0]);
       
  1003             $y3Obj = new Zend_Pdf_Element_Numeric($topLeftY);
       
  1004             $this->_contents .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' '
       
  1005                               . $x2Obj->toString() . ' ' . $y2Obj->toString() . ' '
       
  1006                               . $x3Obj->toString() . ' ' . $y3Obj->toString() . ' '
       
  1007                               . " c\n";
       
  1008         }
       
  1009 
       
  1010         switch ($fillType) {
       
  1011             case Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE:
       
  1012                 $this->_contents .= " B*\n";
       
  1013                 break;
       
  1014             case Zend_Pdf_Page::SHAPE_DRAW_FILL:
       
  1015                 $this->_contents .= " f*\n";
       
  1016                 break;
       
  1017             case Zend_Pdf_Page::SHAPE_DRAW_STROKE:
       
  1018                 $this->_contents .= " S\n";
       
  1019                 break;
       
  1020         }
       
  1021 
       
  1022         return $this;
       
  1023     }
       
  1024 
       
  1025     /**
       
  1026      * Draw a line of text at the specified position.
       
  1027      *
       
  1028      * @param string $text
       
  1029      * @param float $x
       
  1030      * @param float $y
       
  1031      * @param string $charEncoding (optional) Character encoding of source text.
       
  1032      *   Defaults to current locale.
       
  1033      * @throws Zend_Pdf_Exception
       
  1034      * @return Zend_Pdf_Canvas_Interface
       
  1035      */
       
  1036     public function drawText($text, $x, $y, $charEncoding = '')
       
  1037     {
       
  1038         if ($this->_font === null) {
       
  1039             require_once 'Zend/Pdf/Exception.php';
       
  1040             throw new Zend_Pdf_Exception('Font has not been set');
       
  1041         }
       
  1042 
       
  1043         $this->_addProcSet('Text');
       
  1044 
       
  1045         $textObj = new Zend_Pdf_Element_String($this->_font->encodeString($text, $charEncoding));
       
  1046         $xObj    = new Zend_Pdf_Element_Numeric($x);
       
  1047         $yObj    = new Zend_Pdf_Element_Numeric($y);
       
  1048 
       
  1049         $this->_contents .= "BT\n"
       
  1050                          .  $xObj->toString() . ' ' . $yObj->toString() . " Td\n"
       
  1051                          .  $textObj->toString() . " Tj\n"
       
  1052                          .  "ET\n";
       
  1053 
       
  1054         return $this;
       
  1055     }
       
  1056 
       
  1057      /**
       
  1058      * Close the path by drawing a straight line back to it's beginning.
       
  1059      *
       
  1060      * @internal (needs implementation)
       
  1061      *
       
  1062      * @throws Zend_Pdf_Exception    - if a path hasn't been started with pathMove()
       
  1063      * @return Zend_Pdf_Canvas_Interface
       
  1064      */
       
  1065     public function pathClose()
       
  1066     {
       
  1067         /** @todo implementation */
       
  1068         return $this;
       
  1069     }
       
  1070 
       
  1071     /**
       
  1072      * Continue the open path in a straight line to the specified position.
       
  1073      *
       
  1074      * @internal (needs implementation)
       
  1075      *
       
  1076      * @param float $x  - the X co-ordinate to move to
       
  1077      * @param float $y  - the Y co-ordinate to move to
       
  1078      * @return Zend_Pdf_Canvas_Interface
       
  1079      */
       
  1080     public function pathLine($x, $y)
       
  1081     {
       
  1082         /** @todo implementation */
       
  1083         return $this;
       
  1084     }
       
  1085 
       
  1086     /**
       
  1087      * Start a new path at the specified position. If a path has already been started,
       
  1088      * move the cursor without drawing a line.
       
  1089      *
       
  1090      * @internal (needs implementation)
       
  1091      *
       
  1092      * @param float $x  - the X co-ordinate to move to
       
  1093      * @param float $y  - the Y co-ordinate to move to
       
  1094      * @return Zend_Pdf_Canvas_Interface
       
  1095      */
       
  1096     public function pathMove($x, $y)
       
  1097     {
       
  1098         /** @todo implementation */
       
  1099         return $this;
       
  1100     }
       
  1101 
       
  1102     /**
       
  1103      * Rotate the page.
       
  1104      *
       
  1105      * @param float $x  - the X co-ordinate of rotation point
       
  1106      * @param float $y  - the Y co-ordinate of rotation point
       
  1107      * @param float $angle - rotation angle
       
  1108      * @return Zend_Pdf_Canvas_Interface
       
  1109      */
       
  1110     public function rotate($x, $y, $angle)
       
  1111     {
       
  1112         $cos  = new Zend_Pdf_Element_Numeric(cos($angle));
       
  1113         $sin  = new Zend_Pdf_Element_Numeric(sin($angle));
       
  1114         $mSin = new Zend_Pdf_Element_Numeric(-$sin->value);
       
  1115 
       
  1116         $xObj = new Zend_Pdf_Element_Numeric($x);
       
  1117         $yObj = new Zend_Pdf_Element_Numeric($y);
       
  1118 
       
  1119         $mXObj = new Zend_Pdf_Element_Numeric(-$x);
       
  1120         $mYObj = new Zend_Pdf_Element_Numeric(-$y);
       
  1121 
       
  1122 
       
  1123         $this->_addProcSet('PDF');
       
  1124         $this->_contents .= '1 0 0 1 ' . $xObj->toString() . ' ' . $yObj->toString() . " cm\n"
       
  1125                          .  $cos->toString() . ' ' . $sin->toString() . ' ' . $mSin->toString() . ' ' . $cos->toString() . " 0 0 cm\n"
       
  1126                          .  '1 0 0 1 ' . $mXObj->toString() . ' ' . $mYObj->toString() . " cm\n";
       
  1127 
       
  1128         return $this;
       
  1129     }
       
  1130 
       
  1131     /**
       
  1132      * Scale coordination system.
       
  1133      *
       
  1134      * @param float $xScale - X dimention scale factor
       
  1135      * @param float $yScale - Y dimention scale factor
       
  1136      * @return Zend_Pdf_Canvas_Interface
       
  1137      */
       
  1138     public function scale($xScale, $yScale)
       
  1139     {
       
  1140         $xScaleObj = new Zend_Pdf_Element_Numeric($xScale);
       
  1141         $yScaleObj = new Zend_Pdf_Element_Numeric($yScale);
       
  1142 
       
  1143         $this->_addProcSet('PDF');
       
  1144         $this->_contents .= $xScaleObj->toString() . ' 0 0 ' . $yScaleObj->toString() . " 0 0 cm\n";
       
  1145 
       
  1146         return $this;
       
  1147     }
       
  1148 
       
  1149     /**
       
  1150      * Translate coordination system.
       
  1151      *
       
  1152      * @param float $xShift - X coordinate shift
       
  1153      * @param float $yShift - Y coordinate shift
       
  1154      * @return Zend_Pdf_Canvas_Interface
       
  1155      */
       
  1156     public function translate($xShift, $yShift)
       
  1157     {
       
  1158         $xShiftObj = new Zend_Pdf_Element_Numeric($xShift);
       
  1159         $yShiftObj = new Zend_Pdf_Element_Numeric($yShift);
       
  1160 
       
  1161         $this->_addProcSet('PDF');
       
  1162         $this->_contents .= '1 0 0 1 ' . $xShiftObj->toString() . ' ' . $yShiftObj->toString() . " cm\n";
       
  1163 
       
  1164         return $this;
       
  1165     }
       
  1166 
       
  1167     /**
       
  1168      * Translate coordination system.
       
  1169      *
       
  1170      * @param float $x  - the X co-ordinate of axis skew point
       
  1171      * @param float $y  - the Y co-ordinate of axis skew point
       
  1172      * @param float $xAngle - X axis skew angle
       
  1173      * @param float $yAngle - Y axis skew angle
       
  1174      * @return Zend_Pdf_Canvas_Interface
       
  1175      */
       
  1176     public function skew($x, $y, $xAngle, $yAngle)
       
  1177     {
       
  1178         $tanXObj = new Zend_Pdf_Element_Numeric(tan($xAngle));
       
  1179         $tanYObj = new Zend_Pdf_Element_Numeric(-tan($yAngle));
       
  1180 
       
  1181         $xObj = new Zend_Pdf_Element_Numeric($x);
       
  1182         $yObj = new Zend_Pdf_Element_Numeric($y);
       
  1183 
       
  1184         $mXObj = new Zend_Pdf_Element_Numeric(-$x);
       
  1185         $mYObj = new Zend_Pdf_Element_Numeric(-$y);
       
  1186 
       
  1187         $this->_addProcSet('PDF');
       
  1188         $this->_contents .= '1 0 0 1 ' . $xObj->toString() . ' ' . $yObj->toString() . " cm\n"
       
  1189                          .  '1 ' . $tanXObj->toString() . ' ' . $tanYObj->toString() . " 1 0 0 cm\n"
       
  1190                          .  '1 0 0 1 ' . $mXObj->toString() . ' ' . $mYObj->toString() . " cm\n";
       
  1191 
       
  1192         return $this;
       
  1193     }
       
  1194 
       
  1195     /**
       
  1196      * Writes the raw data to the page's content stream.
       
  1197      *
       
  1198      * Be sure to consult the PDF reference to ensure your syntax is correct. No
       
  1199      * attempt is made to ensure the validity of the stream data.
       
  1200      *
       
  1201      * @param string $data
       
  1202      * @param string $procSet (optional) Name of ProcSet to add.
       
  1203      * @return Zend_Pdf_Canvas_Interface
       
  1204      */
       
  1205     public function rawWrite($data, $procSet = null)
       
  1206     {
       
  1207         if (! empty($procSet)) {
       
  1208             $this->_addProcSet($procSet);
       
  1209         }
       
  1210         $this->_contents .= $data;
       
  1211 
       
  1212         return $this;
       
  1213     }
       
  1214 }