eZ Publish  [trunk]
class.ezpdftable.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZPDFTable class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package lib
00009  */
00010 
00011 /*!
00012   \class eZPDFTable class.ezpdftable.php
00013   \ingroup eZPDF
00014   \brief eZPDFTable adds extra support for tables
00015 */
00016 
00017 class eZPDFTable extends Cezpdf
00018 {
00019     const NEWLINE = '<C:callNewLine>';
00020     const SPACE = '<C:callSpace>';
00021     const TAB = '<C:callTab>';
00022 
00023     const PAGENUM = '#page';
00024     const TOTAL_PAGENUM = '#total';
00025     const HEADER_LEVEL = '#level';
00026     const HEADER_LEVEL_INDEX = '#indexLevel';
00027 
00028     /**
00029      Constructor. This class is only used to encapsulate a table.
00030     */
00031     function eZPDFTable($paper='a4',$orientation='portrait')
00032     {
00033         $this->Cezpdf($paper, $orientation);
00034         $this->TOC = array();
00035         $this->KeywordArray = array();
00036         $this->PageCounter = array();
00037         $this->initFrameMargins();
00038 
00039         $this->ez['textStack'] = array();
00040 
00041         $this->PreStack = array();
00042         $this->DocSpecification = array();
00043         $this->pushStack();
00044         $this->FrontpageID = null;
00045     }
00046 
00047     /*!
00048      * \private
00049      * Initialize footer and header frame margins. Called by constructor
00050      */
00051     function initFrameMargins()
00052     {
00053         $this->ezFrame = array();
00054 
00055         $config = eZINI::instance( 'pdf.ini' );
00056 
00057         $this->ezFrame['header'] = array( 'y0' => $this->ez['pageHeight'],
00058                                           'leftMargin' => $config->variable( 'Header', 'LeftMargin' ),
00059                                           'rightMargin' => $config->variable( 'Header', 'RightMargin' ),
00060                                           'topMargin' => $config->variable( 'Header', 'TopMargin' ),
00061                                           'bottomMargin' => $config->variable( 'Header', 'BottomMargin' ) );
00062         $this->ezFrame['footer'] = array( 'y0' => $this->ez['bottomMargin'],
00063                                           'leftMargin' => $config->variable( 'Footer', 'LeftMargin' ),
00064                                           'rightMargin' => $config->variable( 'Footer', 'RightMargin' ),
00065                                           'topMargin' => $config->variable( 'Footer', 'TopMargin' ),
00066                                           'bottomMargin' => $config->variable( 'Footer', 'BottomMargin' ) );
00067     }
00068 
00069     /**
00070      Get the current Y offset
00071     */
00072     function yOffset()
00073     {
00074         return $this->y;
00075     }
00076 
00077     /**
00078      Get the current X offset
00079     */
00080     function xOffset()
00081     {
00082         $xOffset = $this->ez['xOffset'];
00083         if ( $xOffset == 0 ||
00084              $this->leftMargin() > $this->ez['xOffset'] )
00085         {
00086             $xOffset = $this->leftMargin();
00087         }
00088         return $xOffset;
00089     }
00090 
00091     function setYOffset( $yOffset )
00092     {
00093         $this->y = $yOffset;
00094     }
00095 
00096     function setXOffset( $xOffset )
00097     {
00098         if ( $xOffset > $this->ez['pageWidth'] - $this->rightMargin() )
00099         {
00100             $this->ez['xOffset'] = 0;
00101         }
00102         else
00103         {
00104             $this->ez['xOffset'] = $xOffset;
00105         }
00106     }
00107 
00108     /*!
00109      * add a table of information to the pdf document
00110      * $data is a two dimensional array
00111      * $cols (optional) is an associative array, the keys are the names of the columns from $data
00112      * to be presented (and in that order), the values are the titles to be given to the columns
00113      * $title (optional) is the title to be put on the top of the table
00114      *
00115      * $options is an associative array which can contain:
00116      * 'cellData' => array( <coord> => array( 'size' => array( <width>, <height>),
00117      *                                        'justification' => <left|right|center> ),
00118      *                      <coord>....)
00119      *            All non specified coords will be threated with default settings. Coord is text, offset 0, ex: '5,6'
00120      *            Coord 'x,0' is table header
00121      * 'showLines'=> 0,1,2, default is 1 (show outside and top lines only), 2=> lines on each row
00122      * 'showHeadings' => 0 or 1
00123      * 'repeatTableHeader' => 0 or 1, if set to 1, the table header will be repeated when a table stretches over multiple pages. ( default 0 )
00124      * 'shaded'=> 0,1,2,3 default is 1 (1->alternate lines are shaded, 0->no shading, 2-> both shaded, second uses shadeCol2)
00125      * 'shadeCol' => (CMYK) array, defining the colour of the shading
00126      * 'shadeCol2' => (CMYK) array, defining the colour of the shading of the other blocks
00127      * 'fontSize' => 10
00128      * 'textCol' => (CMYK) array, text colour
00129      * 'titleFontSize' => 12
00130      * 'rowGap' => 2 , the space added at the top and bottom of each row, between the text and the lines
00131      * 'colGap' => 5 , the space on the left and right sides of each cell
00132      * 'lineCol' => (r,g,b) array, defining the colour of the lines, default, black.
00133      * 'xPos' => 'left','right','center','centre',or coordinate, reference coordinate in the x-direction
00134      * 'xOrientation' => 'left','right','center','centre', position of the table w.r.t 'xPos'
00135      * 'width'=> <number> which will specify the width of the table, if it turns out to not be this
00136      *    wide, then it will stretch the table to fit, if it is wider then each cell will be made
00137      *    proportionalty smaller, and the content may have to wrap.
00138      * 'maxWidth'=> <number> similar to 'width', but will only make table smaller than it wants to be
00139      * 'options' => array(<colname>=>array('justification'=>'left','width'=>100,'link'=>linkDataName),<colname>=>....)
00140      *             allow the setting of other paramaters for the individual columns
00141      * 'minRowSpace'=> the minimum space between the bottom of each row and the bottom margin, in which a new row will be started
00142      *                  if it is less, then a new page would be started, default=-100
00143      * 'innerLineThickness'=>1
00144      * 'outerLineThickness'=>1
00145      * 'splitRows'=>0, 0 or 1, whether or not to allow the rows to be split across page boundaries
00146      * 'protectRows'=>number, the number of rows to hold with the heading on page, ie, if there less than this number of
00147      *                rows on the page, then move the whole lot onto the next page, default=1
00148      *
00149      * note that the user will have had to make a font selection already or this will not
00150      * produce a valid pdf file.
00151      */
00152     function ezTable(&$data,$cols='',$title='',$options='')
00153     {
00154         if (!is_array($data)){
00155             return;
00156         }
00157 
00158         $tableStartY = $this->y;
00159 
00160         // Get total column count and column indexes
00161         if (!is_array($cols)){
00162             // take the columns from the first row of the data set
00163             reset($data);
00164             list($k,$v)=each($data);
00165             if (!is_array($v)){
00166                 return;
00167             }
00168             $cols=array();
00169 
00170             $realCount = 0;
00171             for ( $c = 0; $c < count($v); $c++ )
00172             {
00173                 if ( isset( $options['cellData'][$realCount.',0']['size'] ) )
00174                 {
00175                     $incCount = $options['cellData'][$realCount.',0']['size'];
00176                     for ( $innerCount = 0; $innerCount < $incCount; ++$innerCount )
00177                     {
00178                         $cols[$realCount] = $realCount++;
00179                     }
00180                 }
00181                 else
00182                 {
00183                     $cols[$realCount] = $realCount++;
00184                 }
00185             }
00186         }
00187 
00188         if (!is_array($options)){
00189             $options=array();
00190         }
00191 
00192         $defaults = array(
00193             'cellPadding' => 0,
00194             'shaded' => 0,
00195             'showLines' => 1,
00196             'shadeCol' => eZMath::rgbToCMYK2( 0.8, 0.8, 0.8 ),
00197             'shadeCol2' => eZMath::rgbToCMYK2( 0.7, 0.7, 0.7 ),
00198             'repeatTableHeader' => 0,
00199             'fontSize' => 10,
00200             'titleFontSize' => 12,
00201             'titleGap' => 5,
00202             'lineCol' => array( 0, 0, 0 ),
00203             'gap' => 5,
00204             'xPos' => 'centre',
00205             'xOrientation' => 'centre',
00206             'showHeadings' => 1,
00207             'textCol' => eZMath::rgbToCMYK2( 0, 0, 0 ),
00208             'titleTextCMYK' => eZMath::rgbToCMYK2( 0, 0, 0 ),
00209             'width' => 0,
00210             'maxWidth' => 0,
00211             'cols' => array(),
00212             'minRowSpace' => -100,
00213             'rowGap' => 2,
00214             'colGap' => 5,
00215             'innerLineThickness' => 1,
00216             'outerLineThickness' => 1,
00217             'splitRows' => 0,
00218             'protectRows'=> 1,
00219             'firstRowTitle' => false,
00220             'titleFontSize' => 10,
00221             'test' => 0,
00222             'yBottom' => 0 );
00223 
00224         foreach($defaults as $key=>$value){
00225             if (is_array($value)){
00226                 if (!isset($options[$key]) || !is_array($options[$key])){
00227                     $options[$key]=$value;
00228                 }
00229             } else {
00230                 if (!isset($options[$key])){
00231                     $options[$key]=$value;
00232                 }
00233             }
00234         }
00235         $options['gap']=2*$options['colGap'];
00236         $middle = ($this->ez['pageWidth']- $this->rightMargin() - $this->leftMargin() )/2+$this->leftMargin();
00237         // figure out the maximum widths of the text within each column
00238         $maxWidth = array();
00239         $minWidth = array();
00240 
00241         $maxRowCount = 0;
00242         // find the maximum cell widths based on the data
00243         foreach ( $data as $rowCount=>$row)
00244         {
00245             $realColCount = 0;
00246             for( $columnCount = 0; $columnCount < count( $row ); $columnCount++ )
00247             {
00248                 $wMax = 0; // total maximum width of table column
00249                 $wMix = 0; // minimum width of table column
00250                 $data[$rowCount][$columnCount] = $this->fixupTableCellText( $row[$columnCount] );
00251                 $row[$columnCount] = $data[$rowCount][$columnCount];
00252                 // get col span
00253                 $colSpan = 1;
00254                 if ( isset( $options['cellData'][$realColCount.','.$rowCount]['size'] ) )
00255                 {
00256                     $colSpan = $options['cellData'][$realColCount.','.$rowCount]['size'];
00257                 }
00258 
00259                 //get and set max width
00260                 if ( ( $rowCount == 0 && $options['firstRowTitle'] ) ||
00261                      ( isset( $options['cellData'][$realColCount.','.$rowCount]['title'] ) && $options['cellData'][$realColCount.','.$rowCount]['title'] ) )
00262                 {
00263                     $wMax = $this->ezPrvtGetTextWidth( $options['titleFontSize'], (string)$row[$columnCount] ) * 1.01;
00264                     $wMin = $this->eZGetMaxWordWidth( $options['titleFontSize'], (string)$row[$columnCount] ) * 1.01;
00265                     $options['cellData'][$realColCount.','.$rowCount]['title'] = true;
00266                 }
00267                 else
00268                 {
00269                     $wMax = $this->ezPrvtGetTextWidth( $options['fontSize'], (string)$row[$columnCount] ) * 1.01;
00270                     $wMin = $this->eZGetMaxWordWidth( $options['fontSize'], (string)$row[$columnCount] ) * 1.01;
00271                 }
00272 
00273                 if ( isset( $maxWidth[$colSpan][$realColCount] ) )
00274                 {
00275                     if ( $wMax > $maxWidth[$colSpan][$realColCount] )
00276                     {
00277                         $maxWidth[$colSpan][$realColCount] = $wMax;
00278                     }
00279                 }
00280                 else
00281                 {
00282                     if ( !isset( $maxWidth[$colSpan] ) )
00283                     {
00284                         $maxWidth[$colSpan] = array();
00285                     }
00286                     $maxWidth[$colSpan][$realColCount] = $wMax;
00287                 }
00288 
00289                 if ( isset( $minWidth[$colSpan][$realColCount] ) )
00290                 {
00291                     if ( $wMin > $minWidth[$colSpan][$realColCount] )
00292                     {
00293                         $minWidth[$colSpan][$realColCount] = $wMin;
00294                     }
00295                 }
00296                 else
00297                 {
00298                     if ( !isset( $minWidth[$colSpan] ) )
00299                     {
00300                         $minWidth[$colSpan] = array();
00301                     }
00302                     $minWidth[$colSpan][$realColCount] = $wMin;
00303                 }
00304 
00305                 $realColCount += $colSpan;
00306 
00307                 if ( $realColCount > $maxRowCount )
00308                 {
00309                     $maxRowCount = $realColCount;
00310                 }
00311             }
00312         }
00313 
00314         // calculate the start positions of each of the columns
00315         // Set pre defined max column width data
00316         for ( $columnCount = 0; $columnCount < count( $cols ); $columnCount++ ){
00317             if ( isset( $options['cols'][$columnCount] ) && isset($options['cols'][$columnCount]['width']) && $options['cols'][$colName]['width']>0)
00318             {
00319                 $colSpan = 1;
00320                 if ( isset( $options['cellData'][$realColCount.',0']['size'] ) )
00321                 {
00322                     $colSpan = $options['cellData'][$realColCount.',0']['size'];
00323                 }
00324 
00325                 $maxWidth[$colSpan][$columnCount] = $options['cols'][$colName]['width'] - $options['gap'] - 2*$options['cellPadding'];
00326             }
00327         }
00328 
00329         // Scale column widths
00330         $pos=array();
00331         $columnWidths = array();
00332         $minWidthArray = array();
00333         for ( $offset = 0; $offset < count( $cols ); ++$offset )
00334         {
00335             $columnWidths[$offset] = 0;
00336             $minWidthArray[$offset] = 0;
00337         }
00338         $x=0;
00339         $t=$x;
00340         $adjustmentWidth=0;
00341         $setWidth=0;
00342         foreach ( $maxWidth as $span => $tmp1 )
00343         {
00344             foreach ( $maxWidth[$span] as $offset => $tmp2 )
00345             {
00346                 $currentWidth = 0;
00347                 $currentMinWidth = 0;
00348                 for ( $innerCount = 0; $innerCount < $span; $innerCount++ )
00349                 {
00350                     $currentWidth += $columnWidths[$offset+$innerCount];
00351                     $currentMinWidth += $minWidthArray[$offset + $innerCount];
00352                 }
00353                 if ( $maxWidth[$span][$offset] > $currentWidth )
00354                 {
00355                     if ( $currentWidth == 0 ) // no width set
00356                     {
00357                         for ( $i = 0; $i < $span; $i++ )
00358                         {
00359                             $columnWidths[$offset + $i] = ceil( $maxWidth[$span][$offset] / $span );
00360                             $minWidthArray[$offset + $i] = ceil( $minWidth[$span][$offset] / $span );
00361                         }
00362                     }
00363                     else // scale previous set widths
00364                     {
00365                         for ( $i = 0; $i < $span; $i++ )
00366                         {
00367                             $columnWidths[$offset + $i] = ceil( $maxWidth[$span][$offset] / $currentWidth * $columnWidths[$offset+$i] );
00368                             $minWidthArray[$offset + $i] = ceil( $minWidth[$span][$offset] / $currentMinWidth * $minWidthArray[$offset+$i] );
00369                         }
00370                     }
00371                 }
00372             }
00373         }
00374 
00375         $t = 0;
00376         foreach ( $columnWidths as $count => $width )
00377         {
00378             $pos[$count]=$t;
00379             // if the column width has been specified then set that here, also total the
00380             $t += $width + $options['gap'] + 2*$options['cellPadding'];
00381             $adjustmentWidth += $width;
00382             $setWidth += $options['gap'] + 2*$options['cellPadding'];
00383             $pos[$count+1]=$t;
00384         }
00385         $pos['_end_'] = $t;
00386 
00387         // if maxWidth is specified, and the table is too wide, and the width has not been set,
00388         // then set the width.
00389         if ($options['width']==0 && $options['maxWidth'] && $pos['_end_']>$options['maxWidth']){
00390             // then need to make this one smaller
00391             $options['width']=$options['maxWidth'];
00392         }
00393 
00394         // calculate total table width before limiting
00395         $totalTableWidth = 0;
00396         foreach ( array_keys( $columnWidths ) as $idx ){
00397             $totalTableWidth += $columnWidths[$idx];
00398         }
00399 
00400         if ( $options['width'] == 0 &&
00401              $totalTableWidth > $this->ez['pageWidth'] - $this->leftMargin() - $this->rightMargin() )
00402         {
00403             $options['width'] = $this->ez['pageWidth'] - $this->leftMargin() - $this->rightMargin();
00404         }
00405 
00406         // calculated width as forced. Shrink or enlarge.
00407         $newColumnSize = $this->eZCalculateColumnWidth( $columnWidths, $options, $setWidth, $minWidthArray, $adjustmentWidth );
00408         if ( $newColumnSize !== false )
00409         {
00410             $pos = $newColumnSize;
00411             $t = $pos['_end_'];
00412         }
00413 
00414         /* Calculate max column widths */
00415         foreach ( array_keys ( $maxWidth ) as $colspan )
00416         {
00417             foreach ( array_keys( $maxWidth[$colspan] ) as $offset )
00418             {
00419                 $maxWidth[$colspan][$offset] = 0;
00420                 for ( $columnCount = $offset; $columnCount < $offset + $colspan; $columnCount ++ )
00421                 {
00422                     if ( $maxWidth[$colspan][$offset] == 0 )
00423                     {
00424                         $maxWidth[$colspan][$offset] -= ( $options['gap'] + 2*$options['cellPadding'] );
00425                     }
00426                     $maxWidth[$colspan][$offset] += ( $pos[$columnCount + 1] - $pos[$columnCount] );
00427                 }
00428             }
00429         }
00430 
00431         // now adjust the table to the correct location across the page
00432         switch ($options['xPos']){
00433             case 'left':
00434                 $xref = $this->leftMargin();
00435             break;
00436             case 'right':
00437                 $xref = $this->ez['pageWidth'] - $this->rightMargin();
00438             break;
00439             case 'centre':
00440             case 'center':
00441                 $xref = $middle;
00442             break;
00443             default:
00444                 $xref = $options['xPos'];
00445             break;
00446         }
00447         switch ($options['xOrientation']){
00448             case 'left':
00449             case 'right':
00450                 $dx = $xref;
00451             break;
00452             case 'centre':
00453             case 'center':
00454                 $dx = $xref-$t/2;
00455             break;
00456         }
00457 
00458         foreach($pos as $key=>$value){
00459             $pos[$key] += $dx + $options['gap']/2;
00460         }
00461         $x0=$x+$dx + $options['gap']/2;
00462         $x1=$t+$dx + $options['gap']/2;
00463 
00464         $baseLeftMargin = $this->leftMargin();
00465         $basePos = $pos;
00466         $baseX0 = $x0;
00467         $baseX1 = $x1;
00468 
00469         // ok, just about ready to make me a table
00470         $this->setColor( $options['textCol'] );
00471 
00472         $middle = ($x1+$x0)/2;
00473 
00474         // start a transaction which will be used to regress the table, if there are not enough rows protected
00475         if ($options['protectRows']>0){
00476             $this->transaction('start');
00477             $movedOnce=0;
00478         }
00479         $abortTable = 1;
00480 
00481         if ( $options['yBottom'] > 0 ) // for aligning table to bottom
00482         {
00483             $options['test'] = 1;
00484         }
00485 
00486         while ($abortTable){
00487             $abortTable=0;
00488 
00489             $dm = $this->ez['leftMargin']-$baseLeftMargin;
00490             foreach($basePos as $key=>$value){
00491                 $pos[$key] += $dm;
00492             }
00493             $x0=$baseX0+$dm;
00494             $x1=$baseX1+$dm;
00495             $middle = ($x1+$x0)/2;
00496 
00497             // margins may have changed on the newpage
00498             $dm = $this->ez['leftMargin']-$baseLeftMargin;
00499             foreach($basePos as $key => $value){
00500                 $pos[$key] += $dm;
00501             }
00502             $x0=$baseX0+$dm;
00503             $x1=$baseX1+$dm;
00504 
00505             $y=$this->y; // to simplify the code a bit
00506             $startY = $y;
00507 
00508             // make the table
00509             $height = $this->getFontHeight($options['fontSize']);
00510             $decender = $this->getFontDecender($options['fontSize']);
00511 
00512             $y0=$y+$decender;
00513             $dy=0;
00514             if ($options['showHeadings']){
00515                 // this function will move the start of the table to a new page if it does not fit on this one
00516                 $headingHeight = $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
00517                 $y0 = $y+$headingHeight;
00518                 $y1 = $y;
00519 
00520                 $dm = $this->leftMargin()-$baseLeftMargin;
00521                 foreach($basePos as $k=>$v){
00522                     $pos[$k]=$v+$dm;
00523                 }
00524                 $x0=$baseX0+$dm;
00525                 $x1=$baseX1+$dm;
00526 
00527             } else {
00528                 $y1 = $y0;
00529             }
00530             $firstLine=1;
00531 
00532 
00533             $isHelperObjectNeeded = ( !$options['test'] && ( $options['shaded'] || isset( $options['titleCellCMYK'] ) ) );
00534             // open an object here so that the text can be put in over the shading
00535             if ( $isHelperObjectNeeded ){
00536                 $this->saveState();
00537                 $textObjectId = $this->openObject();
00538                 $this->closeObject();
00539                 $this->addObject($textObjectId);
00540                 $this->reopenObject($textObjectId);
00541             }
00542 
00543             $cnt=0;
00544             $newPage=0;
00545             $newPageLine = 0;
00546             $tableHeaderRow = array();
00547             $maxRowCount = count( $data );
00548             $oldRowCount = -1;
00549 
00550             $leftOvers=array();
00551 
00552             for ( $rowCount = 0; $rowCount < $maxRowCount; ++$rowCount )
00553             {
00554                 if ( $oldRowCount != -1)
00555                 {
00556                     $rowCount = $oldRowCount;
00557                     $oldRowCount = -1;
00558                 }
00559 
00560                 $row = $data[$rowCount];
00561 
00562                 $cnt++;
00563                 // the transaction support will be used to prevent rows being split
00564                 if ($options['splitRows']==0){
00565                     $pageStart = $this->ezPageCount;
00566                     if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){
00567                         $columnStart = $this->ez['columns']['colNum'];
00568                     }
00569                     if ( !$options['test'] )
00570                     {
00571                         $this->transaction('start');
00572                     }
00573                     $row_orig = $data[$rowCount];
00574                     $y_orig = $y;
00575                     $y0_orig = $y0;
00576                     $y1_orig = $y1;
00577                 }
00578                 $ok=0;
00579                 $secondTurn=0;
00580                 while(!$abortTable && $ok == 0){
00581 
00582                     $maxRowHeight=0;
00583                     $newRow=1;
00584                     while(!$abortTable && ($newPage || $newRow)){
00585 
00586                         $resetLeftOvers = true;
00587                         if ( count( $leftOvers ) > 0 )
00588                             $row = $leftOvers;
00589 
00590                         if ($newPage || $y<$this->ez['bottomMargin'] || (isset($options['minRowSpace']) && $y<($this->ez['bottomMargin']+$options['minRowSpace'])) ){
00591                             // check that enough rows are with the heading
00592                             if ($options['protectRows']>0 && $movedOnce==0 && $cnt<=$options['protectRows']){
00593                                 // then we need to move the whole table onto the next page
00594                                 $movedOnce = 1;
00595                                 $abortTable = 1;
00596                             }
00597 
00598                             $y2=$y-$maxRowHeight+2*$height+$decender-$newRow*$height;
00599                             if ($options['showLines']){
00600                                 if (!$options['showHeadings']){
00601                                     $y0=$y1;
00602                                 }
00603                             }
00604                             if ( $isHelperObjectNeeded )
00605                             {
00606                                 $this->closeObject();
00607                                 $this->restoreState();
00608                             }
00609                             $this->ezNewPage();
00610                             // and the margins may have changed, this is due to the possibility of the columns being turned on
00611                             // as the columns are managed by manipulating the margins
00612 
00613                             $dm = $this->leftMargin()-$baseLeftMargin;
00614                             foreach($basePos as $k=>$v){
00615                                 $pos[$k]=$v+$dm;
00616                             }
00617 
00618                             $x0=$baseX0+$dm;
00619                             $x1=$baseX1+$dm;
00620 
00621                             if ( $isHelperObjectNeeded )
00622                             {
00623                                 $this->saveState();
00624                                 $textObjectId = $this->openObject();
00625                                 $this->closeObject();
00626                                 $this->addObject($textObjectId);
00627                                 $this->reopenObject($textObjectId);
00628                             }
00629                             $this->setColor( $options['textCol'], 1 );
00630                             $y = $this->ez['pageHeight']-$this->ez['topMargin'];
00631                             $y0=$y+$decender;
00632                             $maxRowHeight=0;
00633                             if ($options['showHeadings']){
00634                                 $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
00635                                 $y1=$y;
00636                             } else {
00637                                 $y1=$y0;
00638                             }
00639                             $firstLine=1;
00640                             $y -= $height;
00641 
00642                             if ( $options['repeatTableHeader'] && $oldRowCount == -1)
00643                             {
00644                                 $oldRowCount = $rowCount;
00645                                 $rowCount = 0;
00646                                 $row = $data[$rowCount];
00647                                 $resetLeftOvers = false;
00648                             }
00649                         }
00650 
00651                         $newRow=0;
00652                         // write the actual data
00653                         // if these cells need to be split over a page, then $newPage will be set, and the remaining
00654                         // text will be placed in $leftOvers
00655                         $newPage=0;
00656                         if ( $resetLeftOvers )
00657                             $leftOvers=array();
00658 
00659                         $realColumnCount = 0;
00660 
00661                         $bgTitleX = 2147483647;
00662                         $bgTitleY = -2147483647;
00663                         $bgTitleW = 0;
00664                         $bgTitleH = 0;
00665 
00666                         for ( $columnCount = 0; $columnCount < count ( $row ); $columnCount++ )
00667                         {
00668                             // Get colSpan
00669                             if ( isset( $options['cellData'][$realColumnCount.','.$rowCount]['size'] ) )
00670                             {
00671                                 $colSpan = $options['cellData'][$realColumnCount.','.$rowCount]['size'];
00672                             }
00673                             else
00674                             {
00675                                 $colSpan = 1;
00676                             }
00677 
00678                             $this->ezSetY($y+$height);
00679                             $colNewPage=0;
00680 
00681                             $row[$columnCount] = $this->fixWhitespace( $row[$columnCount] );
00682                             $lines = explode("\n",$row[$columnCount]);
00683                             $this->y -= $options['rowGap'] + $options['cellPadding'];
00684                             $this->setXOffset( $pos[$realColumnCount] );
00685                             $leftMargin = $this->ez['leftMargin'];
00686                             $this->ez['leftMargin'] = $pos[$realColumnCount];
00687 
00688                             foreach ($lines as $line)
00689                             {
00690                                 $line = $this->ezProcessText($line);
00691                                 $start=1;
00692 
00693                                 while (strlen($line) || $start){
00694                                     $start=0;
00695                                     if (!$colNewPage){
00696                                         $this->y-=$height;
00697                                     }
00698                                     if ($this->y < $this->ez['bottomMargin']){
00699                                         $newPage=1;
00700                                         $newPageLine = 1;
00701                                         $colNewPage=1;
00702                                     }
00703                                     if ($colNewPage){
00704                                         if (isset($leftOvers[$realColumnCount])){
00705                                             $leftOvers[$realColumnCount].="\n".$line;
00706                                         } else {
00707                                             $leftOvers[$realColumnCount] = $line;
00708                                         }
00709                                         $line='';
00710                                     } else {
00711                                         if (isset($options['cols'][$realColumnCount]) && isset($options['cols'][$realColumnCount]['justification']) ){
00712                                             $just = $options['cols'][$realColumnCount]['justification'];
00713                                         } else {
00714                                             $just='left';
00715                                         }
00716                                         $storeY = $this->y;
00717                                         if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
00718                                              $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true )
00719                                         {
00720                                             $this->setColor( $options['titleTextCMYK'] );
00721                                             $fontSize = $options['titleFontSize'];
00722                                         }
00723                                         else
00724                                         {
00725                                             $this->setColor( $options['textCol'], 1 );
00726                                             $fontSize = $options['fontSize'];
00727                                         }
00728 
00729                                         $textInfo = $this->addTextWrap( $pos[$realColumnCount],
00730                                                                         $this->y,
00731                                                                         $maxWidth[$colSpan][$realColumnCount],
00732                                                                         $fontSize,
00733                                                                         $line,
00734                                                                         $just,
00735                                                                         0,
00736                                                                         $options['test'] );
00737 
00738                                         $this->y = $storeY;
00739                                         if ( isset( $textInfo['text'] ) )
00740                                             $line = $textInfo['text'];
00741                                         else
00742                                             $line = '';
00743 
00744                                         if ( $line == '' )
00745                                         {
00746                                             if ( isset( $textInfo['height'] ) )
00747                                                 $this->y -= $textInfo['height'];
00748                                         }
00749                                     }
00750                                 }
00751                             }
00752                             $this->ez['leftMargin'] = $leftMargin;
00753 
00754                             $dy=$y-$this->y+$options['rowGap']+$options['cellPadding'];
00755                             if ($dy>$maxRowHeight)
00756                             {
00757                                 $maxRowHeight=$dy;
00758                             }
00759 
00760                             /////////////////////////////////////////////////////////////////
00761                             // calc title's background rect
00762                             /////////////////////////////////////////////////////////////////
00763                             if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
00764                                  $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true &&
00765                                  isset( $options['titleCellCMYK'] ) )
00766                             {
00767                                 $cellX = $pos[$realColumnCount] - $options['gap']/2;
00768                                 $cellY = $y+$decender+$height;
00769                                 $cellW = $maxWidth[$colSpan][$realColumnCount] + $options['gap'];
00770                                 $cellH = -$maxRowHeight;
00771 
00772                                 if ( $bgTitleX > $cellX )
00773                                     $bgTitleX = $cellX;
00774 
00775                                 if ( $bgTitleY < $cellY )
00776                                     $bgTitleY = $cellY;
00777 
00778                                 $bgTitleW += $cellW;
00779 
00780                                 if ( $bgTitleH > $cellH )
00781                                     $bgTitleH = $cellH;
00782                             }
00783                             /////////////////////////////////////////////////////////////////
00784 
00785                             $realColumnCount += $colSpan;
00786 
00787                         } // End for ( ... count( $row ) ... )
00788 
00789                         if ( !$options['test'] )
00790                         {
00791                             ////////////////////////////////////////////////////////////
00792                             // draw title's background
00793                             ////////////////////////////////////////////////////////////
00794                             if( $bgTitleW != 0 && $bgTitleH != 0 )
00795                             {
00796                                 // we have non-empty rect
00797                                 $this->closeObject();
00798                                 $this->setColor( $options['titleCellCMYK'], true );
00799                                 $this->filledRectangle( $bgTitleX, $bgTitleY, $bgTitleW, $bgTitleH );
00800                                 $this->reopenObject($textObjectId);
00801                             }
00802                             ////////////////////////////////////////////////////////////
00803 
00804                             if ( isset( $options['cellData'][$realColumnCount.','.$rowCount] ) &&
00805                                  $options['cellData'][$realColumnCount.','.$rowCount]['title'] === true )
00806                             {
00807                                 $shadeCol = $options['titleCellCMYK'];
00808                             }
00809                             else
00810                             {
00811                                 if( $cnt % 2 == 0 )
00812                                 {
00813                                     $shadeCol = $options['shadeCol'];
00814                                 }
00815                                 else
00816                                 {
00817                                     $shadeCol = $options['shadeCol2'];
00818                                 }
00819                             }
00820 
00821                             $rowHeight = $maxRowHeight;
00822                             $realColumnCount = 0;
00823                             for ( $columnCount = 0; $realColumnCount < $maxRowCount; $columnCount++ )
00824                             {
00825                                 if ( isset( $options['cellData'][$realColumnCount.','.$rowCount]['size'] ) )
00826                                 {
00827                                     $colSpan = $options['cellData'][$realColumnCount.','.$rowCount]['size'];
00828                                 }
00829                                 else
00830                                 {
00831                                     $colSpan = 1;
00832                                 }
00833 
00834                                 if ( $options['shaded'] && $cnt % 2 == 0 )
00835                                 {
00836                                     $this->closeObject();
00837                                     $this->setColor( $shadeCol );
00838                                     $this->filledRectangle($pos[$realColumnCount] - $options['cellPadding'],
00839                                                            $y,
00840                                                            $maxWidth[$colSpan][$realColumnCount] + 2*$options['cellPadding'],
00841                                                            -$rowHeight );
00842                                     $this->reopenObject($textObjectId);
00843                                 }
00844 
00845                                 if ($options['shaded']==2 && $cnt%2==1){
00846                                     $this->closeObject();
00847                                     $this->setColor( $shadeCol );
00848                                     $this->filledRectangle($pos[$realColumnCount] - $options['cellPadding'],
00849                                                            $y,
00850                                                            $maxWidth[$colSpan][$realColumnCount] + 2*$options['cellPadding'],
00851                                                            -$rowHeight );
00852                                     $this->reopenObject($textObjectId);
00853                                 }
00854 
00855                                 $realColumnCount += $colSpan;
00856                             }
00857 
00858                             // now add the shading underneath
00859                             // Draw lines for each row and above
00860                             if ( $options['showLines'] > 0 )
00861                             {
00862                                 $this->saveState();
00863                                 $this->setStrokeColorRGB($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);
00864 
00865                                 if ( $rowCount == 0 || $newPageLine == 1 )
00866                                 {
00867                                     $this->line( $x0-$options['gap']/2, $y+$decender+$height, $x1-$options['gap']/2, $y+$decender+$height );
00868                                 }
00869                                 $this->line( $x0-$options['gap']/2, $y+$decender+$height, $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
00870                                 $this->line( $x1-$options['gap']/2, $y+$decender+$height, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
00871 
00872                                 if ( $options['showLines'] > 1 )
00873                                 {
00874                                     // draw inner lines
00875                                     $this->line( $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
00876 
00877                                     for ( $posOffset = 0; $posOffset < count( $pos ) - 2; )
00878                                     {
00879                                         $colSpan = 1;
00880                                         if ( isset( $options['cellData'][$posOffset.','.$rowCount]['size'] ) )
00881                                         {
00882                                             $colSpan = $options['cellData'][$posOffset.','.$rowCount]['size'];
00883                                         }
00884                                         $this->line( $pos[$posOffset+$colSpan]-$options['gap']/2, $y+$decender+$height,
00885                                                      $pos[$posOffset+$colSpan]-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
00886                                         $posOffset += $colSpan;
00887                                     }
00888                                 }
00889                                 else if ( $rowCount == count( $data ) - 1 )
00890                                 {
00891                                     $this->line( $x0-$options['gap']/2, $y+$decender+$height-$maxRowHeight, $x1-$options['gap']/2, $y+$decender+$height-$maxRowHeight );
00892                                 }
00893                                 $this->restoreState();
00894                             }
00895                             if ($options['showLines']>1){
00896                                 $this->saveState();
00897                                 $this->setStrokeColorRGB($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);
00898 
00899                                 if ($firstLine){
00900                                     $this->setLineStyle($options['outerLineThickness']);
00901                                     $firstLine=0;
00902                                 } else {
00903                                     $this->setLineStyle($options['innerLineThickness']);
00904                                 }
00905                                 $this->line($x0-$options['gap']/2,$y+$decender+$height-$maxRowHeight,$x1-$options['gap']/2,$y+$decender+$height-$maxRowHeight);
00906                                 $this->restoreState();
00907                             }
00908                         }
00909                     } // end of while
00910                     $y=$y-$maxRowHeight;
00911 
00912                     // checking row split over pages
00913                     if ( $options['splitRows'] == 0 )
00914                     {
00915                         if ( ( ($this->ezPageCount != $pageStart) || (isset($this->ez['columns']) && $this->ez['columns']['on']==1 && $columnStart != $this->ez['columns']['colNum'] ))  && $secondTurn==0){
00916                             // then we need to go back and try that again !
00917                             $newPage=1;
00918                             $newPageLine = 1;
00919                             $secondTurn=1;
00920                             $this->transaction('rewind');
00921                             $row = $row_orig;
00922                             $y = $y_orig;
00923                             $y0 = $y0_orig;
00924                             $y1 = $y1_orig;
00925                             $ok=0;
00926 
00927                             $dm = $this->leftMargin()-$baseLeftMargin;
00928                             foreach($basePos as $k=>$v){
00929                                 $pos[$k]=$v+$dm;
00930                             }
00931                             $x0=$baseX0+$dm;
00932                             $x1=$baseX1+$dm;
00933 
00934                         } else {
00935                             $this->transaction('commit');
00936                             $ok=1;
00937                         }
00938                     }
00939                     else
00940                     {
00941                         $ok=1;  // don't go round the loop if splitting rows is allowed
00942                     }
00943 
00944                 }  // end of while to check for row splitting
00945                 if ($abortTable){
00946                     if ($ok==0){
00947                         $this->transaction('abort');
00948                     }
00949                     // only the outer transaction should be operational
00950                     $this->transaction('rewind');
00951                     $this->ezNewPage();
00952                     break;
00953                 }
00954 
00955             } // end of ( ... $rowCount < $maxRowCount ... )
00956 
00957             if ( isset ( $options['yBottom'] ) && $options['yBottom'] > 0 )
00958             {
00959                 $tableHeight = $startY - $y;
00960                 $this->y = $options['yBottom'] + $tableHeight;
00961                 $yBottom = $options['yBottom'];
00962                 unset( $options['yBottom'] );
00963                 $options['test'] = 0;
00964                 $this->transaction('rewind');
00965 //                $this->transaction('start');
00966                 $abortTable = 1;
00967                 continue;
00968             }
00969 
00970         } // end of while ($abortTable)
00971 
00972         // table has been put on the page, the rows guarded as required, commit.
00973         $this->transaction('commit');
00974 
00975         $y2=$y+$decender;
00976         if ($options['showLines']){
00977             if (!$options['showHeadings']){
00978                 $y0=$y1;
00979             }
00980 //            $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);
00981         }
00982 
00983         // close the object for drawing the text on top
00984         if ( $isHelperObjectNeeded ){
00985             $this->closeObject();
00986             $this->restoreState();
00987         }
00988 
00989         if ( $options['overwrite'] > 0 )
00990         {
00991             $this->y=$tableStartY;
00992         }
00993         else
00994         {
00995             $this->y=$y;
00996         }
00997 
00998         return $this->y;
00999     }
01000 
01001     /*!
01002      \private
01003      Calculate Table column widths
01004 
01005      \param ColumnWidth Array
01006      \param Table options
01007      \param Total Width
01008      \param Margin Width
01009      \param minimum Table width Array
01010      \param Position array ( for private use only ).
01011      \return Array of fixed column sizes ( returned )
01012     */
01013     function eZCalculateColumnWidth( $columnWidthArray,
01014                                      $options,
01015                                      $marginWidth,
01016                                      $minWidthArray,
01017                                      $totalWidth,
01018                                      $fixedSizeArray = array() )
01019     {
01020         $newWidth = 0;
01021         if ( $options['width'] && $totalWidth>0 ){
01022             $newCleanWidth = $options['width'] - $marginWidth;
01023             $t = 0;
01024             $pos = array();
01025             foreach ( $columnWidthArray as $count => $width )
01026             {
01027                 $pos[$count] = $t;
01028 
01029                 if ( isset( $fixedSizeArray[(string)$count] ) )
01030                 {
01031                     $t += $fixedSizeArray[(string)$count] + $options['gap'] + 2*$options['cellPadding'];
01032                     continue;
01033                 }
01034 
01035                 $newWidth = round( $newCleanWidth/$totalWidth * $columnWidthArray[$count] );
01036 
01037                 if ( $newWidth < $minWidthArray[$count] &&
01038                      count( $fixedSizeArray ) < count( $columnWidthArray ) )
01039                 {
01040                     $fixedSizeArray[(string)$count] = $minWidthArray[$count];
01041 
01042                     return $this->eZCalculateColumnWidth( $columnWidthArray,
01043                                                           $options,
01044                                                           $marginWidth + $minWidthArray[$count],
01045                                                           $minWidthArray,
01046                                                           $totalWidth - $minWidthArray[$count],
01047                                                           $fixedSizeArray );
01048                 }
01049                 $t += $newWidth + $options['gap'] + 2*$options['cellPadding'];
01050             }
01051             $pos[]=$t;
01052             $pos['_end_']=$t;
01053             return $pos;
01054         }
01055 
01056         return false;
01057     }
01058 
01059     function ezPrvtTableDrawLines($pos,$gap,$x0,$x1,$y0,$y1,$y2,$col,$inner,$outer,$opt=1){
01060         $x0=1000;
01061         $x1=0;
01062         $this->setStrokeColorRGB($col[0],$col[1],$col[2]);
01063         $cnt=0;
01064         $n = count($pos);
01065         foreach($pos as $x){
01066             $cnt++;
01067             if ($cnt==1 || $cnt==$n){
01068                 $this->setLineStyle($outer);
01069             } else {
01070                 $this->setLineStyle($inner);
01071             }
01072             $this->line($x-$gap/2,$y0,$x-$gap/2,$y2);
01073             if ($x>$x1){ $x1=$x; };
01074             if ($x<$x0){ $x0=$x; };
01075         }
01076         $this->setLineStyle($outer);
01077         $this->line($x0-$gap/2-$outer/2,$y0,$x1-$gap/2+$outer/2,$y0);
01078         // only do the second line if it is different to the first, AND each row does not have
01079         // a line on it.
01080         if ($y0!=$y1 && $opt<2){
01081             $this->line($x0-$gap/2,$y1,$x1-$gap/2,$y1);
01082         }
01083         $this->line($x0-$gap/2-$outer/2,$y2,$x1-$gap/2+$outer/2,$y2);
01084     }
01085 
01086     /**
01087      * Callback function to set anchor
01088      */
01089     function callAnchor( $info )
01090     {
01091         $paramArray = explode( ':', $info['p'] );
01092 
01093         $this->addDestination( $paramArray[0], $paramArray[1], $this->yOffset() + $this->getFontHeight( $this->fontSize ) );
01094     }
01095 
01096     /**
01097      * Callback function to set header
01098      */
01099     function callHeader( $params )
01100     {
01101         $options = array();
01102 
01103         if ( isset( $params['size'] ) )
01104         {
01105             $options['fontSize'] = $params['size'];
01106         }
01107 
01108         if ( isset( $params['justification'] ) )
01109         {
01110             $options['justification'] = $params['justification'];
01111         }
01112 
01113         if ( isset( $params['fontName'] ) )
01114         {
01115             $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['fontName'];
01116         }
01117 
01118         $this->addToPreStack( $options );
01119 
01120         $label = $params['label'];
01121         $level = $params['level'];
01122 
01123         return '<C:callInsertTOC:'. $label .','. $level .'>';
01124     }
01125 
01126     /**
01127      * Function for insert image
01128      */
01129     function callImage( $info )
01130     {
01131         $params = array();
01132         $leftMargin = false;
01133         $rightMargin = false;
01134 
01135         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01136 
01137         $filename = rawurldecode( $params['src'] );
01138 
01139         $mimetype = eZMimeType::findByFileContents( $filename );
01140 
01141         $this->transaction( 'start' );
01142 
01143         if ( !isset( $params['static'] ) )
01144         {
01145             $params['static'] = false;
01146         }
01147 
01148         if ( $this->yOffset()-$params['height'] < $this->ez['bottomMargin'] )
01149         {
01150             $this->ezNewPage();
01151         }
01152 
01153         if ( isset( $params['dpi'] ) )
01154         {
01155             $newWidth = (int)( $params['width'] * ( (int)$params['dpi'] / 72 ) );
01156             $newHeight = (int)( $params['height'] * ( (int)$params['dpi'] / 72 ) );
01157             $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
01158             while( file_exists( $newFilename ) )
01159             {
01160                 $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
01161             }
01162 
01163             $img = eZImageManager::factory();
01164             $newImg = $img->convert( $filename,
01165                                      $newFilename,
01166                                      false,
01167                                      array( 'filters' => array( array( 'name' => 'geometry/scaledownonly',
01168                                                                        'data' => array( $newWidth, $newHeight ) ) ) ) );
01169             $filename = $newFilename['url'];
01170         }
01171 
01172         $drawableAreaWidth = $this->ez['pageWidth'] - $this->ez['leftMargin'] - $this->ez['rightMargin'];
01173 
01174         switch( $params['align'] )
01175         {
01176             case 'right':
01177             {
01178                 $xOffset = $this->ez['pageWidth'] - ( $this->rightMargin() + $params['width'] );
01179                 $rightMargin = $this->rightMargin() + $params['width'];
01180                 if ( $rightMargin > ( $drawableAreaWidth + $this->rightMargin() ) )
01181                 {
01182                     // the image is equal or larger then width of the page(of the drawable area) => no point
01183                     // to set $rightMargin and next object(text, image, ...) should be outputted below the image.
01184                     $rightMargin = false;
01185                 }
01186             } break;
01187 
01188             case 'center':
01189             {
01190                 $xOffset = ( $this->ez['pageWidth'] - $this->rightMargin() - $this->leftMargin() ) / 2 + $this->leftMargin() - $params['width'] / 2;
01191             } break;
01192 
01193             case 'left':
01194             default:
01195             {
01196                 $xOffset = $this->leftMargin();
01197                 $leftMargin = $this->leftMargin() + $params['width'];
01198                 if ( $leftMargin > ( $drawableAreaWidth + $this->leftMargin() ) )
01199                 {
01200                     // the image is equal or larger then width of the page(of the drawable area) => no point
01201                     // to set $leftMargin and next object(text, image, ...) should be outputted below the image.
01202                     $leftMargin = false;
01203                 }
01204 
01205             } break;
01206         }
01207 
01208         if ( isset( $params['x'] ) )
01209         {
01210             $xOffset = $params['x'];
01211             $leftMargin = false;
01212             $rightMargin = false;
01213         }
01214 
01215         $yOffset = $this->yOffset();
01216         $whileCount = 0;
01217 
01218         if ( $params['width'] < $drawableAreaWidth )
01219         {
01220             while ( $this->leftMargin( $yOffset ) > $xOffset &&
01221                     ++$whileCount < 100 )
01222             {
01223                 $yOffset -= 10;
01224             }
01225         }
01226 
01227         $yOffset -= $params['height'];
01228         $yOffset += $this->lineHeight()/2;
01229         if ( isset( $params['y'] ) )
01230         {
01231             $yOffset = $params['y'];
01232         }
01233 
01234         if ( $leftMargin !== false )
01235         {
01236             $this->setLimitedLeftMargin( $yOffset - 7, $yOffset + $params['height'] + 7, $leftMargin + 7 );
01237         }
01238         if ( $rightMargin !== false )
01239         {
01240             $this->setLimitedRightMargin( $yOffset- 7, $yOffset + $params['height'] + 7, $rightMargin + 7 );
01241         }
01242 
01243         switch( $mimetype['name'] )
01244         {
01245             case 'image/gif':
01246             {
01247                 $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
01248                 while( file_exists( $newFilename ) )
01249                 {
01250                     $newFilename = eZSys::cacheDirectory() . '/' . md5( mt_rand() ) . '.jpg';
01251                 }
01252                 $newMimetype = eZMimeType::findByURL( $newFilename );
01253 
01254                 $img = eZImageManager::factory();
01255                 $newImg = $img->convert( $mimetype,
01256                                          $newMimetype,
01257                                          false,
01258                                          array() );
01259                 $this->addJpegFromFile( $newMimetype['url'],
01260                                         $xOffset,
01261                                         $yOffset,
01262                                         $params['width'],
01263                                         $params['height'] );
01264             } break;
01265 
01266             case 'image/jpeg':
01267             {
01268                 $this->addJpegFromFile( $filename,
01269                                         $xOffset,
01270                                         $yOffset,
01271                                         $params['width'],
01272                                         $params['height'] );
01273             } break;
01274 
01275             case 'image/png':
01276             {
01277                 if ( $this->addPngFromFile( $filename,
01278                                             $xOffset,
01279                                             $yOffset,
01280                                             $params['width'],
01281                                             $params['height'] ) === false )
01282                 {
01283                     $this->transaction('abort');
01284                     return;
01285                 }
01286             } break;
01287 
01288             default:
01289             {
01290                 eZDebug::writeError( 'Unsupported image file type, '. $mimetype['name'], __METHOD__ );
01291                 $this->transaction( 'abort' );
01292                 return;
01293             } break;
01294         }
01295 
01296         $this->transaction( 'commit' );
01297 
01298         if ( !$leftMargin && !$rightMargin  && !$params['static'] )
01299         {
01300             $this->y -= $params['height'] + $this->lineHeight();
01301         }
01302 
01303         return array( 'y' => $params['height'] + $this->lineHeight() );
01304     }
01305 
01306 
01307     /**
01308      * function for inserting keyword
01309      */
01310     function callKeyword( $info )
01311     {
01312         $keyWord = $this->fixWhitespace( rawurldecode( $info['p'] ) );
01313         $page = $this->ezWhatPageNumber($this->ezGetCurrentPageNumber());
01314 
01315         if ( !isset( $this->KeywordArray[$keyWord] ) )
01316         {
01317             $this->KeywordArray[$keyWord] = array();
01318         }
01319 
01320         if ( !isset( $this->KeywordArray[$keyWord][(string)$page] ) )
01321         {
01322             $label = $info['p'] .':'. $page;
01323             $this->KeywordArray[$keyWord][(string)$page] = array( 'label' => $label );
01324 
01325             $this->addDestination( 'keyword:'.$label,
01326                                    'FitH',
01327                                    $this->yOffset() );
01328         }
01329     }
01330 
01331     /**
01332      * function for inserting TOC
01333      */
01334     function callInsertTOC( $info )
01335     {
01336         $params = explode( ',', $info['p'] );
01337 
01338         $label = $params[0];
01339         $level = $params[1];
01340 
01341         $tocCount = count( $this->TOC );
01342         $this->TOC[] = array( 'label' => $this->fixWhitespace( rawurldecode( $label ) ),
01343                               'localPageNumber' => $this->ezWhatPageNumber( $this->ezGetCurrentPageNumber() ),
01344                               'level' => $level,
01345                               'pageNumber' => $this->ezGetCurrentPageNumber() );
01346         $this->addDestination( 'toc'. $tocCount,
01347                                'FitH',
01348                                $this->yOffset() + $this->getFontHeight( $this->fontSize() ) );
01349     }
01350 
01351     /**
01352      * Callback function for inserting TOC
01353      */
01354     function callTOC( $info )
01355     {
01356         $params = array();
01357 
01358         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01359 
01360         $sizes = isset( $params['size'] ) ? explode( ',', $params['size'] ) : '';
01361         $indents = isset( $params['indent'] ) ? explode( ',', $params['indent'] ) : '';
01362         $dots = isset( $params['dots'] ) ? $params['dots'] : '';
01363         $contentText = isset( $params['contentText'] ) ? $params['contentText'] : ezpI18n::tr( 'lib/ezpdf/classes', 'Contents', 'Table of contents' );
01364 
01365         $this->insertTOC( $sizes, $indents, $dots, $contentText );
01366     }
01367 
01368     /**
01369      * Callback function for creating new page
01370      */
01371     function callNewPage( $info )
01372     {
01373         $this->ezNewPage();
01374     }
01375 
01376     function callIndex( $info )
01377     {
01378         $this->ezNewPage();
01379         $fontSize = $this->fontSize();
01380         Cezpdf::ezText( ezpI18n::tr( 'lib/ezpdf/classes', 'Index', 'Keyword index name' ) . '<C:callInsertTOC:Index,1>'."\n", 26, array('justification'=>'centre'));
01381 
01382         if ( count( $this->KeywordArray ) == 0 )
01383             return;
01384 
01385         ksort( $this->KeywordArray );
01386         reset( $this->KeywordArray );
01387 
01388         $this->ezColumnsStart( array( 'num' => 2 ) );
01389 
01390         foreach( array_keys( $this->KeywordArray ) as $keyWord )
01391         {
01392             Cezpdf::ezText( $keyWord,
01393                             $fontSize,
01394                             array( 'justification' => 'left' ) );
01395 
01396             foreach( array_keys( $this->KeywordArray[$keyWord] ) as $page )
01397             {
01398                 Cezpdf::ezText( '<c:ilink:keyword:'. $this->KeywordArray[$keyWord][$page]['label'] .'> '. $page .'</c:ilink>',
01399                                 $fontSize,
01400                                 array( 'justification' => 'right' ) );
01401             }
01402         }
01403 
01404         $this->ezColumnsStop();
01405         $this->setFontSize( $fontSize );
01406     }
01407 
01408     /*!
01409      Create Table Of Contents (TOC)
01410 
01411      \param size array, element 0 define size of header level 1, etc.
01412      \param indent, element 0 define indent of header level 1, etc.
01413      \param dots, if true, generate dots between name and pagenumber
01414      \param content text
01415      \param level, how many header levels to generate toc form
01416     */
01417     function insertTOC( $sizeArray = array( 20, 18, 16, 14, 12 ),
01418                         $indentArray = array( 0, 4, 6, 8, 10 ),
01419                         $dots = true,
01420                         $contentText = '',
01421                         $level = 3 )
01422     {
01423         $fontSize = $this->fontSize();
01424         $this->ezStopPageNumbers(1,1);
01425 
01426         $this->ezInsertMode(1,1,'before');
01427         $this->ezNewPage();
01428         Cezpdf::ezText( $contentText ."\n", 26, array('justification'=>'centre'));
01429 
01430         foreach($this->TOC as $k=>$v){
01431             if ( $v['level'] <= $level )
01432             {
01433                 if ( $dots )
01434                 {
01435                     Cezpdf::ezText( '<c:ilink:toc'. $k .'>'. $v['label'] .'</c:ilink>',
01436                                     $sizeArray[$v['level']-1],
01437                                     array( 'left' => $indentArray[$v['level']-1],
01438                                            'right' => 100 ) );
01439                     Cezpdf::ezText( '<C:dots:'. $sizeArray[$v['level']-1].$v['localPageNumber'] .'>',
01440                                     $sizeArray[$v['level']-1] );
01441                     Cezpdf::ezText( "\n", $sizeArray[$v['level']-1] );
01442                 }
01443                 else
01444                 {
01445                     Cezpdf::ezText( '<c:ilink:toc'. $k .'>'.$v['label'].'</c:ilink>',
01446                                     $sizeArray[$v['level']-1],
01447                                     array( 'left' => $indentArray[$v['level']-1] ) );
01448                     Cezpdf::ezText( '<c:ilink:toc'. $k .'>'. $v['localPageNumber'] .'</c:ilink>',
01449                                     $sizeArray[$v['level']-1],
01450                                     array( 'justification' => 'right' ) );
01451                 }
01452             }
01453         }
01454 
01455         $this->setFontSize( $fontSize );
01456         $this->ezInsertMode(0);
01457     }
01458 
01459     function dots($info)
01460     {
01461         // draw a dotted line over to the right and put on a page number
01462         $tmp = $info['p'];
01463         $size = substr($tmp, 0, 2);
01464         $thick=1;
01465         $lbl = substr($tmp,2);
01466         $xpos = $this->ez['pageWidth'] - $this->rightMargin() - $this->leftMargin();
01467 
01468         $this->saveState();
01469         $this->setLineStyle($thick,'round','',array(0,10));
01470         $this->line($xpos,$info['y'],$info['x']+5,$info['y']);
01471         $this->restoreState();
01472         $this->addText($xpos+5,$info['y'],$size,$lbl);
01473         $this->setXOffset( $xpos+5+$this->getTextWidth($lbl, $size) );
01474     }
01475 
01476     /**
01477      * Callback function to set font
01478      */
01479     function callFont( $params )
01480     {
01481         $options = array();
01482 
01483         $keyArray = array ( 'c', 'm', 'y', 'k' );
01484         if ( isset( $params['cmyk'] ) )
01485         {
01486             $params['cmyk'] = explode( ',', $params['cmyk'] );
01487             foreach ( array_keys( $params['cmyk'] ) as $key )
01488             {
01489                 $options['cmyk'][$keyArray[$key]] = $params['cmyk'][$key];
01490             }
01491             $this->setStrokeColor( $params['cmyk'] );
01492         }
01493 
01494         if ( isset( $params['name'] ) )
01495         {
01496             $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['name'];
01497         }
01498 
01499         if ( isset( $params['size'] ) )
01500         {
01501             $options['fontSize'] = $params['size'];
01502         }
01503 
01504         if ( isset( $params['justification'] ) )
01505         {
01506             $options['justification'] = $params['justification'];
01507         }
01508 
01509         $this->addToPreStack( $options );
01510 
01511         return '';
01512     }
01513 
01514     function &fixWhitespace( &$text )
01515     {
01516         $text = str_replace( array( self::SPACE,
01517                                     self::TAB,
01518                                     self::NEWLINE ),
01519                              array( ' ',
01520                                     "\t",
01521                                     "\n" ),
01522                              $text );
01523         return $text;
01524     }
01525 
01526     /**
01527      * Function overriding the default ezText function for doing preprocessing of text
01528      */
01529     function ezText( $text, $size=0, $options=array(), $test=0)
01530     {
01531         $text = eZPDFTable::fixWhitespace( $text );
01532 
01533         $textLen = strlen( $text );
01534         $newText = '';
01535         for ( $offSet = 0; $offSet < $textLen; $offSet++ )
01536         {
01537             if ( $text[$offSet] == '<' )
01538             {
01539                 if ( strcmp( substr($text, $offSet+1, strlen( 'ezCall' ) ), 'ezCall' ) == 0 ) // ez library preprocessing call.
01540                 {
01541                     $newTextLength = strlen( $newText );
01542                     if ( $newTextLength > 0 && $newText[$newTextLength - 1] == "\n" )
01543                     {
01544                         $newText = rtrim( $newText, "\n" );
01545                         $this->addDocSpecification( $newText );
01546                         $newText = "\n";
01547                     }
01548                     else
01549                     {
01550                         $this->addDocSpecification( $newText );
01551                         $newText = '';
01552                     }
01553 
01554                     $params = array();
01555                     $funcName = '';
01556 
01557                     $offSet = eZPDFTable::extractFunction( $text, $offSet, $funcName, $params, 'ezCall' );
01558 
01559                     $newText .= $this->$funcName( $params );
01560 
01561                     continue;
01562                 }
01563                 else if ( strcmp( substr($text, $offSet+1, strlen( '/ezCall' ) ), '/ezCall' ) == 0 )
01564                 {
01565                     $this->addDocSpecification( $newText );
01566                     array_pop( $this->PreStack );
01567                     $offSet = strpos( $text, '>', $offSet );
01568                     $newText = '';
01569                     continue;
01570                 }
01571                 else if ( strcmp( substr($text, $offSet+1, strlen( 'ezGroup' ) ), 'ezGroup' ) == 0 ) // special call for processing whole text group, used by extends table.
01572                 {
01573                     $newTextLength = strlen( $newText );
01574                     if ( $newTextLength > 0 && $newText[$newTextLength - 1] == "\n" )
01575                     {
01576                         $newText = rtrim( $newText, "\n" );
01577                         $this->addDocSpecification( $newText );
01578                         $newText = "\n";
01579                     }
01580                     else
01581                     {
01582                         $this->addDocSpecification( $newText );
01583                         $newText = '';
01584                     }
01585 
01586                     $params = array();
01587                     $funcName = '';
01588 
01589                     $offSet = eZPDFTable::extractFunction( $text, $offSet, $funcName, $params, 'ezGroup' );
01590                     $offSet++;
01591                     $endGroup = strpos( $text, '</ezGroup:', $offSet );
01592                     $groupText = substr( $text, $offSet, $endGroup - $offSet );
01593                     $groupText = urldecode( $groupText );
01594 
01595                     $this->$funcName( $params, $groupText );
01596 
01597                     $offSet = strpos( $text, '>', $endGroup );
01598                     continue;
01599                 }
01600             }
01601             $newText .= $text[$offSet];
01602         }
01603         if ( strlen( $newText ) > 0 )
01604         {
01605             $this->addDocSpecification( $newText );
01606         }
01607 
01608         $this->outputDocSpecification();
01609     }
01610 
01611     /*!
01612      \private
01613      Fixup table cell text. Removes ezCall tags, and first C:callNewLine if they exists.
01614 
01615      \param text
01616 
01617      \return text without ezgroup/ezcall tags
01618     */
01619     function fixupTableCellText( $text )
01620     {
01621         $text = preg_replace( "/^" . self::NEWLINE . "/i", "", $text );
01622         $text = preg_replace( "/" . self::NEWLINE . "$/i", "", $text );
01623         return preg_replace( "'<[\/]*?ezCall:[^<>]*?>'si", "", $text );
01624     }
01625 
01626     /*!
01627      Function for drawing rectangle in document
01628 
01629      \param parameters
01630     */
01631     function callRectangle( $info )
01632     {
01633         $params = array();
01634 
01635         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01636 
01637         $keyArray = array ( 'c', 'm', 'y', 'k' );
01638         $cmykColor = explode( ',', $params['cmyk'] );
01639 
01640         foreach ( array_keys( $cmykColor ) as $key )
01641         {
01642             $cmykColor[$keyArray[$key]] = $cmykColor[$key];
01643             unset( $cmykColor[$key] );
01644         }
01645 
01646         $stackColor = $this->currentStrokeColour;
01647         $this->setStrokeColor( $cmykColor );
01648 
01649         if ( isset( $params['x'] ) )
01650         {
01651             $x1 = $params['x'];
01652             $x2 = $x1 + $params['width'];
01653         }
01654         if ( isset( $params['y'] ) )
01655         {
01656             $y1 = $params['y'];
01657             $y2 = $y1 + $params['height'];
01658         }
01659 
01660         if ( isset( $params['topY'] ) )
01661         {
01662             $y2 = $params['topY'];
01663             if ( $params['height'] > 0 )
01664             {
01665                 $y1 = $params['topY'] - $params['height'];
01666             }
01667             else
01668             {
01669                 $y1 = $this->yOffset() + $params['height'];
01670             }
01671         }
01672 
01673         $this->setLineStyle( $params['line_width'] );
01674 
01675         if ( $params['corner'] )
01676         {
01677             $factor = $params['corner'];
01678             $degree = 0;
01679 
01680             $this->line( $x1 + $factor, $y1, $x2 - $factor, $y1 );
01681             $this->line( $x2, $y1 + $factor, $x2, $y2 - $factor );
01682             $this->line( $x2 - $factor, $y2, $x1 + $factor, $y2 );
01683             $this->line( $x1, $y2 - $factor, $x1, $y1 + $factor );
01684 
01685             $this->curve( $x2 - $factor, $y1,
01686                           $x2, $y1 - $degree * $factor,
01687                           $x2 + $degree * $factor, $y1,
01688                           $x2, $y1 + $factor );
01689             $this->curve( $x2, $y2 - $factor,
01690                           $x2 + $degree * $factor, $y2,
01691                           $x2, $y2 + $degree * $factor,
01692                           $x2 - $factor, $y2 );
01693             $this->curve( $x1 + $factor, $y2,
01694                           $x1, $y2 + $degree * $factor,
01695                           $x1 - $degree * $factor, $y2,
01696                           $x1, $y2 - $factor );
01697             $this->curve( $x1, $y1 + $factor,
01698                           $x1 - $degree * $factor, $y1,
01699                           $x1, $y1 - $degree * $factor,
01700                           $x1 + $factor, $y1 );
01701         }
01702         else
01703         {
01704             $this->rectangle( $x1, $y1, $params['width'], $params['height'] );
01705         }
01706 
01707         $this->setColor( $stackColor );
01708     }
01709 
01710     /*!
01711      Set new margins
01712     */
01713     function callSetMargin( $info )
01714     {
01715         $options = array();
01716 
01717         eZPDFTable::extractParameters( $info['p'], 0, $options, true );
01718 
01719         if ( isset( $options['left'] ) )
01720         {
01721             $this->ez['leftMargin'] = (float)$options['left'];
01722         }
01723 
01724         if ( isset( $options['delta_left'] ) )
01725         {
01726             $this->ez['leftMargin'] += $options['delta_left'];
01727         }
01728 
01729         if ( isset( $options['right'] ) )
01730         {
01731             $this->ez['rightMargin'] = (float)$options['right'];
01732         }
01733 
01734         if ( isset( $options['delta_right'] ) )
01735         {
01736             $this->ez['rightMargin'] += $options['delta_right'];
01737         }
01738 
01739         if ( isset( $options['bottom'] ) )
01740         {
01741             $this->ez['bottomMargin'] = (float)$options['bottom'];
01742         }
01743 
01744         if ( isset( $options['line_space'] ) )
01745         {
01746             $this->ez['lineSpace'] = (float)$options['line_space'];
01747         }
01748 
01749         if ( isset( $options['top'] ) )
01750         {
01751             $this->ez['topMargin'] = (float)$options['top'];
01752             if ( $this->yOffset() < $this->ez['topMargin'] )
01753             {
01754                 $this->ez['yOffset'] = (float)$options['y'];
01755                 $this->y = (float)$options['y'];
01756             }
01757         }
01758 
01759         if ( isset( $options['x'] ) )
01760         {
01761             $this->setXOffset( (float)$options['x'] );
01762         }
01763 
01764         if ( isset( $options['y'] ) )
01765         {
01766             $this->ez['yOffset'] = (float)$options['y'];
01767             $this->y = (float)$options['y'];
01768         }
01769 
01770         return array( 'x' => $this->xOffset() );
01771     }
01772 
01773     /*!
01774      Draw filled circle
01775     */
01776     function callCircle( $info )
01777     {
01778         $params = array();
01779         $forceYPos = true;
01780 
01781         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01782 
01783         $keyArray = array ( 'c', 'm', 'y', 'k' );
01784         $cmykColor = explode( ',', $params['cmyk'] );
01785 
01786         foreach ( array_keys( $cmykColor ) as $key )
01787         {
01788             $cmykColor[$keyArray[$key]] = $cmykColor[$key];
01789             unset( $cmykColor[$key] );
01790         }
01791 
01792         $strokeStackColor = $this->currentStrokeColour;
01793         $this->setStrokeColor( $cmykColor );
01794         $stackColor = $this->currentColour;
01795         $this->setColor( $cmykColor );
01796 
01797         if ( $params['x'] == -1 )
01798         {
01799             $params['x'] = $this->xOffset() + $params['radius'];
01800         }
01801         if ( $params['y'] == -1 )
01802         {
01803             $forceYPos = false;
01804             $params['y'] = $this->yOffset();
01805         }
01806         if ( isset( $params['yOffset'] ) )
01807         {
01808             if ( $params['yOffset'] == -1 )
01809             {
01810                 $params['y'] += $this->getFontHeight( $this->fontSize() )/2 - $params['radius'];
01811             }
01812             else
01813             {
01814                 $params['y'] += $params['yOffset'];
01815             }
01816         }
01817 
01818         if ( $params['y'] - $this->getFontHeight( $this->fontSize() ) < $this->ez['bottomMargin'] &&
01819              !$forceYPos )
01820         {
01821             $this->ezNewPage();
01822             return $this->callCircle( $info );
01823         }
01824 
01825         $params['x'] += $params['pre_indent'];
01826 
01827         $this->filledEllipse( $params['x'], $params['y'], $params['radius'] );
01828 
01829         $this->setStrokeColor( $strokeStackColor );
01830         $this->setColor( $stackColor );
01831 
01832         if ( isset( $params['indent'] ) )
01833         {
01834             return array( 'x' => $params['x'] + $params['radius'] * 2 + $params['indent'] );
01835         }
01836         else
01837         {
01838             return array( 'x' => $params['x'] + $params['radius'] * 2 );
01839         }
01840 
01841     }
01842 
01843     /*!
01844      Function for drawing filled rectangle in document
01845 
01846      \param params
01847     */
01848     function callFilledRectangle( $info )
01849     {
01850         $params = array();
01851 
01852         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01853 
01854         $keyArray = array ( 'c', 'm', 'y', 'k' );
01855         $cmykTop = explode( ',', $params['cmykTop'] );
01856         $cmykBottom = explode( ',', $params['cmykBottom'] );
01857 
01858         foreach ( array_keys( $cmykBottom ) as $key )
01859         {
01860             $cmykBottom[$keyArray[$key]] = $cmykBottom[$key];
01861             unset( $cmykBottom[$key] );
01862             $cmykTop[$keyArray[$key]] = $cmykTop[$key];
01863             unset( $cmykTop[$key] );
01864         }
01865 
01866         $this->ezShadedRectangle( $params['x'], $params['y'], $params['width'], $params['height'], $cmykTop, $cmykBottom );
01867     }
01868 
01869     /*!
01870       Function for adding footer definition to PDF document. creates call on stack for ezInsertFooter
01871 
01872       \param parameters
01873       \text inside ezGroup Tags
01874     */
01875     function callBlockFrame( $params, $text )
01876     {
01877         if ( strlen( $text ) > 0 )
01878         {
01879             $this->addDocSpecFunction( 'ezInsertBlockFrame', array( $text, $params) );
01880         }
01881     }
01882 
01883     /*!
01884       Function for adding footer definition to PDF document. creates call on stack for ezInsertFooter
01885 
01886       \param parameters
01887       \text inside ezGroup Tags
01888     */
01889     function callFrame( $params, $text )
01890     {
01891         if ( strlen( $text ) > 0 )
01892         {
01893             $this->addDocSpecFunction( 'ezInsertFrame', array( $this->fixWhitespace( $text ), $params) );
01894         }
01895     }
01896 
01897     /*!
01898       Add line to all pages
01899     */
01900     function callLine( $params, $text )
01901     {
01902         $this->addDocSpecFunction( 'ezInsertLine', array( $params ) );
01903     }
01904 
01905     /*!
01906      Draw line on current page in PDF document
01907     */
01908     function callDrawLine( $info )
01909     {
01910         $params = array();
01911         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01912 
01913         $this->setLineStyle( $params['thickness'] );
01914         $this->line( $params['x1'], $params['y1'], $params['x2'], $params['y2'] );
01915     }
01916 
01917     /*!
01918       Function for setting frame margins. Frames are used to define for example footer and header areas
01919 
01920       \param info, standard ezpdf callback function
01921     */
01922     function callFrameMargins( $info )
01923     {
01924         $params = array();
01925         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
01926 
01927         if( isset( $this->ezFrame[$params['identifier']] ) )
01928         {
01929             $this->ezFrame[$params['identifier']] = array_merge( $this->ezFrame[$params['identifier']],
01930                                                                  $params );
01931         }
01932         else
01933         {
01934             $this->ezFrame[$params['identifier']] = $params;
01935         }
01936     }
01937 
01938     /*!
01939       Insert line onto every page
01940 
01941       \param line parameters
01942     */
01943     function ezInsertLine( $params )
01944     {
01945         reset( $this->ezPages );
01946         foreach ( $this->ezPages as $pageNum => $pageID )
01947         {
01948             $this->reopenObject($pageID);
01949             $this->line( $params['x1'], $params['y1'], $params['x2'], $params['y2'] );
01950             $this->closeObject();
01951         }
01952         reset( $this->ezPages );
01953     }
01954 
01955     /*!
01956       Insert footer/header into PDF document
01957 
01958       \param text
01959       \param text parameters
01960     */
01961     function ezInsertBlockFrame( $text, $textParameters )
01962     {
01963         $header = false;
01964         switch( $textParameters['location'] )
01965         {
01966             case 'footer_block':
01967             {
01968                 $frameCoords = $this->ezFrame['footer'];
01969             } break;
01970 
01971             case 'header_block':
01972             {
01973                 $header = true;
01974                 $frameCoords = $this->ezFrame['header'];
01975             } break;
01976         }
01977 
01978         $text = str_replace( array( ' ', "\t", "\r\n", "\n" ),
01979                              '',
01980                              urldecode( $text ) );
01981 
01982         foreach ( $this->ezPages as $pageNum => $pageID )
01983         {
01984             $this->pushStack();
01985 
01986             if ( $header )
01987             {
01988                 foreach( $frameCoords as $key => $value )
01989                 {
01990                     $this->ez[$key] = $value;
01991                 }
01992                 $this->setYOffset( $this->ez['pageHeight'] - $this->ez['topMargin'] );
01993             }
01994             else
01995             {
01996                 $this->ez['topMargin'] = $this->ez['pageHeight'] - $this->ez['bottomMargin'] + $frameCoords['topMargin'];
01997                 foreach( $frameCoords as $key => $value )
01998                 {
01999                     if ( $key != 'topMargin' )
02000                     {
02001                         $this->ez[$key] = $value;
02002                     }
02003                 }
02004             }
02005 
02006             $this->setXOffset( 0 );
02007 
02008             $frameText = $text; //Create copy of text
02009             if( $textParameters['page'] == 'even' &&
02010                 $pageNum % 2 == 1 )
02011                 continue;
02012             else if ( $textParameters['page'] == 'odd' &&
02013                       $pageNum % 2 == 0 )
02014                 continue;
02015 
02016             if ( strstr( $frameText, self::PAGENUM ) !== false )
02017             {
02018                 foreach ( array_keys( $this->PageCounter ) as $identifier )
02019                 {
02020                     if ( $this->PageCounter[$identifier]['start'] <= $pageNum &&
02021                          $this->PageCounter[$identifier]['stop'] >= $pageNum )
02022                     {
02023                         $frameText = str_replace( self::PAGENUM,
02024                                                   $this->ezWhatPageNumber( $pageNum, $identifier ),
02025                                                   $frameText );
02026 
02027                         if ( strstr( $frameText, self::TOTAL_PAGENUM ) !== false )
02028                         {
02029                             $frameText = str_replace( self::TOTAL_PAGENUM,
02030                                                       $this->PageCounter[$identifier]['stop'] - $this->PageCounter[$identifier]['start'] + 1,
02031                                                       $frameText );
02032                         }
02033                     }
02034                 }
02035             }
02036 
02037             for( $levelCount = 0; $levelCount < 9; $levelCount++ )
02038             {
02039                 if ( strstr( $frameText, self::HEADER_LEVEL.$levelCount ) !== false )
02040                 {
02041                     $frameText = str_replace( self::HEADER_LEVEL.$levelCount,
02042                                               $this->headerLabel( $pageNum, $levelCount ),
02043                                               $frameText );
02044                 }
02045 
02046                 if ( strstr( $frameText, self::HEADER_LEVEL_INDEX.$levelCount ) !== false )
02047                 {
02048                     $frameText = str_replace( self::HEADER_LEVEL_INDEX.$levelCount,
02049                                               $this->headerIndex( $pageNum, $levelCount ),
02050                                               $frameText );
02051                 }
02052             }
02053 
02054             $this->reopenObject($pageID);
02055             $this->ezText( $frameText );
02056             $this->closeObject();
02057             $this->popStack();
02058         }
02059     }
02060 
02061     /*!
02062       Insert footer/header into PDF document
02063 
02064       \param text
02065       \param text parameters
02066     */
02067     function ezInsertFrame( $text, $textParameters )
02068     {
02069         $size = $this->fontSize();
02070         if ( isset( $textParameters['size'] ) )
02071         {
02072             $size = $textParameters['size'];
02073         }
02074 
02075         $previousFont = $this->currentFont();
02076         if ( isset( $textParameters['font'] ) )
02077         {
02078             $this->selectFont( $textParameters['font'] );
02079         }
02080 
02081         $justification = $this->justification();
02082         if ( isset( $textParameters['justification'] ) )
02083         {
02084             $justification = $textParameters['justification'];
02085         }
02086 
02087         switch( $textParameters['location'] )
02088         {
02089             case 'footer':
02090             {
02091                 $frameCoords =& $this->ezFrame['footer'];
02092             } break;
02093 
02094             case 'frame_header':
02095             {
02096                 $frameCoords =& $this->ezFrame['header'];
02097             } break;
02098 
02099             default:
02100             {
02101                 $frameCoords =& $this->ezFrame[0];
02102             } break;
02103         }
02104 
02105         foreach ( $this->ezPages as $pageNum => $pageID )
02106         {
02107             if ( $pageNum < $textParameters['pageOffset'] )
02108                 continue;
02109 
02110             $frameText = $text; //Create copy of text
02111             if( $textParameters['page'] == 'even' &&
02112                 $pageNum % 2 == 1 )
02113                 continue;
02114             else if ( $textParameters['page'] == 'odd' &&
02115                       $pageNum % 2 == 0 )
02116                 continue;
02117 
02118             $countIdentifier = '';
02119             if ( strstr( $frameText, self::PAGENUM ) !== false )
02120             {
02121                 foreach ( array_keys( $this->PageCounter ) as $identifier )
02122                 {
02123                     if ( $this->PageCounter[$identifier]['start'] <= $pageNum &&
02124                          $this->PageCounter[$identifier]['stop'] >= $pageNum )
02125                     {
02126                         $frameText = str_replace( self::PAGENUM,
02127                                                   $this->ezWhatPageNumber( $pageNum, $identifier ),
02128                                                   $frameText );
02129 
02130                         if ( strstr( $frameText, self::TOTAL_PAGENUM ) !== false )
02131                         {
02132                             $frameText = str_replace( self::TOTAL_PAGENUM,
02133                                                       $this->PageCounter[$identifier]['stop'] - $this->PageCounter[$identifier]['start'] + 1,
02134                                                       $frameText );
02135                         }
02136                     }
02137                 }
02138             }
02139 
02140             for( $levelCount = 0; $levelCount < 9; $levelCount++ )
02141             {
02142                 if ( strstr( $frameText, self::HEADER_LEVEL.$levelCount ) !== false )
02143                 {
02144                     $frameText = str_replace( self::HEADER_LEVEL.$levelCount,
02145                                               $this->headerLabel( $pageNum, $levelCount ),
02146                                               $frameText );
02147                 }
02148 
02149                 if ( strstr( $frameText, self::HEADER_LEVEL_INDEX.$levelCount ) !== false )
02150                 {
02151                     $frameText = str_replace( self::HEADER_LEVEL_INDEX.$levelCount,
02152                                               $this->headerIndex( $pageNum, $levelCount ),
02153                                               $frameText );
02154                 }
02155             }
02156 
02157             $yOffset = $frameCoords['y0'] - $frameCoords['topMargin'];
02158             if ( $textParameters['newline'] )
02159             {
02160                 $yOffset -= $this->getFontHeight( $size );
02161             }
02162 
02163             $yOffset -= $this->getFontHeight( $size );
02164             $xOffset = $frameCoords['leftMargin'];
02165             $pageWidth = $this->ez['pageWidth'] - $frameCoords['leftMargin'] - $frameCoords['rightMargin'];
02166 
02167             $this->reopenObject($pageID);
02168 
02169             $lines = explode( "\n", $frameText );
02170             foreach ( array_keys( $lines ) as $key )
02171             {
02172                 $start=1;
02173                 $line = $lines[$key];
02174                 while (strlen($line) || $start){
02175                     $start = 0;
02176                     $textInfo = $this->addTextWrap( $xOffset, $yOffset, $pageWidth, $size, $line, $justification );
02177                     $line = $textInfo['text'];
02178 
02179                     if ( strlen( $line ) )
02180                     {
02181                         $yOffset -= $this->getFontHeight( $size );
02182                     }
02183                 }
02184             }
02185 
02186             $this->closeObject();
02187         }
02188 
02189         $this->selectFont( $previousFont );
02190     }
02191 
02192     /*!
02193      * Function for inserting frontpage into document. Called by ezGroup specification
02194      *
02195      * \param parameters
02196      * \param text in ezGroup
02197      */
02198     function callFrontpage( $params, $text )
02199     {
02200         $this->addDocSpecFunction( 'insertFrontpage', array( $params, $text ) );
02201     }
02202 
02203     /*!
02204      * Insert front page
02205      */
02206     function insertFrontpage( $params, $text )
02207     {
02208         $this->saveState();
02209         $closeObject = false;
02210         if ( $this->FrontpageID == null )
02211         {
02212             $this->ezInsertMode(1,1,'before');
02213             $this->ezNewPage();
02214             $this->FrontpageID = $this->currentPage;
02215         }
02216         else if( $this->currentPage != $this->FrontpageID )
02217         {
02218             $this->reopenObject( $this->FrontpageID );
02219             $closeObject = true;
02220         }
02221 
02222         $fontSize = $this->fontSize();
02223 
02224         $text = $this->fixWhitespace( $text );
02225         $this->setXOffset( 0 );
02226 
02227         Cezpdf::ezText( $text, $params['size'], array( 'justification' => $params['justification'],
02228                                                        'top_margin' => $params['top_margin'] ) );
02229 
02230         $this->setFontSize( $fontSize );
02231 
02232         if ( $closeObject )
02233         {
02234             $this->closeObject();
02235         }
02236         $this->restoreState();
02237     }
02238 
02239     /*!
02240      * Function for generating table definition. Called by ezGroup specification
02241      *
02242      * \param parameters
02243      * \param text in ezGroup
02244      */
02245     function callTable( $params, $text )
02246     {
02247         $textLen = strlen( $text );
02248         $tableData = array();
02249         $cellData = array();
02250         $showLines = 2;
02251         $rowCount = 0;
02252         $columnCount = 0;
02253 
02254         $columnText = '';
02255 
02256         $keyArray = array ( 'c', 'm', 'y', 'k' );
02257         if ( isset( $params['titleCellCMYK'] ) )
02258         {
02259             $params['titleCellCMYK'] = explode( ',', $params['titleCellCMYK'] );
02260             foreach ( array_keys( $params['titleCellCMYK'] ) as $key )
02261             {
02262                 $params['titleCellCMYK'][$keyArray[$key]] = $params['titleCellCMYK'][$key];
02263                 unset( $params['titleCellCMYK'][$key] );
02264             }
02265         }
02266 
02267         if ( isset( $params['cellCMYK'] ) )
02268         {
02269             $params['cellCMYK'] = explode( ',', $params['cellCMYK'] );
02270             foreach ( array_keys( $params['cellCMYK'] ) as $key )
02271             {
02272                 $params['cellCMYK'][$keyArray[$key]] = $params['cellCMYK'][$key];
02273                 unset( $params['cellCMYK'][$key] );
02274             }
02275             $params['shaded'] = 2;
02276             $params['shadeCol'] = $params['cellCMYK'];
02277             $params['shadeCol2'] = $params['cellCMYK'];
02278         }
02279 
02280         if ( isset( $params['textCMYK'] ) )
02281         {
02282             $params['textCMYK'] = explode( ',', $params['textCMYK'] );
02283             foreach ( array_keys( $params['textCMYK'] ) as $key )
02284             {
02285                 $params['textCMYK'][$keyArray[$key]] = $params['textCMYK'][$key];
02286                 unset( $params['textCMYK'][$key] );
02287             }
02288             $params['textCol'] = $params['textCMYK'];
02289         }
02290 
02291         if ( isset( $params['titleTextCMYK'] ) )
02292         {
02293             $params['titleTextCMYK'] = explode( ',', $params['titleTextCMYK'] );
02294             foreach ( array_keys( $params['titleTextCMYK'] ) as $key )
02295             {
02296                 $params['titleTextCMYK'][$keyArray[$key]] = $params['titleTextCMYK'][$key];
02297                 unset( $params['titleTextCMYK'][$key] );
02298             }
02299             $params['titleTextCMYK'] = $params['titleTextCMYK'];
02300         }
02301 
02302         if ( isset( $params['showLines'] ) )
02303         {
02304             $showLines = $params['showLines'];
02305         }
02306 
02307         for ( $offSet = 0; $offSet < $textLen; $offSet++ )
02308         {
02309             if ( $text[$offSet] == '<' )
02310             {
02311                 if ( strcmp( substr($text, $offSet+1, strlen( 'tr' ) ), 'tr' ) == 0 )
02312                 {
02313                     $tableData[] = array();
02314                     $offSet++;
02315                     $offSet += strlen( 'tr' );
02316                     continue;
02317                 }
02318                 else if ( strcmp( substr($text, $offSet+1, strlen( 'td' ) ), 'td' ) == 0 )
02319                 {
02320                     $tdParams = array();
02321                     $offSet++;
02322                     $offSet += strlen( 'td' );
02323                     $offSet = eZPDFTable::extractParameters( $text, $offSet, $tdParams );
02324 
02325                     if ( count( $tdParams ) > 0 )
02326                     {
02327                         $cellData[$columnCount. ',' .$rowCount] = array();
02328                         if ( isset( $tdParams['colspan'] ) )
02329                         {
02330                             $cellData[$columnCount. ',' .$rowCount]['size'] = (int)$tdParams['colspan'];
02331                         }
02332                         if ( isset( $tdParams['align'] ) )
02333                         {
02334                             $cellData[$columnCount. ',' .$rowCount]['justification'] = $tdParams['align'];
02335                         }
02336                         if ( isset( $tdParams['width'] ) )
02337                         {
02338                             $cellData[$columnCount. ',' .$rowCount]['width'] = $tdParams['width'];
02339                         }
02340                     }
02341                     continue;
02342                 }
02343                 else if ( strcmp( substr($text, $offSet+1, strlen( 'th' ) ), 'th' ) == 0 )
02344                 {
02345                     $thParams = array();
02346                     $offSet++;
02347                     $offSet += strlen( 'th' );
02348                     $offSet = eZPDFTable::extractParameters( $text, $offSet, $thParams );
02349 
02350                     $cellData[$columnCount. ',' .$rowCount] = array();
02351                     $cellData[$columnCount.','.$rowCount]['title'] = true;
02352                     if ( isset( $thParams['colspan'] ) )
02353                     {
02354                         $cellData[$columnCount. ',' .$rowCount]['size'] = (int)$thParams['colspan'];
02355                     }
02356                     if ( isset( $thParams['align'] ) )
02357                     {
02358                         $cellData[$columnCount. ',' .$rowCount]['justification'] = $thParams['align'];
02359                     }
02360                     if ( isset( $thParams['width'] ) )
02361                     {
02362                         $cellData[$columnCount. ',' .$rowCount]['width'] = $thParams['width'];
02363                     }
02364                     continue;
02365                 }
02366                 else if ( strcmp( substr($text, $offSet+1, strlen( '/tr' ) ), '/tr' ) == 0 )
02367                 {
02368                     $rowCount++;
02369                     $columnCount = 0;
02370                     $offSet++;
02371                     $offSet += strlen( '/tr' );
02372                     continue;
02373                 }
02374                 else if ( strcmp( substr($text, $offSet+1, strlen( '/td' ) ), '/td' ) == 0 )
02375                 {
02376                     if ( $columnCount == 0 )
02377                     {
02378                         $tableData[$rowCount] = array();
02379                     }
02380                     $tableData[$rowCount][$columnCount] = $columnText;
02381                     $columnText = '';
02382                     $columnCount++;
02383                     $offSet++;
02384                     $offSet += strlen( '/td' );
02385                     continue;
02386                 }
02387                 else if ( strcmp( substr($text, $offSet+1, strlen( '/th' ) ), '/th' ) == 0 )
02388                 {
02389                     if ( $columnCount == 0 )
02390                     {
02391                         $tableData[$rowCount] = array();
02392                     }
02393                     $tableData[$rowCount][$columnCount] = $columnText;
02394                     $columnText = '';
02395                     $columnCount++;
02396                     $offSet++;
02397                     $offSet += strlen( '/th' );
02398                     continue;
02399                 }
02400             }
02401             $columnText .= $text[$offSet];
02402         }
02403         $this->addDocSpecFunction( 'ezTable', array( &$tableData, '', '', array_merge( array( 'cellData' => $cellData,
02404                                                                                              'showLines' => $showLines ),
02405                                                                                       $params ) ) );
02406     }
02407 
02408     /**
02409      * Function for extracting function name and parameters from text.
02410      *
02411      * \param text
02412      * \param offset
02413      * \param function name (reference)
02414      * \param parameters array (reference)
02415      *
02416      * \return end offset of function
02417      */
02418     function extractFunction( &$text, $offSet, &$functionName, &$parameters, $type='ezCall' )
02419     {
02420         $offSet++;
02421         $offSet += strlen( $type.':' );
02422         $funcEnd = strpos( $text, ':', $offSet );
02423         if ( $funcEnd === false || strpos( $text, '>', $offSet ) < $funcEnd )
02424         {
02425             $funcEnd = strpos( $text, '>', $offSet );
02426         }
02427         $functionName = substr( $text, $offSet, $funcEnd - $offSet );
02428 
02429         return eZPDFTable::extractParameters( $text, $funcEnd, $parameters );
02430     }
02431 
02432     /**
02433      * Function for extracting parameters from : separated key:value list callback functions
02434      *
02435      * \param text
02436      * \param offset
02437      * \param parameters array (reference)
02438      *
02439      * \return end offset of function
02440      */
02441     function extractParameters( &$text, $offSet, &$parameters, $skipFirstChar=false )
02442     {
02443         $endOffset = strpos( $text, '>', $offSet );
02444         if ( $endOffset === false )
02445         {
02446             $endOffset = strlen( $text );
02447         }
02448 
02449         if ( $skipFirstChar === false )
02450             $offSet++;
02451         while ( $offSet < $endOffset )
02452         {
02453             $nameEnd = strpos( $text, ':', $offSet );
02454             $valueEnd = strpos( $text, ':', $nameEnd+1 );
02455             if ( $valueEnd > $endOffset || $valueEnd === false )
02456             {
02457                 $valueEnd = $endOffset;
02458             }
02459             $paramName = substr( $text, $offSet, $nameEnd-$offSet);
02460             ++$nameEnd;
02461             $paramValue = substr( $text, $nameEnd, $valueEnd-$nameEnd );
02462             $parameters[$paramName] = $paramValue;
02463             $offSet = ++$valueEnd;
02464         }
02465 
02466         return $endOffset;
02467     }
02468 
02469     /**
02470       Loop through all document specification settings and print specified text
02471 
02472       \return new Y offset
02473     */
02474     function outputDocSpecification()
02475     {
02476         foreach( array_keys( $this->DocSpecification ) as $key )
02477         {
02478             $outputElement =& $this->DocSpecification[$key];
02479 
02480             $documentSpec =& $outputElement['docSpec'];
02481 
02482             if ( isset( $documentSpec['fontName'] ) )
02483             {
02484                 $this->selectFont( $documentSpec['fontName'] );
02485             }
02486 
02487             if ( isset( $documentSpec['fontSize'] ) )
02488             {
02489                 $size = $documentSpec['fontSize'];
02490             }
02491             else
02492             {
02493                 $size = $this->fontSize();
02494             }
02495 
02496             if ( isset( $documentSpec['cmyk'] ) )
02497             {
02498                 $this->setColor( $documentSpec['cmyk'] );
02499             }
02500 
02501             if ( isset( $outputElement['isFunction'] ) && $outputElement['isFunction'] === true )
02502             {
02503                 $return = call_user_func_array( array( &$this, $outputElement['functionName'] ), $outputElement['parameters'] );
02504             }
02505             else
02506             {
02507                 $return = Cezpdf::ezText( $outputElement['text'],
02508                                           $size,
02509                                           array( 'justification' => $documentSpec['justification'] ) );
02510             }
02511         }
02512         return $return;
02513     }
02514 
02515     /*!
02516      Insert text at specified position
02517     */
02518     function callTextBox( $params, $text )
02519     {
02520         $this->addDocSpecFunction( 'insertTextBox', array( $params, $text ) );
02521     }
02522 
02523     function insertTextBox( $params, $text )
02524     {
02525         $this->pushStack();
02526 
02527         $this->setYOffset( $params['y'] );
02528         $this->setXOffset( $params['x'] );
02529 
02530         $marginText = '<C:callSetMargin';
02531         $marginText .= ':left:' . ( $params['x'] );
02532         $marginText .= ':right:' . ( $this->ez['pageWidth'] - $params['width'] - $params['x'] );
02533         $marginText .= '>';
02534         $marginText .= '<ezCall:callText';
02535         $marginText .= ':size:' . ( isset( $params['size'] ) ? $params['size'] : $this->fontSize() );
02536         $marginText .= ':justification:' . ( isset( $params['align'] ) ? $params['align'] : 'left' );
02537         $marginText .= '>';
02538 
02539         $this->ezText( $marginText . $text . '</ezCall:callText>' );
02540 
02541         $this->popStack();
02542     }
02543 
02544     /*!
02545      Callback function for adding text frame.
02546     */
02547     function callTextFrame( $params, $text )
02548     {
02549         $this->addDocSpecFunction( 'insertTextFrame', array( $params, $text ) );
02550     }
02551 
02552     /*!
02553      Callback function for adding text frame.
02554     */
02555     function insertTextFrame( $params, $text )
02556     {
02557         $prevColor = $this->currentColour;
02558         $prevFontSize = $this->fontSize();
02559         $prevFont = $this->currentFont();
02560 
02561         if ( isset( $params['fontSize'] ) )
02562         {
02563             $this->setFontSize( $params['fontSize'] );
02564         }
02565 
02566         if ( isset( $params['fontName'] ) )
02567         {
02568             $this->selectFont( $params['fontName'] );
02569         }
02570 
02571         $cmykKeys = array( 'c', 'm', 'y', 'k' );
02572         if ( isset( $params ['frameCMYK'] ) )
02573         {
02574             $params['frameCMYK'] = explode( ',', $params['frameCMYK'] );
02575             foreach ( $cmykKeys as $oldKey => $newKey )
02576             {
02577                 $params['frameCMYK'][$newKey] = $params['frameCMYK'][$oldKey];
02578                 unset( $params['frameCMYK'][$oldKey] );
02579             }
02580         }
02581         if ( isset( $params['textCMYK'] ) )
02582         {
02583             $params['textCMYK'] = explode( ',', $params['textCMYK'] );
02584             foreach ( $cmykKeys as $oldKey => $newKey )
02585             {
02586                 $params['textCMYK'][$newKey] = $params['textCMYK'][$oldKey];
02587                 unset( $params['textCMYK'][$oldKey] );
02588             }
02589         }
02590 
02591         $padding = 0;
02592         if ( isset( $params['padding'] ) )
02593         {
02594             $padding = $params['padding'];
02595         }
02596 
02597         $leftPadding = $padding;
02598         $rightPadding = $padding;
02599         $topPadding = $padding;
02600         $bottomPadding = $padding;
02601 
02602         if ( isset( $params['leftPadding'] ) )
02603         {
02604             $leftPadding = $params['leftPadding'];
02605         }
02606         if ( isset( $params['rightPadding'] ) )
02607         {
02608             $rightPadding = $params['rightPadding'];
02609         }
02610         if ( isset( $params['topPadding'] ) )
02611         {
02612             $topPadding = $params['topPadding'];
02613         }
02614         if ( isset( $params['bottomPadding'] ) )
02615         {
02616             $bottomPadding = $params['bottomPadding'];
02617         }
02618 
02619         $yOffset = $this->yOffset();
02620         $xOffset = $this->xOffset();
02621 
02622         $fontHeight = $this->getFontHeight( $this->ez['fontSize'] );
02623         $fontDecender = $this->getFontDecender( $this->ez['fontSize'] );
02624         $textWidth = $this->getTextWidth( $this->ez['fontSize'], $text );
02625 
02626         $totalHeight = $fontHeight + $topPadding;
02627         $totalWidth = $textWidth + $leftPadding + $rightPadding;
02628 
02629         if ( $rightPadding == -1 )
02630         {
02631             $totalWidth = $leftPadding + $this->ez['pageWidth'] - $xOffset + 10;
02632         }
02633 
02634         if ( isset( $params['frameCMYK'] ) )
02635         {
02636             $this->setColor( $params['frameCMYK'] );
02637         }
02638         $this->filledRectangle( $xOffset - $leftPadding,
02639                                 $yOffset - $bottomPadding,
02640                                 $totalWidth,
02641                                 $totalHeight );
02642 
02643         if ( isset( $params['roundEnds'] ) )
02644         {
02645             if ( $rightPadding != -1 )
02646             {
02647                 $this->filledEllipse( $xOffset + $textWidth + $rightPadding, $yOffset - $bottomPadding + ( $totalHeight / 2 ), $totalHeight / 2 );
02648             }
02649             if ( $leftPadding != -1 )
02650             {
02651                 $this->filledEllipse( $xOffset - $leftPadding, $yOffset - $bottomPadding + ( $totalHeight / 2 ), $totalHeight / 2 );
02652             }
02653         }
02654 
02655         if ( isset( $params['textCMYK'] ) )
02656         {
02657             $this->setColor( $params['textCMYK'] );
02658         }
02659         else
02660         {
02661             $this->setColor( $prevColor );
02662         }
02663         $this->addText( $xOffset, $yOffset, $this->fontSize(), $text );
02664 
02665         $this->setColor( $prevColor );
02666         $this->setFontSize( $prevFontSize );
02667         $this->selectFont( $prevFont );
02668     }
02669 
02670     /**
02671      * Callback function for adding text
02672      */
02673     function callText( $params )
02674     {
02675         $options = array();
02676 
02677         if ( isset( $params['font'] ) )
02678         {
02679             $options['fontName'] = 'lib/ezpdf/classes/fonts/'. $params['font'];
02680         }
02681 
02682         if ( isset( $params['size'] ) )
02683         {
02684             $options['fontSize'] = $params['size'];
02685         }
02686 
02687         if ( isset( $params['justification'] ) )
02688         {
02689             $options['justification'] = $params['justification'];
02690         }
02691 
02692         if ( isset( $params['cmyk'] ) )
02693         {
02694             $keyArray = array ( 'c', 'm', 'y', 'k' );
02695             $options['cmyk'] = array();
02696             $params['cmyk'] = explode( ',', $params['cmyk'] );
02697             foreach ( array_keys( $params['cmyk'] ) as $key )
02698             {
02699                 $options['cmyk'][$keyArray[$key]] = $params['cmyk'][$key];
02700             }
02701         }
02702 
02703         $this->addToPreStack( $options );
02704 
02705         return '';
02706     }
02707 
02708     /*!
02709      * Add and build Stack for function calls and document specification Stack
02710 
02711       \param countinues text, set to false to insert independent frames. DEfault true
02712     */
02713     function pushStack( $continous = true)
02714     {
02715         $docSpecArray = array( 'DocSpec' => $this->DocSpecification,
02716                                'PreStack' => $this->PreStack,
02717                                'LeftMarginArray' => $this->LeftMarginArray,
02718                                'RightMarginArray' => $this->RightMarginArray,
02719                                'LeftMargin' => $this->ez['leftMargin'],
02720                                'RightMargin' => $this->ez['rightMargin'],
02721                                'TopMargin' => $this->ez['topMargin'],
02722                                'BottomMargin' => $this->ez['bottomMargin'],
02723                                'LineSpace' => $this->ez['lineSpace'],
02724                                'Continous' => $continous,
02725                                'FontSize' => $this->fontSize(),
02726                                'Justification' => $this->justification() );
02727         if ( $continous )
02728         {
02729             $docSpecArray['YPos'] = $this->yOffset();
02730             $docSpecArray['XPos'] = $this->xOffset();
02731         }
02732 
02733         $this->DocSpecStack[] = $docSpecArray;
02734 
02735         $this->PreStack = array( array( 'justification' => $this->justification(),
02736                                         'fontSize' => $this->fontSize(),
02737                                         'fontName' => 'lib/ezpdf/classes/fonts/Helvetica',
02738                                         'cmyk' => eZMath:: rgbToCMYK2( 0, 0, 0 ) ) );
02739         $this->DocSpecification = array();
02740     }
02741 
02742     /*!
02743      Pop Specification stack.
02744     */
02745     function popStack()
02746     {
02747         $stackArray = array_pop( $this->DocSpecStack );
02748         $this->DocSpecification = $stackArray['DocSpec'];
02749         $this->PreStack = $stackArray['PreStack'];
02750         $this->LeftMarginArray = $stackArray['LeftMarginArray'];
02751         $this->RightMarginArray = $stackArray['RightMarginArray'];
02752         $this->ez['leftMargin'] = $stackArray['LeftMargin'];
02753         $this->ez['rightMargin'] = $stackArray['RightMargin'];
02754         $this->ez['topMargin'] = $stackArray['TopMargin'];
02755         $this->ez['bottomMargin'] = $stackArray['BottomMargin'];
02756         $this->ez['lineSpace'] = $stackArray['LineSpace'];
02757         $this->setFontSize( $stackArray['FontSize'] );
02758         $this->setJustification( $stackArray['justification'] );
02759 
02760         if ( $stackArray['continous'] )
02761         {
02762             $this->setYOffset( $stackArray['YPos'] );
02763             $this->setXOffset( $stackArray['XPos'] );
02764         }
02765     }
02766 
02767     /**
02768      * Function for adding text to doc specification
02769      *
02770      * param - text to add
02771      */
02772     function addDocSpecification( $text )
02773     {
02774         $docSpec = array_pop( $this->PreStack );
02775         $this->DocSpecification[] = array ( 'docSpec' => $docSpec,
02776                                             'text' => $text );
02777         $this->PreStack[] = $docSpec;
02778     }
02779 
02780     /**
02781      * Function for adding function to doc specification
02782      *
02783      * param - text to add
02784      */
02785     function addDocSpecFunction( $functionName, $parameters )
02786     {
02787         $docSpec = array_pop( $this->PreStack );
02788         $this->DocSpecification[] = array ( 'docSpec' => $docSpec,
02789                                             'isFunction' => true,
02790                                             'functionName' => $functionName,
02791                                             'parameters' => $parameters );
02792         $this->PreStack[] = $docSpec;
02793     }
02794 
02795 
02796     /**
02797      * function for adding font specification to PreStack array
02798      *
02799      * Possible $options setting:
02800      * - justification
02801      * - fontSize
02802      * - fontName
02803      */
02804     function addToPreStack( $options=array() )
02805     {
02806         $currentElement = array();
02807 
02808         $prevElement = array_pop( $this->PreStack );
02809 
02810         if ( isset( $options['justification'] ) )
02811         {
02812             $currentElement['justification'] = $options['justification'];
02813         }
02814         else
02815         {
02816             $currentElement['justification'] = $prevElement['justification'];
02817         }
02818 
02819         if ( isset( $options['fontSize'] ) )
02820         {
02821             $currentElement['fontSize'] = $options['fontSize'];
02822         }
02823         else
02824         {
02825             $currentElement['fontSize'] = $prevElement['fontSize'];
02826         }
02827 
02828         if ( isset( $options['fontName'] ) )
02829         {
02830             $currentElement['fontName'] = $options['fontName'];
02831         }
02832         else
02833         {
02834             $currentElement['fontName'] = $prevElement['fontName'];
02835         }
02836 
02837         if ( isset( $options['cmyk'] ) )
02838         {
02839             $currentElement['cmyk'] = $options['cmyk'];
02840         }
02841         else
02842         {
02843             $currentElement['cmyk'] = $prevElement['cmyk'];
02844         }
02845 
02846         $this->PreStack[] = $prevElement;
02847         $this->PreStack[] = $currentElement;
02848     }
02849 
02850     /*!
02851       Draw line related to a frame.
02852     */
02853     function callFrameLine( $info )
02854     {
02855         $parameters = array();
02856         eZPDFTable::extractParameters( $info['p'], 0, $parameters, true );
02857 
02858         $location = $parameters['location'];
02859         $yOffset = $parameters['margin'];
02860         if ( $location == 'frame_header' )
02861         {
02862             $yOffset = $this->ez['pageHeight'] - $parameters['margin'];
02863         }
02864 
02865         $rightMargin = $this->rightMargin( $yOffset );
02866         if ( isset( $parameters['rightMargin'] ) )
02867         {
02868             $rightMargin = $parameters['rightMargin'];
02869         }
02870 
02871         $leftMargin = $this->leftMargin( $yOffset );
02872         if ( isset( $parameters['leftMargin'] ) )
02873         {
02874             $leftMargin = $parameters['leftMargin'];
02875         }
02876 
02877         $this->setLineStyle( $parameters['thickness'] );
02878 
02879         reset( $this->ezPages );
02880         foreach ( $this->ezPages as $pageNum => $pageID )
02881         {
02882             if( $pageNum < $parameters['pageOffset'] )
02883                 continue;
02884 
02885             if ( $parameters['page'] == 'odd' &&
02886                  $pageNum % 2 == 0 )
02887                 continue;
02888 
02889             if ( $parameters['page'] == 'even' &&
02890                  $pageNum % 2 == 1 )
02891                 continue;
02892 
02893             $this->reopenObject( $pageID );
02894             $this->line( $leftMargin, $yOffset, $this->ez['pageWidth'] - $rightMargin, $yOffset );
02895             $this->closeObject();
02896         }
02897 
02898         $this->setLineStyle( 1 );
02899     }
02900 
02901     /*!
02902      Start page counter in PDF document
02903 
02904      \param counter identifier
02905     */
02906     function callStartPageCounter( $info )
02907     {
02908         $params = array();
02909 
02910         eZPDFTable::extractParameters( $info['p'], 0, $params, true );
02911 
02912         $identifier = 'main';
02913         if ( isset( $params['identifier'] ) )
02914         {
02915             $identifier = $params['identifier'];
02916         }
02917 
02918         if ( isset( $params['start'] ) )
02919         {
02920             $this->PageCounter[$identifier] = array();
02921             $this->PageCounter[$identifier]['start'] = $this->ezGetCurrentPageNumber();
02922         }
02923         if ( isset( $params['stop'] ) )
02924         {
02925             $this->PageCounter[$identifier]['stop'] = $this->ezGetCurrentPageNumber();
02926         }
02927     }
02928 
02929     /*!
02930 
02931      \param real page number
02932      \param pagecounter identifier
02933     */
02934     function ezWhatPageNumber( $pageNum, $identifier = false )
02935     {
02936         if ( $identifier === false )
02937         {
02938             foreach ( array_keys( $this->PageCounter ) as $identifier )
02939             {
02940                 if ( isset( $this->PageCounter[$identifier]['start'] ) &&
02941                      $this->PageCounter[$identifier]['start'] <= $pageNum &&
02942                      ( !isset( $this->PageCounter[$identifier]['stop'] ) || $this->PageCounter[$identifier]['stop'] >= $pageNum ) )
02943                     return $pageNum - $this->PageCounter[$identifier]['start'] + 1;
02944             }
02945         }
02946         else
02947             return $pageNum - $this->PageCounter[$identifier]['start'] + 1;
02948     }
02949 
02950     /*!
02951       \private
02952 
02953       Get header label of content on specified page and specified level
02954 
02955       \param current page
02956       \param level
02957     */
02958     function headerLabel( $page, $level )
02959     {
02960         $headerLabel = '';
02961         foreach ( array_keys( $this->TOC ) as $key )
02962         {
02963             $header = $this->TOC[$key];
02964             if ( $header['pageNumber'] > $page )
02965                 return $headerLabel;
02966 
02967             if ( $header['level'] == $level )
02968             {
02969                 $headerLabel = $header['label'];
02970             }
02971             else if ( $header['level'] < $level )
02972             {
02973                 $headerLabel = '';
02974             }
02975         }
02976 
02977         return $headerLabel;
02978     }
02979 
02980     /*!
02981       \private
02982 
02983       Get header label of content on specified page and specified level
02984 
02985       \param current page
02986       \param level
02987     */
02988     function headerIndex( $page, $level )
02989     {
02990         $headerIndex = 0;
02991         foreach ( array_keys( $this->TOC ) as $key )
02992         {
02993             $header = $this->TOC[$key];
02994             if ( $header['pageNumber'] > $page )
02995                 return ( $headerIndex != 0 ? $headerIndex : '' );
02996 
02997             if ( $header['level'] == $level )
02998             {
02999                 $headerIndex++;
03000             }
03001             else if ( $header['level'] < $level )
03002             {
03003                 $headerLabel = 0;
03004             }
03005         }
03006 
03007         return ( $headerIndex != 0 ? $headerIndex : '' );
03008     }
03009 
03010     public $TOC; // Table of content array
03011     public $KeywordArray; // keyword array
03012     public $PageCounter;
03013 
03014     public $FrontpageID; // Variable used to store reference to frontpage
03015 
03016     public $ezFrame; // array containing frame definitions
03017 
03018     /* Stack and array used for preprocessing document */
03019     public $PreStack;
03020     public $DocSpecification;
03021 
03022     /* Stack array for recursive ezText calls */
03023     public $DocSpecStack = array();
03024 }
03025 
03026 
03027 ?>