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