[ Index ]
 

Code source de eZ Publish 3.9.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/ezpdf/classes/ -> class.ezpdftable.php (source)

   1  <?php
   2  
   3  //
   4  // Created on: <01-Sep-2003 13:23:32 kk>
   5  //
   6  // SOFTWARE NAME: eZ publish
   7  // SOFTWARE RELEASE: 3.9.0
   8  // BUILD VERSION: 17785
   9  // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS
  10  // SOFTWARE LICENSE: GNU General Public License v2.0
  11  // NOTICE: >
  12  //   This program is free software; you can redistribute it and/or
  13  //   modify it under the terms of version 2.0  of the GNU General
  14  //   Public License as published by the Free Software Foundation.
  15  //
  16  //   This program is distributed in the hope that it will be useful,
  17  //   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18  //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19  //   GNU General Public License for more details.
  20  //
  21  //   You should have received a copy of version 2.0 of the GNU General
  22  //   Public License along with this program; if not, write to the Free
  23  //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  24  //   MA 02110-1301, USA.
  25  //
  26  //
  27  
  28  /*! \file ezpdftable.php
  29  */
  30  
  31  include_once ( 'lib/ezpdf/classes/class.ezpdf.php' );
  32  
  33  define( 'EZ_PDF_LIB_NEWLINE', '<C:callNewLine>' );
  34  define( 'EZ_PDF_LIB_SPACE', '<C:callSpace>' );
  35  define( 'EZ_PDF_LIB_TAB', '<C:callTab>' );
  36  
  37  define( 'EZ_PDF_LIB_PAGENUM', '#page' );
  38  define( 'EZ_PDF_LIB_TOTAL_PAGENUM', '#total' );
  39  define( 'EZ_PDF_LIB_HEADER_LEVEL', '#level' );
  40  define( 'EZ_PDF_LIB_HEADER_LEVEL_INDEX', '#indexLevel' );
  41  
  42  /*!
  43    \class eZPDFTable class.ezpdftable.php
  44    \ingroup eZPDF
  45    \brief eZPDFTable adds extra support for tables
  46  */
  47  
  48  class eZPDFTable extends Cezpdf
  49  {
  50  
  51      /**
  52       Constructor. This class is only used to encapsulate a table.
  53      */
  54      function eZPDFTable($paper='a4',$orientation='portrait')
  55      {
  56          $this->Cezpdf($paper, $orientation);
  57          $this->TOC = array();
  58          $this->KeywordArray = array();
  59          $this->PageCounter = array();
  60          $this->initFrameMargins();
  61  
  62          $this->ez['textStack'] = array();
  63  
  64          $this->PreStack = array();
  65          $this->DocSpecification = array();
  66          $this->pushStack();
  67          $this->FrontpageID = null;
  68      }
  69  
  70      /*!
  71       * \private
  72       * Initialize footer and header frame margins. Called by constructor
  73       */
  74      function initFrameMargins()
  75      {
  76          $this->ezFrame = array();
  77  
  78          $config =& eZINI::instance( 'pdf.ini' );
  79  
  80          $this->ezFrame['header'] = array( 'y0' => $this->ez['pageHeight'],
  81                                            'leftMargin' => $config->variable( 'Header', 'LeftMargin' ),
  82                                            'rightMargin' => $config->variable( 'Header', 'RightMargin' ),
  83                                            'topMargin' => $config->variable( 'Header', 'TopMargin' ),
  84                                            'bottomMargin' => $config->variable( 'Header', 'BottomMargin' ) );
  85          $this->ezFrame['footer'] = array( 'y0' => $this->ez['bottomMargin'],
  86                                            'leftMargin' => $config->variable( 'Footer', 'LeftMargin' ),
  87                                            'rightMargin' => $config->variable( 'Footer', 'RightMargin' ),
  88                                            'topMargin' => $config->variable( 'Footer', 'TopMargin' ),
  89                                            'bottomMargin' => $config->variable( 'Footer', 'BottomMargin' ) );
  90      }
  91  
  92      /**
  93       Get the current Y offset
  94      */
  95      function yOffset()
  96      {
  97          return $this->y;
  98      }
  99  
 100      /**
 101       Get the current X offset
 102      */
 103      function xOffset()
 104      {
 105          $xOffset = $this->ez['xOffset'];
 106          if ( $xOffset == 0 ||
 107               $this->leftMargin() > $this->ez['xOffset'] )
 108          {
 109              $xOffset = $this->leftMargin();
 110          }
 111          return $xOffset;
 112      }
 113  
 114      function setYOffset( $yOffset )
 115      {
 116          $this->y = $yOffset;
 117      }
 118  
 119      function setXOffset( $xOffset )
 120      {
 121          if ( $xOffset > $this->ez['pageWidth'] - $this->rightMargin() )
 122          {
 123              $this->ez['xOffset'] = 0;
 124          }
 125          else
 126          {
 127              $this->ez['xOffset'] = $xOffset;
 128          }
 129      }
 130  
 131      /*!
 132       * add a table of information to the pdf document
 133       * $data is a two dimensional array
 134       * $cols (optional) is an associative array, the keys are the names of the columns from $data
 135       * to be presented (and in that order), the values are the titles to be given to the columns
 136       * $title (optional) is the title to be put on the top of the table
 137       *
 138       * $options is an associative array which can contain:
 139       * 'cellData' => array( <coord> => array( 'size' => array( <width>, <height>),
 140       *                                        'justification' => <left|right|center> ),
 141       *                      <coord>....)
 142       *            All non specified coords will be threated with default settings. Coord is text, offset 0, ex: '5,6'
 143       *            Coord 'x,0' is table header
 144       * 'showLines'=> 0,1,2, default is 1 (show outside and top lines only), 2=> lines on each row
 145       * 'showHeadings' => 0 or 1
 146       * 'repeatTableHeader' => 0 or 1, if set to 1, the table header will be repeated when a table stretches over multiple pages. ( default 0 )
 147       * 'shaded'=> 0,1,2,3 default is 1 (1->alternate lines are shaded, 0->no shading, 2-> both shaded, second uses shadeCol2)
 148       * 'shadeCol' => (CMYK) array, defining the colour of the shading
 149       * 'shadeCol2' => (CMYK) array, defining the colour of the shading of the other blocks
 150       * 'fontSize' => 10
 151       * 'textCol' => (CMYK) array, text colour
 152       * 'titleFontSize' => 12
 153       * 'rowGap' => 2 , the space added at the top and bottom of each row, between the text and the lines
 154       * 'colGap' => 5 , the space on the left and right sides of each cell
 155       * 'lineCol' => (r,g,b) array, defining the colour of the lines, default, black.
 156       * 'xPos' => 'left','right','center','centre',or coordinate, reference coordinate in the x-direction
 157       * 'xOrientation' => 'left','right','center','centre', position of the table w.r.t 'xPos'
 158       * 'width'=> <number> which will specify the width of the table, if it turns out to not be this
 159       *    wide, then it will stretch the table to fit, if it is wider then each cell will be made
 160       *    proportionalty smaller, and the content may have to wrap.
 161       * 'maxWidth'=> <number> similar to 'width', but will only make table smaller than it wants to be
 162       * 'options' => array(<colname>=>array('justification'=>'left','width'=>100,'link'=>linkDataName),<colname>=>....)
 163       *             allow the setting of other paramaters for the individual columns
 164       * 'minRowSpace'=> the minimum space between the bottom of each row and the bottom margin, in which a new row will be started
 165       *                  if it is less, then a new page would be started, default=-100
 166       * 'innerLineThickness'=>1
 167       * 'outerLineThickness'=>1
 168       * 'splitRows'=>0, 0 or 1, whether or not to allow the rows to be split across page boundaries
 169       * 'protectRows'=>number, the number of rows to hold with the heading on page, ie, if there less than this number of
 170       *                rows on the page, then move the whole lot onto the next page, default=1
 171       *
 172       * note that the user will have had to make a font selection already or this will not
 173       * produce a valid pdf file.
 174       */
 175      function ezTable(&$data,$cols='',$title='',$options='')
 176      {
 177          include_once ( 'lib/ezutils/classes/ezmath.php' );
 178  
 179          if (!is_array($data)){
 180              return;
 181          }
 182  
 183          $tableStartY = $this->y;
 184  
 185          // Get total column count and column indexes
 186          if (!is_array($cols)){
 187              // take the columns from the first row of the data set
 188              reset($data);
 189              list($k,$v)=each($data);
 190              if (!is_array($v)){
 191                  return;
 192              }
 193              $cols=array();
 194  
 195              $realCount = 0;
 196              for ( $c = 0; $c < count($v); $c++ )
 197              {
 198                  if ( isset( $options['cellData'][$realCount.',0']['size'] ) )
 199                  {
 200                      $incCount = $options['cellData'][$realCount.',0']['size'];
 201                      for ( $innerCount = 0; $innerCount < $incCount; ++$innerCount )
 202                      {
 203                          $cols[$realCount] = $realCount++;
 204                      }
 205                  }
 206                  else
 207                  {
 208                      $cols[$realCount] = $realCount++;
 209                  }
 210              }
 211          }
 212  
 213          if (!is_array($options)){
 214              $options=array();
 215          }
 216  
 217          $defaults = array(
 218              'cellPadding' => 0,
 219              'shaded' => 0,
 220              'showLines' => 1,
 221              'shadeCol' => eZMath::rgbToCMYK2( 0.8, 0.8, 0.8 ),
 222              'shadeCol2' => eZMath::rgbToCMYK2( 0.7, 0.7, 0.7 ),
 223              'repeatTableHeader' => 0,
 224              'fontSize' => 10,
 225              'titleFontSize' => 12,
 226              'titleGap' => 5,
 227              'lineCol' => array( 0, 0, 0 ),
 228              'gap' => 5,
 229              'xPos' => 'centre',
 230              'xOrientation' => 'centre',
 231              'showHeadings' => 1,
 232              'textCol' => eZMath::rgbToCMYK2( 0, 0, 0 ),
 233              'titleTextCMYK' => eZMath::rgbToCMYK2( 0, 0, 0 ),
 234              'width' => 0,
 235              'maxWidth' => 0,
 236              'cols' => array(),
 237              'minRowSpace' => -100,
 238              'rowGap' => 2,
 239              'colGap' => 5,
 240              'innerLineThickness' => 1,
 241              'outerLineThickness' => 1,
 242              'splitRows' => 0,
 243              'protectRows'=> 1,
 244              'firstRowTitle' => false,
 245              'titleFontSize' => 10,
 246              'test' => 0,
 247              'yBottom' => 0 );
 248  
 249          foreach($defaults as $key=>$value){
 250              if (is_array($value)){
 251                  if (!isset($options[$key]) || !is_array($options[$key])){
 252                      $options[$key]=$value;
 253                  }
 254              } else {
 255                  if (!isset($options[$key])){
 256                      $options[$key]=$value;
 257                  }
 258              }
 259          }
 260          $options['gap']=2*$options['colGap'];
 261          $middle = ($this->ez['pageWidth']- $this->rightMargin() - $this->leftMargin() )/2+$this->leftMargin();
 262          // figure out the maximum widths of the text within each column
 263          $maxWidth = array();
 264          $minWidth = array();
 265  
 266          $maxRowCount = 0;
 267          // find the maximum cell widths based on the data
 268          foreach ( $data as $rowCount=>$row)
 269          {
 270              $realColCount = 0;
 271              for( $columnCount = 0; $columnCount < count( $row ); $columnCount++ )
 272              {
 273                  $wMax = 0; // total maximum width of table column
 274                  $wMix = 0; // minimum width of table column
 275                  $data[$rowCount][$columnCount] = $this->fixupTableCellText( $row[$columnCount] );
 276                  $row[$columnCount] = $data[$rowCount][$columnCount];
 277                  // get col span
 278                  $colSpan = 1;
 279                  if ( isset( $options['cellData'][$realColCount.','.$rowCount]['size'] ) )
 280                  {
 281                      $colSpan = $options['cellData'][$realColCount.','.$rowCount]['size'];
 282                  }
 283  
 284                  //get and set max width
 285                  if ( ( $rowCount == 0 && $options['firstRowTitle'] ) ||
 286                       ( isset( $options['cellData'][$realColCount.','.$rowCount]['title'] ) && $options['cellData'][$realColCount.','.$rowCount]['title'] ) )
 287                  {
 288                      $wMax = $this->ezPrvtGetTextWidth( $options['titleFontSize'], (string)$row[$columnCount] ) * 1.01;
 289                      $wMin = $this->eZGetMaxWordWidth( $options['titleFontSize'], (string)$row[$columnCount] ) * 1.01;
 290                      $options['cellData'][$realColCount.','.$rowCount]['title'] = true;
 291                  }
 292                  else
 293                  {
 294                      $wMax = $this->ezPrvtGetTextWidth( $options['fontSize'], (string)$row[$columnCount] ) * 1.01;
 295                      $wMin = $this->eZGetMaxWordWidth( $options['fontSize'], (string)$row[$columnCount] ) * 1.01;
 296                  }
 297  
 298                  if ( isset( $maxWidth[$colSpan][$realColCount] ) )
 299                  {
 300                      if ( $wMax > $maxWidth[$colSpan][$realColCount] )
 301                      {
 302                          $maxWidth[$colSpan][$realColCount] = $wMax;
 303                      }
 304                  }
 305                  else
 306                  {
 307                      if ( !isset( $maxWidth[$colSpan] ) )
 308                      {
 309                          $maxWidth[$colSpan] = array();
 310                      }
 311                      $maxWidth[$colSpan][$realColCount] = $wMax;
 312                  }
 313  
 314                  if ( isset( $minWidth[$colSpan][$realColCount] ) )
 315                  {
 316                      if ( $wMin > $minWidth[$colSpan][$realColCount] )
 317                      {
 318                          $minWidth[$colSpan][$realColCount] = $wMin;
 319                      }
 320                  }
 321                  else
 322                  {
 323                      if ( !isset( $minWidth[$colSpan] ) )
 324                      {
 325                          $minWidth[$colSpan] = array();
 326                      }
 327                      $minWidth[$colSpan][$realColCount] = $wMin;
 328                  }
 329  
 330                  $realColCount += $colSpan;
 331  
 332                  if ( $realColCount > $maxRowCount )
 333                  {
 334                      $maxRowCount = $realColCount;
 335                  }
 336              }
 337          }
 338  
 339          // calculate the start positions of each of the columns
 340          // Set pre defined max column width data
 341          for ( $columnCount = 0; $columnCount < count( $cols ); $columnCount++ ){
 342              if ( isset( $options['cols'][$columnCount] ) && isset($options['cols'][$columnCount]['width']) && $options['cols'][$colName]['width']>0)
 343              {
 344                  $colSpan = 1;
 345                  if ( isset( $options['cellData'][$realColCount.',0']['size'] ) )
 346                  {
 347                      $colSpan = $options['cellData'][$realColCount.',0']['size'];
 348                  }
 349  
 350                  $maxWidth[$colSpan][$columnCount] = $options['cols'][$colName]['width'] - $options['gap'] - 2*$options['cellPadding'];
 351              }
 352          }
 353  
 354          // Scale column widths
 355          $pos=array();
 356          $columnWidths = array();
 357          $minWidthArray = array();
 358          for ( $offset = 0; $offset < count( $cols ); ++$offset )
 359          {
 360              $columnWidths[$offset] = 0;
 361              $minWidthArray[$offset] = 0;
 362          }
 363          $x=0;
 364          $t=$x;
 365          $adjustmentWidth=0;
 366          $setWidth=0;
 367          foreach ( $maxWidth as $span => $tmp1 )
 368          {
 369              foreach ( $maxWidth[$span] as $offset => $tmp2 )
 370              {
 371                  $currentWidth = 0;
 372                  $currentMinWidth = 0;
 373                  for ( $innerCount = 0; $innerCount < $span; $innerCount++ )
 374                  {
 375                      $currentWidth += $columnWidths[$offset+$innerCount];
 376                      $currentMinWidth += $minWidthArray[$offset + $innerCount];
 377                  }
 378                  if ( $maxWidth[$span][$offset] > $currentWidth )
 379                  {
 380                      if ( $currentWidth == 0 ) // no width set
 381                      {
 382                          for ( $i = 0; $i < $span; $i++ )
 383                          {
 384                              $columnWidths[$offset + $i] = ceil( $maxWidth[$span][$offset] / $span );
 385                              $minWidthArray[$offset + $i] = ceil( $minWidth[$span][$offset] / $span );
 386                          }
 387                      }
 388                      else // scale previous set widths
 389                      {
 390                          for ( $i = 0; $i < $span; $i++ )
 391                          {
 392                              $columnWidths[$offset + $i] = ceil( $maxWidth[$span][$offset] / $currentWidth * $columnWidths[$offset+$i] );
 393                              $minWidthArray[$offset + $i] = ceil( $minWidth[$span][$offset] / $currentMinWidth * $minWidthArray[$offset+$i] );
 394                          }
 395                      }
 396                  }
 397              }
 398          }
 399  
 400          $t = 0;
 401          foreach ( $columnWidths as $count => $width )
 402          {
 403              $pos[$count]=$t;
 404              // if the column width has been specified then set that here, also total the
 405              $t += $width + $options['gap'] + 2*$options['cellPadding'];
 406              $adjustmentWidth += $width;
 407              $setWidth += $options['gap'] + 2*$options['cellPadding'];
 408              $pos[$count+1]=$t;
 409          }
 410          $pos['_end_'] = $t;
 411  
 412          // if maxWidth is specified, and the table is too wide, and the width has not been set,
 413          // then set the width.
 414          if ($options['width']==0 && $options['maxWidth'] && $pos['_end_']>$options['maxWidth']){
 415              // then need to make this one smaller
 416              $options['width']=$options['maxWidth'];
 417          }
 418  
 419          // calculate total table width before limiting
 420          $totalTableWidth = 0;
 421          foreach ( array_keys( $columnWidths ) as $idx ){
 422              $totalTableWidth += $columnWidths[$idx];
 423          }
 424  
 425          if ( $options['width'] == 0 &&
 426               $totalTableWidth > $this->ez['pageWidth'] - $this->leftMargin() - $this->rightMargin() )
 427          {
 428              $options['width'] = $this->ez['pageWidth'] - $this->leftMargin() - $this->rightMargin();
 429          }
 430  
 431          // calculated width as forced. Shrink or enlarge.
 432          $newColumnSize = $this->eZCalculateColumnWidth( $columnWidths, $options, $setWidth, $minWidthArray, $adjustmentWidth );
 433          if ( $newColumnSize !== false )
 434          {
 435              $pos = $newColumnSize;
 436              $t = $pos['_end_'];
 437          }
 438  
 439          /* Calculate max column widths */
 440          foreach ( array_keys ( $maxWidth ) as $colspan )
 441          {
 442              foreach ( array_keys( $maxWidth[$colspan] ) as $offset )
 443              {
 444                  $maxWidth[$colspan][$offset] = 0;
 445                  for ( $columnCount = $offset; $columnCount < $offset + $colspan; $columnCount ++ )
 446                  {
 447                      if ( $maxWidth[$colspan][$offset] == 0 )
 448                      {
 449                          $maxWidth[$colspan][$offset] -= ( $options['gap'] + 2*$options['cellPadding'] );
 450                      }
 451                      $maxWidth[$colspan][$offset] += ( $pos[$columnCount + 1] - $pos[$columnCount] );
 452                  }
 453              }
 454          }
 455  
 456          // now adjust the table to the correct location across the page
 457          switch ($options['xPos']){
 458              case 'left':
 459                  $xref = $this->leftMargin();
 460              break;
 461              case 'right':
 462                  $xref = $this->ez['pageWidth'] - $this->rightMargin();
 463              break;
 464              case 'centre':
 465              case 'center':
 466                  $xref = $middle;
 467              break;
 468              default:
 469                  $xref = $options['xPos'];
 470              break;
 471          }
 472          switch ($options['xOrientation']){
 473              case 'left':
 474              case 'right':
 475                  $dx = $xref;
 476              break;
 477              case 'centre':
 478              case 'center':
 479                  $dx = $xref-$t/2;
 480              break;
 481          }
 482  
 483          foreach($pos as $key=>$value){
 484              $pos[$key] += $dx + $options['gap']/2;
 485          }
 486          $x0=$x+$dx + $options['gap']/2;
 487          $x1=$t+$dx + $options['gap']/2;
 488  
 489          $baseLeftMargin = $this->leftMargin();
 490          $basePos = $pos;
 491          $baseX0 = $x0;
 492          $baseX1 = $x1;
 493  
 494          // ok, just about ready to make me a table
 495          $this->setColor( $options['textCol'] );
 496  
 497          $middle = ($x1+$x0)/2;
 498  
 499          // start a transaction which will be used to regress the table, if there are not enough rows protected
 500          if ($options['protectRows']>0){
 501              $this->transaction('start');
 502              $movedOnce=0;
 503          }
 504          $abortTable = 1;
 505  
 506          if ( $options['yBottom'] > 0 ) // for aligning table to bottom
 507          {
 508              $options['test'] = 1;
 509          }
 510  
 511          while ($abortTable){
 512              $abortTable=0;
 513  
 514              $dm = $this->ez['leftMargin']-$baseLeftMargin;
 515              foreach($basePos as $key=>$value){
 516                  $pos[$key] += $dm;
 517              }
 518              $x0=$baseX0+$dm;
 519              $x1=$baseX1+$dm;
 520              $middle = ($x1+$x0)/2;
 521  
 522              // margins may have changed on the newpage
 523              $dm = $this->ez['leftMargin']-$baseLeftMargin;
 524              foreach($basePos as $key => $value){
 525                  $pos[$key] += $dm;
 526              }
 527              $x0=$baseX0+$dm;
 528              $x1=$baseX1+$dm;
 529  
 530              $y=$this->y; // to simplify the code a bit
 531              $startY = $y;
 532  
 533              // make the table
 534              $height = $this->getFontHeight($options['fontSize']);
 535              $decender = $this->getFontDecender($options['fontSize']);
 536  
 537              $y0=$y+$decender;
 538              $dy=0;
 539              if ($options['showHeadings']){
 540                  // this function will move the start of the table to a new page if it does not fit on this one
 541                  $headingHeight = $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
 542                  $y0 = $y+$headingHeight;
 543                  $y1 = $y;
 544  
 545                  $dm = $this->leftMargin()-$baseLeftMargin;
 546                  foreach($basePos as $k=>$v){
 547                      $pos[$k]=$v+$dm;
 548                  }
 549                  $x0=$baseX0+$dm;
 550                  $x1=$baseX1+$dm;
 551  
 552              } else {
 553                  $y1 = $y0;
 554              }
 555              $firstLine=1;
 556  
 557  
 558              $isHelperObjectNeeded = ( !$options['test'] && ( $options['shaded'] || isset( $options['titleCellCMYK'] ) ) );
 559              // open an object here so that the text can be put in over the shading
 560              if ( $isHelperObjectNeeded ){
 561                  $this->saveState();
 562                  $textObjectId = $this->openObject();
 563                  $this->closeObject();
 564                  $this->addObject($textObjectId);
 565                  $this->reopenObject($textObjectId);
 566              }
 567  
 568              $cnt=0;
 569              $newPage=0;
 570              $newPageLine = 0;
 571              $tableHeaderRow = array();
 572              $maxRowCount = count( $data );
 573              $oldRowCount = -1;
 574  
 575              $leftOvers=array();
 576  
 577              for ( $rowCount = 0; $rowCount < $maxRowCount; ++$rowCount )
 578              {
 579                  if ( $oldRowCount != -1)
 580                  {
 581                      $rowCount = $oldRowCount;
 582                      $oldRowCount = -1;
 583                  }
 584  
 585                  $row = $data[$rowCount];
 586  
 587                  $cnt++;
 588                  // the transaction support will be used to prevent rows being split
 589                  if ($options['splitRows']==0){
 590                      $pageStart = $this->ezPageCount;
 591                      if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){
 592                          $columnStart = $this->ez['columns']['colNum'];
 593                      }
 594                      if ( !$options['test'] )
 595                      {
 596                          $this->transaction('start');
 597                      }
 598                      $row_orig = $data[$rowCount];
 599                      $y_orig = $y;
 600                      $y0_orig = $y0;
 601                      $y1_orig = $y1;
 602                  }
 603                  $ok=0;
 604                  $secondTurn=0;
 605                  while(!$abortTable && $ok == 0){
 606  
 607                      $maxRowHeight=0;
 608                      $newRow=1;
 609                      while(!$abortTable && ($newPage || $newRow)){
 610  
 611                          $resetLeftOvers = true;
 612                          if ( count( $leftOvers ) > 0 )
 613                              $row = $leftOvers;
 614  
 615                          if ($newPage || $y<$this->ez['bottomMargin'] || (isset($options['minRowSpace']) && $y<($this->ez['bottomMargin']+$options['minRowSpace'])) ){
 616                              // check that enough rows are with the heading
 617                              if ($options['protectRows']>0 && $movedOnce==0 && $cnt<=$options['protectRows']){
 618                                  // then we need to move the whole table onto the next page
 619                                  $movedOnce = 1;
 620                                  $abortTable = 1;
 621                              }
 622  
 623                              $y2=$y-$maxRowHeight+2*$height+$decender-$newRow*$height;
 624                              if ($options['showLines']){
 625                                  if (!$options['showHeadings']){
 626                                      $y0=$y1;
 627                                  }
 628                              }
 629                              if ( $isHelperObjectNeeded )
 630                              {
 631                                  $this->closeObject();
 632                                  $this->restoreState();
 633                              }
 634                              $this->ezNewPage();
 635                              // and the margins may have changed, this is due to the possibility of the columns being turned on
 636                              // as the columns are managed by manipulating the margins
 637  
 638                              $dm = $this->leftMargin()-$baseLeftMargin;
 639                              foreach($basePos as $k=>$v){
 640                                  $pos[$k]=$v+$dm;
 641                              }
 642  
 643                              $x0=$baseX0+$dm;
 644                              $x1=$baseX1+$dm;
 645  
 646                              if ( $isHelperObjectNeeded )
 647                              {
 648                                  $this->saveState();
 649                                  $textObjectId = $this->openObject();
 650                                  $this->closeObject();
 651                                  $this->addObject($textObjectId);
 652                                  $this->reopenObject($textObjectId);
 653                              }
 654                              $this->setColor( $options['textCol'], 1 );
 655                              $y = $this->ez['pageHeight']-$this->ez['topMargin'];
 656                              $y0=$y+$decender;
 657                              $maxRowHeight=0;
 658                              if ($options['showHeadings']){
 659                                  $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
 660                                  $y1=$y;
 661                              } else {
 662                                  $y1=$y0;
 663                              }
 664                              $firstLine=1;
 665                              $y -= $height;
 666  
 667                              if ( $options['repeatTableHeader'] && $oldRowCount == -1)
 668                              {
 669                                  $oldRowCount = $rowCount;
 670                                  $rowCount = 0;
 671                                  $row = $data[$rowCount];
 672                                  $resetLeftOvers = false;
 673                              }
 674                          }
 675  
 676                          $newRow=0;
 677                          // write the actual data
 678                          // if these cells need to be split over a page, then $newPage will be set, and the remaining
 679                          // text will be placed in $leftOvers
 680                          $newPage=0;
 681                          if ( $resetLeftOvers )
 682                              $leftOvers=array();
 683  
 684                          $realColumnCount = 0;
 685  
 686                          $bgTitleX = 2147483647;
 687                          $bgTitleY = -2147483647;
 688                          $bgTitleW = 0;
 689                          $bgTitleH = 0;
 690  
 691                          for ( $columnCount = 0; $columnCount < count ( $row ); $columnCount++ )
 692                          {
 693                              // Get colSpan
 694                              if ( isset( $options['cellData'][$realColumnCount.','.$rowCount]['size'] ) )
 695                              {
 696                                  $colSpan = $options['cellData'][$realColumnCount.','.$rowCount]['size'];
 697                              }
 698                              else
 699                              {
 700                                  $colSpan = 1;
 701                              }
 702  
 703                              $this->ezSetY($y+$height);
 704                              $colNewPage=0;
 705  
 706                              $row[$columnCount] = $this->fixWhitespace( $row[$columnCount] );
 707                              $lines = explode("\n",$row[$columnCount]);
 708                              $this->y -= $options['rowGap'] + $options['cellPadding'];
 709                              $this->setXOffset( $pos[$realColumnCount] );
 710                              $leftMargin = $this->ez['leftMargin'];
 711                              $this->ez['leftMargin'] = $pos[$realColumnCount];
 712  
 713                              foreach ($lines as $line)
 714                              {
 715                                  $line = $this->ezProcessText($line);
 716                                  $start=1;
 717  
 718                                  while (strlen($line) || $start){
 719                                      $start=0;
 720                                      if (!$colNewPage){
 721                                          $this->y-=$height;
 722                                      }
 723                                      if ($this->y < $this->ez['bottomMargin']){
 724                                          $newPage=1;
 725                                          $newPageLine = 1;
 726                                          $colNewPage=1;
 727                                      }
 728                                      if ($colNewPage){
 729                                          if (isset($leftOvers[$realColumnCount])){
 730                                              $leftOvers[$realColumnCount].="\n".$line;
 731                                          } else {
 732                                              $leftOvers[$realColumnCount] = $line;
 733                                          }
 734                                          $line='';
 735                                      } else {
 736                                          if (isset($options['cols'][$realColumnCount]) && isset($options['cols'][$realColumnCount]['justification']) ){
 737                                              $just = $options['cols'][$realColumnCount]['justification'];
 738                                          } else {
 739                                              $just='left';
 740                                          }
 741                                          $storeY = $this->y;
 742                                          if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
 743                                               $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true )
 744                                          {
 745                                              $this->setColor( $options['titleTextCMYK'] );
 746                                              $fontSize = $options['titleFontSize'];
 747                                          }
 748                                          else
 749                                          {
 750                                              $this->setColor( $options['textCol'], 1 );
 751                                              $fontSize = $options['fontSize'];
 752                                          }
 753  
 754                                          $textInfo = $this->addTextWrap( $pos[$realColumnCount],
 755                                                                          $this->y,
 756                                                                          $maxWidth[$colSpan][$realColumnCount],
 757                                                                          $fontSize,
 758                                                                          $line,
 759                                                                          $just,
 760                                                                          0,
 761                                                                          $options['test'] );
 762  
 763                                          $this->y = $storeY;
 764                                          if ( isset( $textInfo['text'] ) )
 765                                              $line = $textInfo['text'];
 766                                          else
 767                                              $line = '';
 768  
 769                                          if ( $line == '' )
 770                                          {
 771                                              if ( isset( $textInfo['height'] ) )
 772                                                  $this->y -= $textInfo['height'];
 773                                          }
 774                                      }
 775                                  }
 776                              }
 777                              $this->ez['leftMargin'] = $leftMargin;
 778  
 779                              $dy=$y-$this->y+$options['rowGap']+$options['cellPadding'];
 780                              if ($dy>$maxRowHeight)
 781                              {
 782                                  $maxRowHeight=$dy;
 783                              }
 784  
 785                              /////////////////////////////////////////////////////////////////
 786                              // calc title's background rect
 787                              /////////////////////////////////////////////////////////////////
 788                              if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
 789                                   $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true &&
 790                                   isset( $options['titleCellCMYK'] ) )
 791                              {
 792                                  $cellX = $pos[$realColumnCount] - $options['gap']/2;
 793                                  $cellY = $y+$decender+$height;
 794                                  $cellW = $maxWidth[$colSpan][$realColumnCount] + $options['gap'];
 795                                  $cellH = -$maxRowHeight;
 796  
 797                                  if ( $bgTitleX > $cellX )
 798                                      $bgTitleX = $cellX;
 799  
 800                                  if ( $bgTitleY < $cellY )
 801                                      $bgTitleY = $cellY;
 802  
 803                                  $bgTitleW += $cellW;
 804  
 805                                  if ( $bgTitleH > $cellH )
 806                                      $bgTitleH = $cellH;
 807                              }
 808                              /////////////////////////////////////////////////////////////////
 809  
 810                              $realColumnCount += $colSpan;
 811  
 812                          } // End for ( ... count( $row ) ... )
 813  
 814                          if ( !$options['test'] )
 815                          {
 816                              ////////////////////////////////////////////////////////////
 817                              // draw title's background
 818                              ////////////////////////////////////////////////////////////
 819                              if( $bgTitleW != 0 && $bgTitleH != 0 )
 820                              {
 821                                  // we have non-empty rect
 822                                  $this->closeObject();
 823                                  $this->setColor( $options['titleCellCMYK'], true );
 824                                  $this->filledRectangle( $bgTitleX, $bgTitleY, $bgTitleW, $bgTitleH );
 825                                  $this->reopenObject($textObjectId);
 826                              }
 827                              ////////////////////////////////////////////////////////////
 828  
 829                              if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
 830                                   $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true )
 831                              {
 832                                  $shadeCol = $options['titleCellCMYK'];
 833                              }
 834                              else
 835                              {
 836                                  if( $cnt % 2 == 0 )
 837                                  {
 838                                      $shadeCol = $options['shadeCol'];
 839                                  }
 840                                  else
 841                                  {
 842                                      $shadeCol = $options['shadeCol2'];
 843                                  }
 844                              }
 845  
 846                              $rowHeight = $maxRowHeight;
 847                              $realColumnCount = 0;
 848                              for ( $columnCount = 0; $realColumnCount < $maxRowCount; $columnCount++ )
 849                              {
 850                                  if ( isset( $options['cellData'][$realColumnCount.','.$rowCount]['size'] ) )
 851                                  {
 852                                      $colSpan = $options['cellData'][$realColumnCount.','.$rowCount]['size'];
 853                                  }
 854                                  else
 855                                  {
 856                                      $colSpan = 1;
 857                                  }
 858  
 859                                  if ( $options['shaded'] && $cnt % 2 == 0 )
 860                                  {
 861                                      $this->closeObject();
 862                                      $this->setColor( $shadeCol );
 863                                      $this->filledRectangle($pos[$realColumnCount] - $options['cellPadding'],
 864                                                             $y,
 865                                                             $maxWidth[$colSpan][$realColumnCount] + 2*$options['cellPadding'],
 866                                                             -$rowHeight );
 867                                      $this->reopenObject($textObjectId);
 868                                  }
 869  
 870                                  if ($options['shaded']==2 && $cnt%2==1){
 871                                      $this->closeObject();
 872                                      $this->setColor( $shadeCol );
 873                                      $this->filledRectangle($pos[$realColumnCount] - $options['cellPadding'],
 874                                                             $y,
 875                                                             $maxWidth[$colSpan][$realColumnCount] + 2*$options['cellPadding'],
 876                                                             -$rowHeight );
 877                                      $this->reopenObject($textObjectId);
 878                                  }
 879  
 880                                  $realColumnCount += $colSpan;
 881                              }
 882  
 883                              // now add the shading underneath
 884                              // Draw lines for each row and above
 885                              if ( $options['showLines'] > 0 )
 886                              {
 887                                  $this->saveState();
 888                                  $this->setStrokeColorRGB($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);
 889  
 890                                  if ( $rowCount == 0 || $newPageLine == 1 )
 891                                  {
 892                                      $this->line( $x0-$options['gap']/2, $y+$decender+$height, $x1-$options['gap']/2, $y+$decender+$height );
 893                                  }
 894                                  $this->line( $x0-$options['gap']/2, $y+$decender+$height, $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
 895                                  $this->line( $x1-$options['gap']/2, $y+$decender+$height, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
 896  
 897                                  if ( $options['showLines'] > 1 )
 898                                  {
 899                                      // draw inner lines
 900                                      $this->line( $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
 901  
 902                                      for ( $posOffset = 0; $posOffset < count( $pos ) - 2; )
 903                                      {
 904                                          $colSpan = 1;
 905                                          if ( isset( $options['cellData'][$posOffset.','.$rowCount]['size'] ) )
 906                                          {
 907                                              $colSpan = $options['cellData'][$posOffset.','.$rowCount]['size'];
 908                                          }
 909                                          $this->line( $pos[$posOffset+$colSpan]-$options['gap']/2, $y+$decender+$height,
 910                                                       $pos[$posOffset+$colSpan]-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
 911                                          $posOffset += $colSpan;
 912                                      }
 913                                  }
 914                                  else if ( $rowCount == count( $data ) - 1 )
 915                                  {
 916                                      $this->line( $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
 917                                  }
 918                                  $this->restoreState();
 919                              }
 920                              if ($options['showLines']>1){
 921                                  $this->saveState();
 922                                  $this->setStrokeColorRGB($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);
 923  
 924                                  if ($firstLine){
 925                                      $this->setLineStyle($options['outerLineThickness']);
 926                                      $firstLine=0;
 927                                  } else {
 928                                      $this->setLineStyle($options['innerLineThickness']);
 929                                  }
 930                                  $this->line($x0-$options['gap']/2,$y+$decender+$height-$maxRowHeight,$x1-$options['gap']/2,$y+$decender+$height-$maxRowHeight);
 931                                  $this->restoreState();
 932                              }
 933                          }
 934                      } // end of while
 935                      $y=$y-$maxRowHeight;
 936  
 937                      // checking row split over pages
 938                      if ( $options['splitRows'] == 0 )
 939                      {
 940                          if ( ( ($this->ezPageCount != $pageStart) || (isset($this->ez['columns']) && $this->ez['columns']['on']==1 && $columnStart != $this->ez['columns']['colNum'] ))  && $secondTurn==0){
 941                              // then we need to go back and try that again !
 942                              $newPage=1;
 943                              $newPageLine = 1;
 944                              $secondTurn=1;
 945                              $this->transaction('rewind');
 946                              $row = $row_orig;
 947                              $y = $y_orig;
 948                              $y0 = $y0_orig;
 949                              $y1 = $y1_orig;
 950                              $ok=0;
 951  
 952                              $dm = $this->leftMargin()-$baseLeftMargin;
 953                              foreach($basePos as $k=>$v){
 954                                  $pos[$k]=$v+$dm;
 955                              }
 956                              $x0=$baseX0+$dm;
 957                              $x1=$baseX1+$dm;
 958  
 959                          } else {
 960                              $this->transaction('commit');
 961                              $ok=1;
 962                          }
 963                      }
 964                      else
 965                      {
 966                          $ok=1;  // don't go round the loop if splitting rows is allowed
 967                      }
 968  
 969                  }  // end of while to check for row splitting
 970                  if ($abortTable){
 971                      if ($ok==0){
 972                          $this->transaction('abort');
 973                      }
 974                      // only the outer transaction should be operational
 975                      $this->transaction('rewind');
 976                      $this->ezNewPage();
 977                      break;
 978                  }
 979  
 980              } // end of ( ... $rowCount < $maxRowCount ... )
 981  
 982              if ( isset ( $options['yBottom'] ) && $options['yBottom'] > 0 )
 983              {
 984                  $tableHeight = $startY - $y;
 985                  $this->y = $options['yBottom'] + $tableHeight;
 986                  $yBottom = $options['yBottom'];
 987                  unset( $options['yBottom'] );
 988                  $options['test'] = 0;
 989                  $this->transaction('rewind');
 990  //                $this->transaction('start');
 991                  $abortTable = 1;
 992                  continue;
 993              }
 994  
 995          } // end of while ($abortTable)
 996  
 997          // table has been put on the page, the rows guarded as required, commit.
 998          $this->transaction('commit');
 999  
1000          $y2=$y+$decender;
1001          if ($options['showLines']){
1002              if (!$options['showHeadings']){
1003                  $y0=$y1;
1004              }
1005  //            $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);
1006          }
1007  
1008          // close the object for drawing the text on top
1009          if ( $isHelperObjectNeeded ){
1010              $this->closeObject();
1011              $this->restoreState();
1012          }
1013  
1014          if ( $options['overwrite'] > 0 )
1015          {
1016              $this->y=$tableStartY;
1017          }
1018          else
1019          {
1020              $this->y=$y;
1021          }
1022  
1023          return $this->y;
1024      }
1025  
1026      /*!
1027       \private
1028       Calculate Table column widths
1029  
1030       \param ColumnWidth Array
1031       \param Table options
1032       \param Total Width
1033       \param Margin Width
1034       \param minimum Table width Array
1035       \param Position array ( for private use only ).
1036       \return Array of fixed column sizes ( returned )
1037      */
1038      function eZCalculateColumnWidth( $columnWidthArray,
1039                                       $options,
1040                                       $marginWidth,
1041                                       $minWidthArray,
1042                                       $totalWidth,
1043                                       $fixedSizeArray = array() )
1044      {
1045          $newWidth = 0;
1046          if ( $options['width'] && $totalWidth>0 ){
1047              $newCleanWidth = $options['width'] - $marginWidth;
1048              $t = 0;
1049              $pos = array();
1050              foreach ( $columnWidthArray as $count => $width )
1051              {
1052                  $pos[$count] = $t;
1053  
1054                  if ( isset( $fixedSizeArray[(string)$count] ) )
1055                  {
1056                      $t += $fixedSizeArray[(string)$count] + $options['gap'] + 2*$options['cellPadding'];
1057                      continue;
1058                  }
1059  
1060                  $newWidth = round( $newCleanWidth/$totalWidth * $columnWidthArray[$count] );
1061  
1062                  if ( $newWidth < $minWidthArray[$count] &&
1063                       count( $fixedSizeArray ) < count( $columnWidthArray ) )
1064                  {
1065                      $fixedSizeArray[(string)$count] = $minWidthArray[$count];
1066  
1067                      return $this->eZCalculateColumnWidth( $columnWidthArray,
1068                                                            $options,
1069                                                            $marginWidth + $minWidthArray[$count],
1070                                                            $minWidthArray,
1071                                                            $totalWidth - $minWidthArray[$count],
1072                                                            $fixedSizeArray );
1073                  }
1074                  $t += $newWidth + $options['gap'] + 2*$options['cellPadding'];
1075              }
1076              $pos[]=$t;
1077              $pos['_end_']=$t;
1078              return $pos;
1079          }
1080  
1081          return false;
1082      }
1083  
1084      function ezPrvtTableDrawLines($pos,$gap,$x0,$x1,$y0,$y1,$y2,$col,$inner,$outer,$opt=1){
1085          $x0=1000;
1086          $x1=0;
1087          $this->setStrokeColorRGB($col[0],$col[1],$col[2]);
1088          $cnt=0;
1089          $n = count($pos);
1090          foreach($pos as $x){
1091              $cnt++;
1092              if ($cnt==1 || $cnt==$n){
1093                  $this->setLineStyle($outer);
1094              } else {
1095                  $this->setLineStyle($inner);
1096              }
1097              $this->line($x-$gap/2,$y0,$x-$gap/2,$y2);
1098              if ($x>$x1){ $x1=$x; };
1099              if ($x<$x0){ $x0=$x; };
1100          }
1101          $this->setLineStyle($outer);
1102          $this->line($x0-$gap/2-$outer/2,$y0,$x1-$gap/2+$outer/2,$y0);
1103          // only do the second line if it is different to the first, AND each row does not have
1104          // a line on it.
1105          if ($y0!=$y1 && $opt<2){
1106              $this->line($x0-$gap/2,$y1,$x1-$gap/2,$y1);
1107          }
1108          $this->line($x0-$gap/2-$outer/2,$y2,$x1-$gap/2+$outer/2,$y2);
1109      }
1110  
1111      /**
1112       * Callback function to set anchor
1113       */
1114      function callAnchor( $info )
1115      {
1116          $paramArray = explode( ':', $info['p'] );
1117  
1118          $this->addDestination( $paramArray[0], $paramArray[1], $this->yOffset() + $this->getFontHeight( $this->fontSize ) );
1119      }
1120  
1121      /**
1122       * Callback function to set header
1123       */
1124      function callHeader( $params )
1125      {
1126          $options = array();
1127  
1128          if ( isset( $params['size'] ) )
1129          {
1130              $options['fontSize'] = $params['size'];
1131          }
1132  
1133          if ( isset( $params['justification'] ) )
1134          {
1135              $options['justification'] = $params['justification'];
1136          }
1137  
1138          if ( isset( $params['fontName'] ) )
1139          {
1140              $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['fontName'];
1141          }
1142  
1143          $this->addToPreStack( $options );
1144  
1145          $label = $params['label'];
1146          $level = $params['level'];
1147  
1148          return '<C:callInsertTOC:'. $label .','. $level .'>';
1149      }
1150  
1151      /**
1152       * Function for insert image
1153       */
1154      function callImage( $info )
1155      {
1156          $params = array();
1157          $leftMargin = false;
1158          $rightMargin = false;
1159  
1160          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1161  
1162          $filename = rawurldecode( $params['src'] );
1163  
1164          include_once ( 'lib/ezutils/classes/ezmimetype.php' );
1165          $mimetype = eZMimeType::findByFileContents( $filename );
1166  
1167          $this->transaction( 'start' );
1168  
1169          if ( !isset( $params['static'] ) )
1170          {
1171              $params['static'] = false;
1172          }
1173  
1174          if ( $this->yOffset()-$params['height'] < $this->ez['bottomMargin'] )
1175          {
1176              $this->ezNewPage();
1177          }
1178  
1179          if ( isset( $params['dpi'] ) )
1180          {
1181              include_once ( 'kernel/common/image.php' );
1182  
1183              $newWidth = (int)( $params['width'] * ( (int)$params['dpi'] / 72 ) );
1184              $newHeight = (int)( $params['height'] * ( (int)$params['dpi'] / 72 ) );
1185              $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
1186              while( file_exists( $newFilename ) )
1187              {
1188                  $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
1189              }
1190              $img =& imageInit();
1191              $newImg = $img->convert( $filename,
1192                                       $newFilename,
1193                                       false,
1194                                       array( 'filters' => array( array( 'name' => 'geometry/scaledownonly',
1195                                                                         'data' => array( $newWidth, $newHeight ) ) ) ) );
1196              $filename = $newFilename['url'];
1197          }
1198  
1199          $drawableAreaWidth = $this->ez['pageWidth'] - $this->ez['leftMargin'] - $this->ez['rightMargin'];
1200  
1201          switch( $params['align'] )
1202          {
1203              case 'right':
1204              {
1205                  $xOffset = $this->ez['pageWidth'] - ( $this->rightMargin() + $params['width'] );
1206                  $rightMargin = $this->rightMargin() + $params['width'];
1207                  if ( $rightMargin > ( $drawableAreaWidth + $this->rightMargin() ) )
1208                  {
1209                      // the image is equal or larger then width of the page(of the drawable area) => no point
1210                      // to set $rightMargin and next object(text, image, ...) should be outputted below the image.
1211                      $rightMargin = false;
1212                  }
1213              } break;
1214  
1215              case 'center':
1216              {
1217                  $xOffset = ( $this->ez['pageWidth'] - $this->rightMargin() - $this->leftMargin() ) / 2 + $this->leftMargin() - $params['width'] / 2;
1218              } break;
1219  
1220              case 'left':
1221              default:
1222              {
1223                  $xOffset = $this->leftMargin();
1224                  $leftMargin = $this->leftMargin() + $params['width'];
1225                  if ( $leftMargin > ( $drawableAreaWidth + $this->leftMargin() ) )
1226                  {
1227                      // the image is equal or larger then width of the page(of the drawable area) => no point
1228                      // to set $leftMargin and next object(text, image, ...) should be outputted below the image.
1229                      $leftMargin = false;
1230                  }
1231  
1232              } break;
1233          }
1234  
1235          if ( isset( $params['x'] ) )
1236          {
1237              $xOffset = $params['x'];
1238              $leftMargin = false;
1239              $rightMargin = false;
1240          }
1241  
1242          $yOffset = $this->yOffset();
1243          $whileCount = 0;
1244  
1245          if ( $params['width'] < $drawableAreaWidth )
1246          {
1247              while ( $this->leftMargin( $yOffset ) > $xOffset &&
1248                      ++$whileCount < 100 )
1249              {
1250                  $yOffset -= 10;
1251              }
1252          }
1253  
1254          $yOffset -= $params['height'];
1255          $yOffset += $this->lineHeight()/2;
1256          if ( isset( $params['y'] ) )
1257          {
1258              $yOffset = $params['y'];
1259          }
1260  
1261          if ( $leftMargin !== false )
1262          {
1263              $this->setLimitedLeftMargin( $yOffset - 7, $yOffset + $params['height'] + 7, $leftMargin + 7 );
1264          }
1265          if ( $rightMargin !== false )
1266          {
1267              $this->setLimitedRightMargin( $yOffset- 7, $yOffset + $params['height'] + 7, $rightMargin + 7 );
1268          }
1269  
1270          switch( $mimetype['name'] )
1271          {
1272              case 'image/gif':
1273              {
1274                  $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
1275                  while( file_exists( $newFilename ) )
1276                  {
1277                      $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
1278                  }
1279                  $newMimetype = eZMimeType::findByURL( $newFilename );
1280  
1281                  $img =& imageInit();
1282                  $newImg = $img->convert( $mimetype,
1283                                           $newMimetype,
1284                                           false,
1285                                           array() );
1286                  $this->addJpegFromFile( $newMimetype['url'],
1287                                          $xOffset,
1288                                          $yOffset,
1289                                          $params['width'],
1290                                          $params['height'] );
1291              } break;
1292  
1293              case 'image/jpeg':
1294              {
1295                  $this->addJpegFromFile( $filename,
1296                                          $xOffset,
1297                                          $yOffset,
1298                                          $params['width'],
1299                                          $params['height'] );
1300              } break;
1301  
1302              case 'image/png':
1303              {
1304                  if ( $this->addPngFromFile( $filename,
1305                                              $xOffset,
1306                                              $yOffset,
1307                                              $params['width'],
1308                                              $params['height'] ) === false )
1309                  {
1310                      $this->transaction('abort');
1311                      return;
1312                  }
1313              } break;
1314  
1315              default:
1316              {
1317                  eZDebug::writeError( 'Unsupported image file type, '. $mimetype['name'], 'eZPDFTable::callImage' );
1318                  $this->transaction( 'abort' );
1319                  return;
1320              } break;
1321          }
1322  
1323          $this->transaction( 'commit' );
1324  
1325          if ( !$leftMargin && !$rightMargin  && !$params['static'] )
1326          {
1327              $this->y -= $params['height'] + $this->lineHeight();
1328          }
1329  
1330          return array( 'y' => $params['height'] + $this->lineHeight() );
1331      }
1332  
1333  
1334      /**
1335       * function for inserting keyword
1336       */
1337      function callKeyword( $info )
1338      {
1339          $keyWord = $this->fixWhitespace( rawurldecode( $info['p'] ) );
1340          $page = $this->ezWhatPageNumber($this->ezGetCurrentPageNumber());
1341  
1342          if ( !isset( $this->KeywordArray[$keyWord] ) )
1343          {
1344              $this->KeywordArray[$keyWord] = array();
1345          }
1346  
1347          if ( !isset( $this->KeywordArray[$keyWord][(string)$page] ) )
1348          {
1349              $label = $info['p'] .':'. $page;
1350              $this->KeywordArray[$keyWord][(string)$page] = array( 'label' => $label );
1351  
1352              $this->addDestination( 'keyword:'.$label,
1353                                     'FitH',
1354                                     $this->yOffset() );
1355          }
1356      }
1357  
1358      /**
1359       * function for inserting TOC
1360       */
1361      function callInsertTOC( $info )
1362      {
1363          $params = explode( ',', $info['p'] );
1364  
1365          $label = $params[0];
1366          $level = $params[1];
1367  
1368          $tocCount = count( $this->TOC );
1369          $this->TOC[] = array( 'label' => $this->fixWhitespace( rawurldecode( $label ) ),
1370                                'localPageNumber' => $this->ezWhatPageNumber( $this->ezGetCurrentPageNumber() ),
1371                                'level' => $level,
1372                                'pageNumber' => $this->ezGetCurrentPageNumber() );
1373          $this->addDestination( 'toc'. $tocCount,
1374                                 'FitH',
1375                                 $this->yOffset() + $this->getFontHeight( $this->fontSize() ) );
1376      }
1377  
1378      /**
1379       * Callback function for inserting TOC
1380       */
1381      function callTOC( $info )
1382      {
1383          $params = array();
1384  
1385          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1386  
1387          $sizes = isset( $params['size'] ) ? explode( ',', $params['size'] ) : '';
1388          $indents = isset( $params['indent'] ) ? explode( ',', $params['indent'] ) : '';
1389          $dots = isset( $params['dots'] ) ? $params['dots'] : '';
1390          $contentText = isset( $params['contentText'] ) ? $params['contentText'] : ezi18n( 'lib/ezpdf/classes', 'Contents', 'Table of contents' );
1391  
1392          $this->insertTOC( $sizes, $indents, $dots, $contentText );
1393      }
1394  
1395      /**
1396       * Callback function for creating new page
1397       */
1398      function callNewPage( $info )
1399      {
1400          $this->ezNewPage();
1401      }
1402  
1403      function callIndex( $info )
1404      {
1405          $this->ezNewPage();
1406          $fontSize = $this->fontSize();
1407          Cezpdf::ezText( ezi18n( 'lib/ezpdf/classes', 'Index', 'Keyword index name' ) . '<C:callInsertTOC:Index,1>'."\n", 26, array('justification'=>'centre'));
1408  
1409          if ( count( $this->KeywordArray ) == 0 )
1410              return;
1411  
1412          ksort( $this->KeywordArray );
1413          reset( $this->KeywordArray );
1414  
1415          $this->ezColumnsStart( array( 'num' => 2 ) );
1416  
1417          foreach( array_keys( $this->KeywordArray ) as $keyWord )
1418          {
1419              Cezpdf::ezText( $keyWord,
1420                              $fontSize,
1421                              array( 'justification' => 'left' ) );
1422  
1423              foreach( array_keys( $this->KeywordArray[$keyWord] ) as $page )
1424              {
1425                  Cezpdf::ezText( '<c:ilink:keyword:'. $this->KeywordArray[$keyWord][$page]['label'] .'> '. $page .'</c:ilink>',
1426                                  $fontSize,
1427                                  array( 'justification' => 'right' ) );
1428              }
1429          }
1430  
1431          $this->ezColumnsStop();
1432          $this->setFontSize( $fontSize );
1433      }
1434  
1435      /*!
1436       Create Table Of Contents (TOC)
1437  
1438       \param size array, element 0 define size of header level 1, etc.
1439       \param indent, element 0 define indent of header level 1, etc.
1440       \param dots, if true, generate dots between name and pagenumber
1441       \param content text
1442       \param level, how many header levels to generate toc form
1443      */
1444      function insertTOC( $sizeArray = array( 20, 18, 16, 14, 12 ),
1445                          $indentArray = array( 0, 4, 6, 8, 10 ),
1446                          $dots = true,
1447                          $contentText = '',
1448                          $level = 3 )
1449      {
1450          $fontSize = $this->fontSize();
1451          $this->ezStopPageNumbers(1,1);
1452  
1453          $this->ezInsertMode(1,1,'before');
1454          $this->ezNewPage();
1455          Cezpdf::ezText( $contentText ."\n", 26, array('justification'=>'centre'));
1456  
1457          foreach($this->TOC as $k=>$v){
1458              if ( $v['level'] <= $level )
1459              {
1460                  if ( $dots )
1461                  {
1462                      Cezpdf::ezText( '<c:ilink:toc'. $k .'>'. $v['label'] .'</c:ilink>',
1463                                      $sizeArray[$v['level']-1],
1464                                      array( 'left' => $indentArray[$v['level']-1],
1465                                             'right' => 100 ) );
1466                      Cezpdf::ezText( '<C:dots:'. $sizeArray[$v['level']-1].$v['localPageNumber'] .'>',
1467                                      $sizeArray[$v['level']-1] );
1468                      Cezpdf::ezText( "\n", $sizeArray[$v['level']-1] );
1469                  }
1470                  else
1471                  {
1472                      Cezpdf::ezText( '<c:ilink:toc'. $k .'>'.$v['label'].'</c:ilink>',
1473                                      $sizeArray[$v['level']-1],
1474                                      array( 'left' => $indentArray[$v['level']-1] ) );
1475                      Cezpdf::ezText( '<c:ilink:toc'. $k .'>'. $v['localPageNumber'] .'</c:ilink>',
1476                                      $sizeArray[$v['level']-1],
1477                                      array( 'justification' => 'right' ) );
1478                  }
1479              }
1480          }
1481  
1482          $this->setFontSize( $fontSize );
1483          $this->ezInsertMode(0);
1484      }
1485  
1486      function dots($info)
1487      {
1488          // draw a dotted line over to the right and put on a page number
1489          $tmp = $info['p'];
1490          $size = substr($tmp, 0, 2);
1491          $thick=1;
1492          $lbl = substr($tmp,2);
1493          $xpos = $this->ez['pageWidth'] - $this->rightMargin() - $this->leftMargin();
1494  
1495          $this->saveState();
1496          $this->setLineStyle($thick,'round','',array(0,10));
1497          $this->line($xpos,$info['y'],$info['x']+5,$info['y']);
1498          $this->restoreState();
1499          $this->addText($xpos+5,$info['y'],$size,$lbl);
1500          $this->setXOffset( $xpos+5+$this->getTextWidth($lbl, $size) );
1501      }
1502  
1503      /**
1504       * Callback function to set font
1505       */
1506      function callFont( $params )
1507      {
1508          $options = array();
1509  
1510          $keyArray = array ( 'c', 'm', 'y', 'k' );
1511          if ( isset( $params['cmyk'] ) )
1512          {
1513              $params['cmyk'] = explode( ',', $params['cmyk'] );
1514              foreach ( array_keys( $params['cmyk'] ) as $key )
1515              {
1516                  $options['cmyk'][$keyArray[$key]] = $params['cmyk'][$key];
1517              }
1518              $this->setStrokeColor( $params['cmyk'] );
1519          }
1520  
1521          if ( isset( $params['name'] ) )
1522          {
1523              $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['name'];
1524          }
1525  
1526          if ( isset( $params['size'] ) )
1527          {
1528              $options['fontSize'] = $params['size'];
1529          }
1530  
1531          if ( isset( $params['justification'] ) )
1532          {
1533              $options['justification'] = $params['justification'];
1534          }
1535  
1536          $this->addToPreStack( $options );
1537  
1538          return '';
1539      }
1540  
1541      function &fixWhitespace( &$text )
1542      {
1543          $text = str_replace( array( EZ_PDF_LIB_SPACE,
1544                                      EZ_PDF_LIB_TAB,
1545                                      EZ_PDF_LIB_NEWLINE ),
1546                               array( ' ',
1547                                      "\t",
1548                                      "\n" ),
1549                               $text );
1550          return $text;
1551      }
1552  
1553      /**
1554       * Function overriding the default ezText function for doing preprocessing of text
1555       */
1556      function ezText( $text, $size=0, $options=array(), $test=0)
1557      {
1558          $text = eZPDFTable::fixWhitespace( $text );
1559  
1560          $textLen = strlen( $text );
1561          $newText = '';
1562          for ( $offSet = 0; $offSet < $textLen; $offSet++ )
1563          {
1564              if ( $text[$offSet] == '<' )
1565              {
1566                  if ( strcmp( substr($text, $offSet+1, strlen( 'ezCall' ) ), 'ezCall' ) == 0 ) // ez library preprocessing call.
1567                  {
1568                      $newTextLength = strlen( $newText );
1569                      if ( $newTextLength > 0 && $newText[$newTextLength - 1] == "\n" )
1570                      {
1571                          unset( $newText[$newTextLength - 1] );
1572                          $this->addDocSpecification( $newText );
1573                          $newText = "\n";
1574                      }
1575                      else
1576                      {
1577                          $this->addDocSpecification( $newText );
1578                          $newText = '';
1579                      }
1580  
1581                      $params = array();
1582                      $funcName = '';
1583  
1584                      $offSet = eZPDFTable::extractFunction( $text, $offSet, $funcName, $params, 'ezCall' );
1585  
1586                      $newText .= $this->$funcName( $params );
1587  
1588                      continue;
1589                  }
1590                  else if ( strcmp( substr($text, $offSet+1, strlen( '/ezCall' ) ), '/ezCall' ) == 0 )
1591                  {
1592                      $this->addDocSpecification( $newText );
1593                      array_pop( $this->PreStack );
1594                      $offSet = strpos( $text, '>', $offSet );
1595                      $newText = '';
1596                      continue;
1597                  }
1598                  else if ( strcmp( substr($text, $offSet+1, strlen( 'ezGroup' ) ), 'ezGroup' ) == 0 ) // special call for processing whole text group, used by extends table.
1599                  {
1600                      $newTextLength = strlen( $newText );
1601                      if ( $newTextLength > 0 && $newText[$newTextLength - 1] == "\n" )
1602                      {
1603                          unset( $newText[$newTextLength - 1] );
1604                          $this->addDocSpecification( $newText );
1605                          $newText = "\n";
1606                      }
1607                      else
1608                      {
1609                          $this->addDocSpecification( $newText );
1610                          $newText = '';
1611                      }
1612  
1613                      $params = array();
1614                      $funcName = '';
1615  
1616                      $offSet = eZPDFTable::extractFunction( $text, $offSet, $funcName, $params, 'ezGroup' );
1617                      $offSet++;
1618                      $endGroup = strpos( $text, '</ezGroup:', $offSet );
1619                      $groupText = substr( $text, $offSet, $endGroup - $offSet );
1620                      $groupText = urldecode( $groupText );
1621  
1622                      $this->$funcName( $params, $groupText );
1623  
1624                      $offSet = strpos( $text, '>', $endGroup );
1625                      continue;
1626                  }
1627              }
1628              $newText .= $text[$offSet];
1629          }
1630          if ( strlen( $newText ) > 0 )
1631          {
1632              $this->addDocSpecification( $newText );
1633          }
1634  
1635          $this->outputDocSpecification();
1636      }
1637  
1638      /*!
1639       \private
1640       Fixup table cell text. Removes ezCall tags, and first C:callNewLine if they exists.
1641  
1642       \param text
1643  
1644       \return text without ezgroup/ezcall tags
1645      */
1646      function fixupTableCellText( $text )
1647      {
1648          $text = preg_replace( "/^" . EZ_PDF_LIB_NEWLINE . "/i", "", $text );
1649          $text = preg_replace( "/" . EZ_PDF_LIB_NEWLINE . "$/i", "", $text );
1650          return preg_replace( "'<[\/]*?ezCall:[^<>]*?>'si", "", $text );
1651      }
1652  
1653      /*!
1654       Function for drawing rectangle in document
1655  
1656       \param parameters
1657      */
1658      function callRectangle( $info )
1659      {
1660          $params = array();
1661  
1662          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1663  
1664          $keyArray = array ( 'c', 'm', 'y', 'k' );
1665          $cmykColor = explode( ',', $params['cmyk'] );
1666  
1667          foreach ( array_keys( $cmykColor ) as $key )
1668          {
1669              $cmykColor[$keyArray[$key]] = $cmykColor[$key];
1670              unset( $cmykColor[$key] );
1671          }
1672  
1673          $stackColor = $this->currentStrokeColour;
1674          $this->setStrokeColor( $cmykColor );
1675  
1676          if ( isset( $params['x'] ) )
1677          {
1678              $x1 = $params['x'];
1679              $x2 = $x1 + $params['width'];
1680          }
1681          if ( isset( $params['y'] ) )
1682          {
1683              $y1 = $params['y'];
1684              $y2 = $y1 + $params['height'];
1685          }
1686  
1687          if ( isset( $params['topY'] ) )
1688          {
1689              $y2 = $params['topY'];
1690              if ( $params['height'] > 0 )
1691              {
1692                  $y1 = $params['topY'] - $params['height'];
1693              }
1694              else
1695              {
1696                  $y1 = $this->yOffset() + $params['height'];
1697              }
1698          }
1699  
1700          $this->setLineStyle( $params['line_width'] );
1701  
1702          if ( $params['corner'] )
1703          {
1704              $factor = $params['corner'];
1705              $degree = 0;
1706  
1707              $this->line( $x1 + $factor, $y1, $x2 - $factor, $y1 );
1708              $this->line( $x2, $y1 + $factor, $x2, $y2 - $factor );
1709              $this->line( $x2 - $factor, $y2, $x1 + $factor, $y2 );
1710              $this->line( $x1, $y2 - $factor, $x1, $y1 + $factor );
1711  
1712              $this->curve( $x2 - $factor, $y1,
1713                            $x2, $y1 - $degree * $factor,
1714                            $x2 + $degree * $factor, $y1,
1715                            $x2, $y1 + $factor );
1716              $this->curve( $x2, $y2 - $factor,
1717                            $x2 + $degree * $factor, $y2,
1718                            $x2, $y2 + $degree * $factor,
1719                            $x2 - $factor, $y2 );
1720              $this->curve( $x1 + $factor, $y2,
1721                            $x1, $y2 + $degree * $factor,
1722                            $x1 - $degree * $factor, $y2,
1723                            $x1, $y2 - $factor );
1724              $this->curve( $x1, $y1 + $factor,
1725                            $x1 - $degree * $factor, $y1,
1726                            $x1, $y1 - $degree * $factor,
1727                            $x1 + $factor, $y1 );
1728          }
1729          else
1730          {
1731              $this->rectangle( $x1, $y1, $params['width'], $params['height'] );
1732          }
1733  
1734          $this->setColor( $stackColor );
1735      }
1736  
1737      /*!
1738       Set new margins
1739      */
1740      function callSetMargin( $info )
1741      {
1742          $options = array();
1743  
1744          eZPDFTable::extractParameters( $info['p'], 0, $options, true );
1745  
1746          if ( isset( $options['left'] ) )
1747          {
1748              $this->ez['leftMargin'] = (float)$options['left'];
1749          }
1750  
1751          if ( isset( $options['delta_left'] ) )
1752          {
1753              $this->ez['leftMargin'] += $options['delta_left'];
1754          }
1755  
1756          if ( isset( $options['right'] ) )
1757          {
1758              $this->ez['rightMargin'] = (float)$options['right'];
1759          }
1760  
1761          if ( isset( $options['delta_right'] ) )
1762          {
1763              $this->ez['rightMargin'] += $options['delta_right'];
1764          }
1765  
1766          if ( isset( $options['bottom'] ) )
1767          {
1768              $this->ez['bottomMargin'] = (float)$options['bottom'];
1769          }
1770  
1771          if ( isset( $options['line_space'] ) )
1772          {
1773              $this->ez['lineSpace'] = (float)$options['line_space'];
1774          }
1775  
1776          if ( isset( $options['top'] ) )
1777          {
1778              $this->ez['topMargin'] = (float)$options['top'];
1779              if ( $this->yOffset() < $this->ez['topMargin'] )
1780              {
1781                  $this->ez['yOffset'] = (float)$options['y'];
1782                  $this->y = (float)$options['y'];
1783              }
1784          }
1785  
1786          if ( isset( $options['x'] ) )
1787          {
1788              $this->setXOffset( (float)$options['x'] );
1789          }
1790  
1791          if ( isset( $options['y'] ) )
1792          {
1793              $this->ez['yOffset'] = (float)$options['y'];
1794              $this->y = (float)$options['y'];
1795          }
1796  
1797          return array( 'x' => $this->xOffset() );
1798      }
1799  
1800      /*!
1801       Draw filled circle
1802      */
1803      function callCircle( $info )
1804      {
1805          $params = array();
1806          $forceYPos = true;
1807  
1808          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1809  
1810          $keyArray = array ( 'c', 'm', 'y', 'k' );
1811          $cmykColor = explode( ',', $params['cmyk'] );
1812  
1813          foreach ( array_keys( $cmykColor ) as $key )
1814          {
1815              $cmykColor[$keyArray[$key]] = $cmykColor[$key];
1816              unset( $cmykColor[$key] );
1817          }
1818  
1819          $strokeStackColor = $this->currentStrokeColour;
1820          $this->setStrokeColor( $cmykColor );
1821          $stackColor = $this->currentColour;
1822          $this->setColor( $cmykColor );
1823  
1824          if ( $params['x'] == -1 )
1825          {
1826              $params['x'] = $this->xOffset() + $params['radius'];
1827          }
1828          if ( $params['y'] == -1 )
1829          {
1830              $forceYPos = false;
1831              $params['y'] = $this->yOffset();
1832          }
1833          if ( isset( $params['yOffset'] ) )
1834          {
1835              if ( $params['yOffset'] == -1 )
1836              {
1837                  $params['y'] += $this->getFontHeight( $this->fontSize() )/2 - $params['radius'];
1838              }
1839              else
1840              {
1841                  $params['y'] += $params['yOffset'];
1842              }
1843          }
1844  
1845          if ( $params['y'] - $this->getFontHeight( $this->fontSize() ) < $this->ez['bottomMargin'] &&
1846               !$forceYPos )
1847          {
1848              $this->ezNewPage();
1849              return $this->callCircle( $info );
1850          }
1851  
1852          $params['x'] += $params['pre_indent'];
1853  
1854          $this->filledEllipse( $params['x'], $params['y'], $params['radius'] );
1855  
1856          $this->setStrokeColor( $strokeStackColor );
1857          $this->setColor( $stackColor );
1858  
1859          if ( isset( $params['indent'] ) )
1860          {
1861              return array( 'x' => $params['x'] + $params['radius'] * 2 + $params['indent'] );
1862          }
1863          else
1864          {
1865              return array( 'x' => $params['x'] + $params['radius'] * 2 );
1866          }
1867  
1868      }
1869  
1870      /*!
1871       Function for drawing filled rectangle in document
1872  
1873       \param params
1874      */
1875      function callFilledRectangle( $info )
1876      {
1877          $params = array();
1878  
1879          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1880  
1881          $keyArray = array ( 'c', 'm', 'y', 'k' );
1882          $cmykTop = explode( ',', $params['cmykTop'] );
1883          $cmykBottom = explode( ',', $params['cmykBottom'] );
1884  
1885          foreach ( array_keys( $cmykBottom ) as $key )
1886          {
1887              $cmykBottom[$keyArray[$key]] = $cmykBottom[$key];
1888              unset( $cmykBottom[$key] );
1889              $cmykTop[$keyArray[$key]] = $cmykTop[$key];
1890              unset( $cmykTop[$key] );
1891          }
1892  
1893          $this->ezShadedRectangle( $params['x'], $params['y'], $params['width'], $params['height'], $cmykTop, $cmykBottom );
1894      }
1895  
1896      /*!
1897        Function for adding footer definition to PDF document. creates call on stack for ezInsertFooter
1898  
1899        \param parameters
1900        \text inside ezGroup Tags
1901      */
1902      function callBlockFrame( $params, $text )
1903      {
1904          if ( strlen( $text ) > 0 )
1905          {
1906              $this->addDocSpecFunction( 'ezInsertBlockFrame', array( $text, $params) );
1907          }
1908      }
1909  
1910      /*!
1911        Function for adding footer definition to PDF document. creates call on stack for ezInsertFooter
1912  
1913        \param parameters
1914        \text inside ezGroup Tags
1915      */
1916      function callFrame( $params, $text )
1917      {
1918          if ( strlen( $text ) > 0 )
1919          {
1920              $this->addDocSpecFunction( 'ezInsertFrame', array( $this->fixWhitespace( $text ), $params) );
1921          }
1922      }
1923  
1924      /*!
1925        Add line to all pages
1926      */
1927      function callLine( $params, $text )
1928      {
1929          $this->addDocSpecFunction( 'ezInsertLine', array( $params ) );
1930      }
1931  
1932      /*!
1933       Draw line on current page in PDF document
1934      */
1935      function callDrawLine( $info )
1936      {
1937          $params = array();
1938          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1939  
1940          $this->setLineStyle( $params['thickness'] );
1941          $this->line( $params['x1'], $params['y1'], $params['x2'], $params['y2'] );
1942      }
1943  
1944      /*!
1945        Function for setting frame margins. Frames are used to define for example footer and header areas
1946  
1947        \param info, standard ezpdf callback function
1948      */
1949      function callFrameMargins( $info )
1950      {
1951          $params = array();
1952          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
1953  
1954          if( isset( $this->ezFrame[$params['identifier']] ) )
1955          {
1956              $this->ezFrame[$params['identifier']] = array_merge( $this->ezFrame[$params['identifier']],
1957                                                                   $params );
1958          }
1959          else
1960          {
1961              $this->ezFrame[$params['identifier']] = $params;
1962          }
1963      }
1964  
1965      /*!
1966        Insert line onto every page
1967  
1968        \param line parameters
1969      */
1970      function ezInsertLine( $params )
1971      {
1972          reset( $this->ezPages );
1973          foreach ( $this->ezPages as $pageNum => $pageID )
1974          {
1975              $this->reopenObject($pageID);
1976              $this->line( $params['x1'], $params['y1'], $params['x2'], $params['y2'] );
1977              $this->closeObject();
1978          }
1979          reset( $this->ezPages );
1980      }
1981  
1982      /*!
1983        Insert footer/header into PDF document
1984  
1985        \param text
1986        \param text parameters
1987      */
1988      function ezInsertBlockFrame( $text, $textParameters )
1989      {
1990          $header = false;
1991          switch( $textParameters['location'] )
1992          {
1993              case 'footer_block':
1994              {
1995                  $frameCoords = $this->ezFrame['footer'];
1996              } break;
1997  
1998              case 'header_block':
1999              {
2000                  $header = true;
2001                  $frameCoords = $this->ezFrame['header'];
2002              } break;
2003          }
2004  
2005          $text = str_replace( array( ' ', "\t", "\r\n", "\n" ),
2006                               '',
2007                               urldecode( $text ) );
2008  
2009          foreach ( $this->ezPages as $pageNum => $pageID )
2010          {
2011              $this->pushStack();
2012  
2013              if ( $header )
2014              {
2015                  foreach( $frameCoords as $key => $value )
2016                  {
2017                      $this->ez[$key] = $value;
2018                  }
2019                  $this->setYOffset( $this->ez['pageHeight'] - $this->ez['topMargin'] );
2020              }
2021              else
2022              {
2023                  $this->ez['topMargin'] = $this->ez['pageHeight'] - $this->ez['bottomMargin'] + $frameCoords['topMargin'];
2024                  foreach( $frameCoords as $key => $value )
2025                  {
2026                      if ( $key != 'topMargin' )
2027                      {
2028                          $this->ez[$key] = $value;
2029                      }
2030                  }
2031              }
2032  
2033              $this->setXOffset( 0 );
2034  
2035              $frameText = $text; //Create copy of text
2036              if( $textParameters['page'] == 'even' &&
2037                  $pageNum % 2 == 1 )
2038                  continue;
2039              else if ( $textParameters['page'] == 'odd' &&
2040                        $pageNum % 2 == 0 )
2041                  continue;
2042  
2043              if ( strstr( $frameText, EZ_PDF_LIB_PAGENUM ) !== false )
2044              {
2045                  foreach ( array_keys( $this->PageCounter ) as $identifier )
2046                  {
2047                      if ( $this->PageCounter[$identifier]['start'] <= $pageNum &&
2048                           $this->PageCounter[$identifier]['stop'] >= $pageNum )
2049                      {
2050                          $frameText = str_replace( EZ_PDF_LIB_PAGENUM,
2051                                                    $this->ezWhatPageNumber( $pageNum, $identifier ),
2052                                                    $frameText );
2053  
2054                          if ( strstr( $frameText, EZ_PDF_LIB_TOTAL_PAGENUM ) !== false )
2055                          {
2056                              $frameText = str_replace( EZ_PDF_LIB_TOTAL_PAGENUM,
2057                                                        $this->PageCounter[$identifier]['stop'] - $this->PageCounter[$identifier]['start'] + 1,
2058                                                        $frameText );
2059                          }
2060                      }
2061                  }
2062              }
2063  
2064              for( $levelCount = 0; $levelCount < 9; $levelCount++ )
2065              {
2066                  if ( strstr( $frameText, EZ_PDF_LIB_HEADER_LEVEL.$levelCount ) !== false )
2067                  {
2068                      $frameText = str_replace( EZ_PDF_LIB_HEADER_LEVEL.$levelCount,
2069                                                $this->headerLabel( $pageNum, $levelCount ),
2070                                                $frameText );
2071                  }
2072  
2073                  if ( strstr( $frameText, EZ_PDF_LIB_HEADER_LEVEL_INDEX.$levelCount ) !== false )
2074                  {
2075                      $frameText = str_replace( EZ_PDF_LIB_HEADER_LEVEL_INDEX.$levelCount,
2076                                                $this->headerIndex( $pageNum, $levelCount ),
2077                                                $frameText );
2078                  }
2079              }
2080  
2081              $this->reopenObject($pageID);
2082              $this->ezText( $frameText );
2083              $this->closeObject();
2084              $this->popStack();
2085          }
2086      }
2087  
2088      /*!
2089        Insert footer/header into PDF document
2090  
2091        \param text
2092        \param text parameters
2093      */
2094      function ezInsertFrame( $text, $textParameters )
2095      {
2096          $size = $this->fontSize();
2097          if ( isset( $textParameters['size'] ) )
2098          {
2099              $size = $textParameters['size'];
2100          }
2101  
2102          $previousFont = $this->currentFont();
2103          if ( isset( $textParameters['font'] ) )
2104          {
2105              $this->selectFont( $textParameters['font'] );
2106          }
2107  
2108          $justification = $this->justification();
2109          if ( isset( $textParameters['justification'] ) )
2110          {
2111              $justification = $textParameters['justification'];
2112          }
2113  
2114          switch( $textParameters['location'] )
2115          {
2116              case 'footer':
2117              {
2118                  $frameCoords =& $this->ezFrame['footer'];
2119              } break;
2120  
2121              case 'frame_header':
2122              {
2123                  $frameCoords =& $this->ezFrame['header'];
2124              } break;
2125  
2126              default:
2127              {
2128                  $frameCoords =& $this->ezFrame[0];
2129              } break;
2130          }
2131  
2132          foreach ( $this->ezPages as $pageNum => $pageID )
2133          {
2134              if ( $pageNum < $textParameters['pageOffset'] )
2135                  continue;
2136  
2137              $frameText = $text; //Create copy of text
2138              if( $textParameters['page'] == 'even' &&
2139                  $pageNum % 2 == 1 )
2140                  continue;
2141              else if ( $textParameters['page'] == 'odd' &&
2142                        $pageNum % 2 == 0 )
2143                  continue;
2144  
2145              $countIdentifier = '';
2146              if ( strstr( $frameText, EZ_PDF_LIB_PAGENUM ) !== false )
2147              {
2148                  foreach ( array_keys( $this->PageCounter ) as $identifier )
2149                  {
2150                      if ( $this->PageCounter[$identifier]['start'] <= $pageNum &&
2151                           $this->PageCounter[$identifier]['stop'] >= $pageNum )
2152                      {
2153                          $frameText = str_replace( EZ_PDF_LIB_PAGENUM,
2154                                                    $this->ezWhatPageNumber( $pageNum, $identifier ),
2155                                                    $frameText );
2156  
2157                          if ( strstr( $frameText, EZ_PDF_LIB_TOTAL_PAGENUM ) !== false )
2158                          {
2159                              $frameText = str_replace( EZ_PDF_LIB_TOTAL_PAGENUM,
2160                                                        $this->PageCounter[$identifier]['stop'] - $this->PageCounter[$identifier]['start'] + 1,
2161                                                        $frameText );
2162                          }
2163                      }
2164                  }
2165              }
2166  
2167              for( $levelCount = 0; $levelCount < 9; $levelCount++ )
2168              {
2169                  if ( strstr( $frameText, EZ_PDF_LIB_HEADER_LEVEL.$levelCount ) !== false )
2170                  {
2171                      $frameText = str_replace( EZ_PDF_LIB_HEADER_LEVEL.$levelCount,
2172                                                $this->headerLabel( $pageNum, $levelCount ),
2173                                                $frameText );
2174                  }
2175  
2176                  if ( strstr( $frameText, EZ_PDF_LIB_HEADER_LEVEL_INDEX.$levelCount ) !== false )
2177                  {
2178                      $frameText = str_replace( EZ_PDF_LIB_HEADER_LEVEL_INDEX.$levelCount,
2179                                                $this->headerIndex( $pageNum, $levelCount ),
2180                                                $frameText );
2181                  }
2182              }
2183  
2184              $yOffset = $frameCoords['y0'] - $frameCoords['topMargin'];
2185              if ( $textParameters['newline'] )
2186              {
2187                  $yOffset -= $this->getFontHeight( $size );
2188              }
2189  
2190              $yOffset -= $this->getFontHeight( $size );
2191              $xOffset = $frameCoords['leftMargin'];
2192              $pageWidth = $this->ez['pageWidth'] - $frameCoords['leftMargin'] - $frameCoords['rightMargin'];
2193  
2194              $this->reopenObject($pageID);
2195  
2196              $lines = explode( "\n", $frameText );
2197              foreach ( array_keys( $lines ) as $key )
2198              {
2199                  $start=1;
2200                  $line = $lines[$key];
2201                  while (strlen($line) || $start){
2202                      $start = 0;
2203                      $textInfo = $this->addTextWrap( $xOffset, $yOffset, $pageWidth, $size, $line, $justification );
2204                      $line = $textInfo['text'];
2205  
2206                      if ( strlen( $line ) )
2207                      {
2208                          $yOffset -= $this->getFontHeight( $size );
2209                      }
2210                  }
2211              }
2212  
2213              $this->closeObject();
2214          }
2215  
2216          $this->selectFont( $previousFont );
2217      }
2218  
2219      /*!
2220       * Function for inserting frontpage into document. Called by ezGroup specification
2221       *
2222       * \param parameters
2223       * \param text in ezGroup
2224       */
2225      function callFrontpage( $params, $text )
2226      {
2227          $this->addDocSpecFunction( 'insertFrontpage', array( $params, $text ) );
2228      }
2229  
2230      /*!
2231       * Insert front page
2232       */
2233      function insertFrontpage( $params, $text )
2234      {
2235          $this->saveState();
2236          $closeObject = false;
2237          if ( $this->FrontpageID == null )
2238          {
2239              $this->ezInsertMode(1,1,'before');
2240              $this->ezNewPage();
2241              $this->FrontpageID = $this->currentPage;
2242          }
2243          else if( $this->currentPage != $this->FrontpageID )
2244          {
2245              $this->reopenObject( $this->FrontpageID );
2246              $closeObject = true;
2247          }
2248  
2249          $fontSize = $this->fontSize();
2250  
2251          $text = $this->fixWhitespace( $text );
2252          $this->setXOffset( 0 );
2253  
2254          Cezpdf::ezText( $text, $params['size'], array( 'justification' => $params['justification'],
2255                                                         'top_margin' => $params['top_margin'] ) );
2256  
2257          $this->setFontSize( $fontSize );
2258  
2259          if ( $closeObject )
2260          {
2261              $this->closeObject();
2262          }
2263          $this->restoreState();
2264      }
2265  
2266      /*!
2267       * Function for generating table definition. Called by ezGroup specification
2268       *
2269       * \param parameters
2270       * \param text in ezGroup
2271       */
2272      function callTable( $params, $text )
2273      {
2274          $textLen = strlen( $text );
2275          $tableData = array();
2276          $cellData = array();
2277          $showLines = 2;
2278          $rowCount = 0;
2279          $columnCount = 0;
2280  
2281          $columnText = '';
2282  
2283          $keyArray = array ( 'c', 'm', 'y', 'k' );
2284          if ( isset( $params['titleCellCMYK'] ) )
2285          {
2286              $params['titleCellCMYK'] = explode( ',', $params['titleCellCMYK'] );
2287              foreach ( array_keys( $params['titleCellCMYK'] ) as $key )
2288              {
2289                  $params['titleCellCMYK'][$keyArray[$key]] = $params['titleCellCMYK'][$key];
2290                  unset( $params['titleCellCMYK'][$key] );
2291              }
2292          }
2293  
2294          if ( isset( $params['cellCMYK'] ) )
2295          {
2296              $params['cellCMYK'] = explode( ',', $params['cellCMYK'] );
2297              foreach ( array_keys( $params['cellCMYK'] ) as $key )
2298              {
2299                  $params['cellCMYK'][$keyArray[$key]] = $params['cellCMYK'][$key];
2300                  unset( $params['cellCMYK'][$key] );
2301              }
2302              $params['shaded'] = 2;
2303              $params['shadeCol'] = $params['cellCMYK'];
2304              $params['shadeCol2'] = $params['cellCMYK'];
2305          }
2306  
2307          if ( isset( $params['textCMYK'] ) )
2308          {
2309              $params['textCMYK'] = explode( ',', $params['textCMYK'] );
2310              foreach ( array_keys( $params['textCMYK'] ) as $key )
2311              {
2312                  $params['textCMYK'][$keyArray[$key]] = $params['textCMYK'][$key];
2313                  unset( $params['textCMYK'][$key] );
2314              }
2315              $params['textCol'] = $params['textCMYK'];
2316          }
2317  
2318          if ( isset( $params['titleTextCMYK'] ) )
2319          {
2320              $params['titleTextCMYK'] = explode( ',', $params['titleTextCMYK'] );
2321              foreach ( array_keys( $params['titleTextCMYK'] ) as $key )
2322              {
2323                  $params['titleTextCMYK'][$keyArray[$key]] = $params['titleTextCMYK'][$key];
2324                  unset( $params['titleTextCMYK'][$key] );
2325              }
2326              $params['titleTextCMYK'] = $params['titleTextCMYK'];
2327          }
2328  
2329          if ( isset( $params['showLines'] ) )
2330          {
2331              $showLines = $params['showLines'];
2332          }
2333  
2334          for ( $offSet = 0; $offSet < $textLen; $offSet++ )
2335          {
2336              if ( $text[$offSet] == '<' )
2337              {
2338                  if ( strcmp( substr($text, $offSet+1, strlen( 'tr' ) ), 'tr' ) == 0 )
2339                  {
2340                      $tableData[] = array();
2341                      $offSet++;
2342                      $offSet += strlen( 'tr' );
2343                      continue;
2344                  }
2345                  else if ( strcmp( substr($text, $offSet+1, strlen( 'td' ) ), 'td' ) == 0 )
2346                  {
2347                      $tdParams = array();
2348                      $offSet++;
2349                      $offSet += strlen( 'td' );
2350                      $offSet = eZPDFTable::extractParameters( $text, $offSet, $tdParams );
2351  
2352                      if ( count( $tdParams ) > 0 )
2353                      {
2354                          $cellData[$columnCount. ',' .$rowCount] = array();
2355                          if ( isset( $tdParams['colspan'] ) )
2356                          {
2357                              $cellData[$columnCount. ',' .$rowCount]['size'] = (int)$tdParams['colspan'];
2358                          }
2359                          if ( isset( $tdParams['align'] ) )
2360                          {
2361                              $cellData[$columnCount. ',' .$rowCount]['justification'] = $tdParams['align'];
2362                          }
2363                          if ( isset( $tdParams['width'] ) )
2364                          {
2365                              $cellData[$columnCount. ',' .$rowCount]['width'] = $tdParams['width'];
2366                          }
2367                      }
2368                      continue;
2369                  }
2370                  else if ( strcmp( substr($text, $offSet+1, strlen( 'th' ) ), 'th' ) == 0 )
2371                  {
2372                      $thParams = array();
2373                      $offSet++;
2374                      $offSet += strlen( 'th' );
2375                      $offSet = eZPDFTable::extractParameters( $text, $offSet, $thParams );
2376  
2377                      $cellData[$columnCount. ',' .$rowCount] = array();
2378                      $cellData[$columnCount.','.$rowCount]['title'] = true;
2379                      if ( isset( $thParams['colspan'] ) )
2380                      {
2381                          $cellData[$columnCount. ',' .$rowCount]['size'] = array( (int)$thParams['colspan'], 1 );
2382                      }
2383                      if ( isset( $thParams['align'] ) )
2384                      {
2385                          $cellData[$columnCount. ',' .$rowCount]['justification'] = array( $thParams['align'], 1 );
2386                      }
2387  
2388                      continue;
2389                  }
2390                  else if ( strcmp( substr($text, $offSet+1, strlen( '/tr' ) ), '/tr' ) == 0 )
2391                  {
2392                      $rowCount++;
2393                      $columnCount = 0;
2394                      $offSet++;
2395                      $offSet += strlen( '/tr' );
2396                      continue;
2397                  }
2398                  else if ( strcmp( substr($text, $offSet+1, strlen( '/td' ) ), '/td' ) == 0 )
2399                  {
2400                      if ( $columnCount == 0 )
2401                      {
2402                          $tableData[$rowCount] = array();
2403                      }
2404                      $tableData[$rowCount][$columnCount] = $columnText;
2405                      $columnText = '';
2406                      $columnCount++;
2407                      $offSet++;
2408                      $offSet += strlen( '/td' );
2409                      continue;
2410                  }
2411                  else if ( strcmp( substr($text, $offSet+1, strlen( '/th' ) ), '/th' ) == 0 )
2412                  {
2413                      if ( $columnCount == 0 )
2414                      {
2415                          $tableData[$rowCount] = array();
2416                      }
2417                      $tableData[$rowCount][$columnCount] = $columnText;
2418                      $columnText = '';
2419                      $columnCount++;
2420                      $offSet++;
2421                      $offSet += strlen( '/th' );
2422                      continue;
2423                  }
2424              }
2425              $columnText .= $text[$offSet];
2426          }
2427          $this->addDocSpecFunction( 'ezTable', array( $tableData, '', '', array_merge( array( 'cellData' => $cellData,
2428                                                                                               'showLines' => $showLines ),
2429                                                                                        $params ) ) );
2430      }
2431  
2432      /**
2433       * Function for extracting function name and parameters from text.
2434       *
2435       * \param text
2436       * \param offset
2437       * \param function name (reference)
2438       * \param parameters array (reference)
2439       *
2440       * \return end offset of function
2441       */
2442      function extractFunction( &$text, $offSet, &$functionName, &$parameters, $type='ezCall' )
2443      {
2444          $offSet++;
2445          $offSet += strlen( $type.':' );
2446          $funcEnd = strpos( $text, ':', $offSet );
2447          if ( $funcEnd === false || strpos( $text, '>', $offSet ) < $funcEnd )
2448          {
2449              $funcEnd = strpos( $text, '>', $offSet );
2450          }
2451          $functionName = substr( $text, $offSet, $funcEnd - $offSet );
2452  
2453          return eZPDFTable::extractParameters( $text, $funcEnd, $parameters );
2454      }
2455  
2456      /**
2457       * Function for extracting parameters from : separated key:value list callback functions
2458       *
2459       * \param text
2460       * \param offset
2461       * \param parameters array (reference)
2462       *
2463       * \return end offset of function
2464       */
2465      function extractParameters( &$text, $offSet, &$parameters, $skipFirstChar=false )
2466      {
2467          $endOffset = strpos( $text, '>', $offSet );
2468          if ( $endOffset === false )
2469          {
2470              $endOffset = strlen( $text );
2471          }
2472  
2473          if ( $skipFirstChar === false )
2474              $offSet++;
2475          while ( $offSet < $endOffset )
2476          {
2477              $nameEnd = strpos( $text, ':', $offSet );
2478              $valueEnd = strpos( $text, ':', $nameEnd+1 );
2479              if ( $valueEnd > $endOffset || $valueEnd === false )
2480              {
2481                  $valueEnd = $endOffset;
2482              }
2483              $paramName = substr( $text, $offSet, $nameEnd-$offSet);
2484              ++$nameEnd;
2485              $paramValue = substr( $text, $nameEnd, $valueEnd-$nameEnd );
2486              $parameters[$paramName] = $paramValue;
2487              $offSet = ++$valueEnd;
2488          }
2489  
2490          return $endOffset;
2491      }
2492  
2493      /**
2494        Loop through all document specification settings and print specified text
2495  
2496        \return new Y offset
2497      */
2498      function outputDocSpecification()
2499      {
2500          foreach( array_keys( $this->DocSpecification ) as $key )
2501          {
2502              $outputElement =& $this->DocSpecification[$key];
2503  
2504              $documentSpec =& $outputElement['docSpec'];
2505  
2506              if ( isset( $documentSpec['fontName'] ) )
2507              {
2508                  $this->selectFont( $documentSpec['fontName'] );
2509              }
2510  
2511              if ( isset( $documentSpec['fontSize'] ) )
2512              {
2513                  $size = $documentSpec['fontSize'];
2514              }
2515              else
2516              {
2517                  $size = $this->fontSize();
2518              }
2519  
2520              if ( isset( $documentSpec['cmyk'] ) )
2521              {
2522                  $this->setColor( $documentSpec['cmyk'] );
2523              }
2524  
2525              if ( isset( $outputElement['isFunction'] ) && $outputElement['isFunction'] === true )
2526              {
2527                  $return = call_user_func_array( array( &$this, $outputElement['functionName'] ), $outputElement['parameters'] );
2528              }
2529              else
2530              {
2531                  $return = Cezpdf::ezText( $outputElement['text'],
2532                                            $size,
2533                                            array( 'justification' => $documentSpec['justification'] ) );
2534              }
2535          }
2536          return $return;
2537      }
2538  
2539      /*!
2540       Insert text at specified position
2541      */
2542      function callTextBox( $params, $text )
2543      {
2544          $this->addDocSpecFunction( 'insertTextBox', array( $params, $text ) );
2545      }
2546  
2547      function insertTextBox( $params, $text )
2548      {
2549          $this->pushStack();
2550  
2551          $this->setYOffset( $params['y'] );
2552          $this->setXOffset( $params['x'] );
2553  
2554          $marginText = '<C:callSetMargin';
2555          $marginText .= ':left:' . ( $params['x'] );
2556          $marginText .= ':right:' . ( $this->ez['pageWidth'] - $params['width'] - $params['x'] );
2557          $marginText .= '>';
2558          $marginText .= '<ezCall:callText';
2559          $marginText .= ':size:' . ( isset( $params['size'] ) ? $params['size'] : $this->fontSize() );
2560          $marginText .= ':justification:' . ( isset( $params['align'] ) ? $params['align'] : 'left' );
2561          $marginText .= '>';
2562  
2563          $this->ezText( $marginText . urldecode( $text ) . '</ezCall:callText>' );
2564  
2565          $this->popStack();
2566      }
2567  
2568      /*!
2569       Callback function for adding text frame.
2570      */
2571      function callTextFrame( $params, $text )
2572      {
2573          $this->addDocSpecFunction( 'insertTextFrame', array( $params, $text ) );
2574      }
2575  
2576      /*!
2577       Callback function for adding text frame.
2578      */
2579      function insertTextFrame( $params, $text )
2580      {
2581          $prevColor = $this->currentColour;
2582          $prevFontSize = $this->fontSize();
2583          $prevFont = $this->currentFont();
2584  
2585          if ( isset( $params['fontSize'] ) )
2586          {
2587              $this->setFontSize( $params['fontSize'] );
2588          }
2589  
2590          if ( isset( $params['fontName'] ) )
2591          {
2592              $this->selectFont( $params['fontName'] );
2593          }
2594  
2595          $cmykKeys = array( 'c', 'm', 'y', 'k' );
2596          if ( isset( $params ['frameCMYK'] ) )
2597          {
2598              $params['frameCMYK'] = explode( ',', $params['frameCMYK'] );
2599              foreach ( $cmykKeys as $oldKey => $newKey )
2600              {
2601                  $params['frameCMYK'][$newKey] = $params['frameCMYK'][$oldKey];
2602                  unset( $params['frameCMYK'][$oldKey] );
2603              }
2604          }
2605          if ( isset( $params['textCMYK'] ) )
2606          {
2607              $params['textCMYK'] = explode( ',', $params['textCMYK'] );
2608              foreach ( $cmykKeys as $oldKey => $newKey )
2609              {
2610                  $params['textCMYK'][$newKey] = $params['textCMYK'][$oldKey];
2611                  unset( $params['textCMYK'][$oldKey] );
2612              }
2613          }
2614  
2615          $padding = 0;
2616          if ( isset( $params['padding'] ) )
2617          {
2618              $padding = $params['padding'];
2619          }
2620  
2621          $leftPadding = $padding;
2622          $rightPadding = $padding;
2623          $topPadding = $padding;
2624          $bottomPadding = $padding;
2625  
2626          if ( isset( $params['leftPadding'] ) )
2627          {
2628              $leftPadding = $params['leftPadding'];
2629          }
2630          if ( isset( $params['rightPadding'] ) )
2631          {
2632              $rightPadding = $params['rightPadding'];
2633          }
2634          if ( isset( $params['topPadding'] ) )
2635          {
2636              $topPadding = $params['topPadding'];
2637          }
2638          if ( isset( $params['bottomPadding'] ) )
2639          {
2640              $bottomPadding = $params['bottomPadding'];
2641          }
2642  
2643          $yOffset = $this->yOffset();
2644          $xOffset = $this->xOffset();
2645  
2646          $fontHeight = $this->getFontHeight( $this->ez['fontSize'] );
2647          $fontDecender = $this->getFontDecender( $this->ez['fontSize'] );
2648          $textWidth = $this->getTextWidth( $this->ez['fontSize'], $text );
2649  
2650          $totalHeight = $fontHeight + $topPadding;
2651          $totalWidth = $textWidth + $leftPadding + $rightPadding;
2652  
2653          if ( $rightPadding == -1 )
2654          {
2655              $totalWidth = $leftPadding + $this->ez['pageWidth'] - $xOffset + 10;
2656          }
2657  
2658          if ( isset( $params['frameCMYK'] ) )
2659          {
2660              $this->setColor( $params['frameCMYK'] );
2661          }
2662          $this->filledRectangle( $xOffset - $leftPadding,
2663                                  $yOffset - $bottomPadding,
2664                                  $totalWidth,
2665                                  $totalHeight );
2666  
2667          if ( isset( $params['roundEnds'] ) )
2668          {
2669              if ( $rightPadding != -1 )
2670              {
2671                  $this->filledEllipse( $xOffset + $textWidth + $rightPadding, $yOffset - $bottomPadding + ( $totalHeight / 2 ), $totalHeight / 2 );
2672              }
2673              if ( $leftPadding != -1 )
2674              {
2675                  $this->filledEllipse( $xOffset - $leftPadding, $yOffset - $bottomPadding + ( $totalHeight / 2 ), $totalHeight / 2 );
2676              }
2677          }
2678  
2679          if ( isset( $params['textCMYK'] ) )
2680          {
2681              $this->setColor( $params['textCMYK'] );
2682          }
2683          else
2684          {
2685              $this->setColor( $prevColor );
2686          }
2687          $this->addText( $xOffset, $yOffset, $this->fontSize(), $text );
2688  
2689          $this->setColor( $prevColor );
2690          $this->setFontSize( $prevFontSize );
2691          $this->selectFont( $prevFont );
2692      }
2693  
2694      /**
2695       * Callback function for adding text
2696       */
2697      function callText( $params )
2698      {
2699          $options = array();
2700  
2701          if ( isset( $params['font'] ) )
2702          {
2703              $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['font'];
2704          }
2705  
2706          if ( isset( $params['size'] ) )
2707          {
2708              $options['fontSize'] = $params['size'];
2709          }
2710  
2711          if ( isset( $params['justification'] ) )
2712          {
2713              $options['justification'] = $params['justification'];
2714          }
2715  
2716          if ( isset( $params['cmyk'] ) )
2717          {
2718              $keyArray = array ( 'c', 'm', 'y', 'k' );
2719              $options['cmyk'] = array();
2720              $params['cmyk'] = explode( ',', $params['cmyk'] );
2721              foreach ( array_keys( $params['cmyk'] ) as $key )
2722              {
2723                  $options['cmyk'][$keyArray[$key]] = $params['cmyk'][$key];
2724              }
2725          }
2726  
2727          $this->addToPreStack( $options );
2728  
2729          return '';
2730      }
2731  
2732      /*!
2733       * Add and build Stack for function calls and document specification Stack
2734  
2735        \param countinues text, set to false to insert independent frames. DEfault true
2736      */
2737      function pushStack( $continous = true)
2738      {
2739          include_once ( 'lib/ezutils/classes/ezmath.php' );
2740          $docSpecArray = array( 'DocSpec' => $this->DocSpecification,
2741                                 'PreStack' => $this->PreStack,
2742                                 'LeftMarginArray' => $this->LeftMarginArray,
2743                                 'RightMarginArray' => $this->RightMarginArray,
2744                                 'LeftMargin' => $this->ez['leftMargin'],
2745                                 'RightMargin' => $this->ez['rightMargin'],
2746                                 'TopMargin' => $this->ez['topMargin'],
2747                                 'BottomMargin' => $this->ez['bottomMargin'],
2748                                 'LineSpace' => $this->ez['lineSpace'],
2749                                 'Continous' => $continous,
2750                                 'FontSize' => $this->fontSize(),
2751                                 'Justification' => $this->justification() );
2752          if ( $continous )
2753          {
2754              $docSpecArray['YPos'] = $this->yOffset();
2755              $docSpecArray['XPos'] = $this->xOffset();
2756          }
2757  
2758          $this->DocSpecStack[] = $docSpecArray;
2759  
2760          $this->PreStack = array( array( 'justification' => $this->justification(),
2761                                          'fontSize' => $this->fontSize(),
2762                                          'fontName' => 'lib/ezpdf/classes/fonts/Helvetica',
2763                                          'cmyk' => eZMath:: rgbToCMYK2( 0, 0, 0 ) ) );
2764          $this->DocSpecification = array();
2765      }
2766  
2767      /*!
2768       Pop Specification stack.
2769      */
2770      function popStack()
2771      {
2772          $stackArray = array_pop( $this->DocSpecStack );
2773          $this->DocSpecification = $stackArray['DocSpec'];
2774          $this->PreStack = $stackArray['PreStack'];
2775          $this->LeftMarginArray = $stackArray['LeftMarginArray'];
2776          $this->RightMarginArray = $stackArray['RightMarginArray'];
2777          $this->ez['leftMargin'] = $stackArray['LeftMargin'];
2778          $this->ez['rightMargin'] = $stackArray['RightMargin'];
2779          $this->ez['topMargin'] = $stackArray['TopMargin'];
2780          $this->ez['bottomMargin'] = $stackArray['BottomMargin'];
2781          $this->ez['lineSpace'] = $stackArray['LineSpace'];
2782          $this->setFontSize( $stackArray['FontSize'] );
2783          $this->setJustification( $stackArray['justification'] );
2784  
2785          if ( $stackArray['continous'] )
2786          {
2787              $this->setYOffset( $stackArray['YPos'] );
2788              $this->setXOffset( $stackArray['XPos'] );
2789          }
2790      }
2791  
2792      /**
2793       * Function for adding text to doc specification
2794       *
2795       * param - text to add
2796       */
2797      function addDocSpecification( $text )
2798      {
2799          $docSpec = array_pop( $this->PreStack );
2800          $this->DocSpecification[] = array ( 'docSpec' => $docSpec,
2801                                              'text' => $text );
2802          $this->PreStack[] = $docSpec;
2803      }
2804  
2805      /**
2806       * Function for adding function to doc specification
2807       *
2808       * param - text to add
2809       */
2810      function addDocSpecFunction( $functionName, $parameters )
2811      {
2812          $docSpec = array_pop( $this->PreStack );
2813          $this->DocSpecification[] = array ( 'docSpec' => $docSpec,
2814                                              'isFunction' => true,
2815                                              'functionName' => $functionName,
2816                                              'parameters' => $parameters );
2817          $this->PreStack[] = $docSpec;
2818      }
2819  
2820  
2821      /**
2822       * function for adding font specification to PreStack array
2823       *
2824       * Possible $options setting:
2825       * - justification
2826       * - fontSize
2827       * - fontName
2828       */
2829      function addToPreStack( $options=array() )
2830      {
2831          $currentElement = array();
2832  
2833          $prevElement = array_pop( $this->PreStack );
2834  
2835          if ( isset( $options['justification'] ) )
2836          {
2837              $currentElement['justification'] = $options['justification'];
2838          }
2839          else
2840          {
2841              $currentElement['justification'] = $prevElement['justification'];
2842          }
2843  
2844          if ( isset( $options['fontSize'] ) )
2845          {
2846              $currentElement['fontSize'] = $options['fontSize'];
2847          }
2848          else
2849          {
2850              $currentElement['fontSize'] = $prevElement['fontSize'];
2851          }
2852  
2853          if ( isset( $options['fontName'] ) )
2854          {
2855              $currentElement['fontName'] = $options['fontName'];
2856          }
2857          else
2858          {
2859              $currentElement['fontName'] = $prevElement['fontName'];
2860          }
2861  
2862          if ( isset( $options['cmyk'] ) )
2863          {
2864              $currentElement['cmyk'] = $options['cmyk'];
2865          }
2866          else
2867          {
2868              $currentElement['cmyk'] = $prevElement['cmyk'];
2869          }
2870  
2871          $this->PreStack[] = $prevElement;
2872          $this->PreStack[] = $currentElement;
2873      }
2874  
2875      /*!
2876        Draw line related to a frame.
2877      */
2878      function callFrameLine( $info )
2879      {
2880          $parameters = array();
2881          eZPDFTable::extractParameters( $info['p'], 0, $parameters, true );
2882  
2883          $location = $parameters['location'];
2884          $yOffset = $parameters['margin'];
2885          if ( $location == 'frame_header' )
2886          {
2887              $yOffset = $this->ez['pageHeight'] - $parameters['margin'];
2888          }
2889  
2890          $rightMargin = $this->rightMargin( $yOffset );
2891          if ( isset( $parameters['rightMargin'] ) )
2892          {
2893              $rightMargin = $parameters['rightMargin'];
2894          }
2895  
2896          $leftMargin = $this->leftMargin( $yOffset );
2897          if ( isset( $parameters['leftMargin'] ) )
2898          {
2899              $leftMargin = $parameters['leftMargin'];
2900          }
2901  
2902          $this->setLineStyle( $parameters['thickness'] );
2903  
2904          reset( $this->ezPages );
2905          foreach ( $this->ezPages as $pageNum => $pageID )
2906          {
2907              if( $pageNum < $parameters['pageOffset'] )
2908                  continue;
2909  
2910              if ( $parameters['page'] == 'odd' &&
2911                   $pageNum % 2 == 0 )
2912                  continue;
2913  
2914              if ( $parameters['page'] == 'even' &&
2915                   $pageNum % 2 == 1 )
2916                  continue;
2917  
2918              $this->reopenObject( $pageID );
2919              $this->line( $leftMargin, $yOffset, $this->ez['pageWidth'] - $rightMargin, $yOffset );
2920              $this->closeObject();
2921          }
2922  
2923          $this->setLineStyle( 1 );
2924      }
2925  
2926      /*!
2927       Start page counter in PDF document
2928  
2929       \param counter identifier
2930      */
2931      function callStartPageCounter( $info )
2932      {
2933          $params = array();
2934  
2935          eZPDFTable::extractParameters( $info['p'], 0, $params, true );
2936  
2937          $identifier = 'main';
2938          if ( isset( $params['identifier'] ) )
2939          {
2940              $identifier = $params['identifier'];
2941          }
2942  
2943          if ( isset( $params['start'] ) )
2944          {
2945              $this->PageCounter[$identifier] = array();
2946              $this->PageCounter[$identifier]['start'] = $this->ezGetCurrentPageNumber();
2947          }
2948          if ( isset( $params['stop'] ) )
2949          {
2950              $this->PageCounter[$identifier]['stop'] = $this->ezGetCurrentPageNumber();
2951          }
2952      }
2953  
2954      /*!
2955       \reimp
2956  
2957       \param real page number
2958       \param pagecounter identifier
2959      */
2960      function ezWhatPageNumber( $pageNum, $identifier = false )
2961      {
2962          if ( $identifier === false )
2963          {
2964              foreach ( array_keys( $this->PageCounter ) as $identifier )
2965              {
2966                  if ( isset( $this->PageCounter[$identifier]['start'] ) &&
2967                       $this->PageCounter[$identifier]['start'] <= $pageNum &&
2968                       ( !isset( $this->PageCounter[$identifier]['stop'] ) || $this->PageCounter[$identifier]['stop'] >= $pageNum ) )
2969                      return $pageNum - $this->PageCounter[$identifier]['start'] + 1;
2970              }
2971          }
2972          else
2973              return $pageNum - $this->PageCounter[$identifier]['start'] + 1;
2974      }
2975  
2976      /*!
2977        \private
2978  
2979        Get header label of content on specified page and specified level
2980  
2981        \param current page
2982        \param level
2983      */
2984      function headerLabel( $page, $level )
2985      {
2986          $headerLabel = '';
2987          foreach ( array_keys( $this->TOC ) as $key )
2988          {
2989              $header = $this->TOC[$key];
2990              if ( $header['pageNumber'] > $page )
2991                  return $headerLabel;
2992  
2993              if ( $header['level'] == $level )
2994              {
2995                  $headerLabel = $header['label'];
2996              }
2997              else if ( $header['level'] < $level )
2998              {
2999                  $headerLabel = '';
3000              }
3001          }
3002  
3003          return $headerLabel;
3004      }
3005  
3006      /*!
3007        \private
3008  
3009        Get header label of content on specified page and specified level
3010  
3011        \param current page
3012        \param level
3013      */
3014      function headerIndex( $page, $level )
3015      {
3016          $headerIndex = 0;
3017          foreach ( array_keys( $this->TOC ) as $key )
3018          {
3019              $header = $this->TOC[$key];
3020              if ( $header['pageNumber'] > $page )
3021                  return ( $headerIndex != 0 ? $headerIndex : '' );
3022  
3023              if ( $header['level'] == $level )
3024              {
3025                  $headerIndex++;
3026              }
3027              else if ( $header['level'] < $level )
3028              {
3029                  $headerLabel = 0;
3030              }
3031          }
3032  
3033          return ( $headerIndex != 0 ? $headerIndex : '' );
3034      }
3035  
3036      var $TOC; // Table of content array
3037      var $KeywordArray; // keyword array
3038      var $PageCounter;
3039  
3040      var $FrontpageID; // Variable used to store reference to frontpage
3041  
3042      var $ezFrame; // array containing frame definitions
3043  
3044      /* Stack and array used for preprocessing document */
3045      var $PreStack;
3046      var $DocSpecification;
3047  
3048      /* Stack array for recursive ezText calls */
3049      var $DocSpecStack = array();
3050  }
3051  
3052  
3053  ?>


Généré le : Sat Feb 24 10:30:04 2007 par Balluche grâce à PHPXref 0.7