Source for file class.ezpdf.php
Documentation is available at class.ezpdf.php
include_once('phpDocumentor/Converters/PDF/default/class.pdf.php');
* This class will take the basic interaction facilities of the Cpdf class
* and make more useful functions so that the user does not have to
* know all the ins and outs of pdf presentation to produce something pretty.
* there is no warranty, implied or otherwise with this software.
* @version 009 (versioning is linked to class.pdf.php)
* released under a public domain licence.
* @author Wayne Munro, R&OS Ltd, {@link http://www.ros.co.nz/pdf}
//==============================================================================
// this class will take the basic interaction facilities of the Cpdf class
// and make more useful functions so that the user does not have to
// know all the ins and outs of pdf presentation to produce something pretty.
// there is no warranty, implied or otherwise with this software.
// version 009 (versioning is linked to class.pdf.php)
// released under a public domain licence.
// Wayne Munro, R&OS Ltd, http://www.ros.co.nz/pdf
//==============================================================================
var $ez= array('fontSize'=> 10); // used for storing most of the page configuration parameters
var $y; // this is the current vertical positon on the page of the writing point, very important
var $ezPages= array(); // keep an array of the ids of the pages, making it easy to go back and add page numbers etc.
// ------------------------------------------------------------------------------
function Cezpdf($paper= 'a4',$orientation= 'portrait'){
// Assuming that people don't want to specify the paper size using the absolute coordinates
// allow a couple of options:
// orientation can be 'portrait' or 'landscape'
// or, to actually set the coordinates, then pass an array in as the first parameter.
// the defaults are as shown.
// -------------------------
// Added new page formats (45 standard ISO paper formats and 4 american common formats)
// paper cordinates are calculated in this way: (inches * 72) where 1 inch = 2.54 cm
// Now you may also pass a 2 values array containing the page width and height in centimeters
// -------------------------
case '4A0': {$size = array(0,0,4767.87,6740.79); break;}
case '2A0': {$size = array(0,0,3370.39,4767.87); break;}
case 'A0': {$size = array(0,0,2383.94,3370.39); break;}
case 'A1': {$size = array(0,0,1683.78,2383.94); break;}
case 'A2': {$size = array(0,0,1190.55,1683.78); break;}
case 'A3': {$size = array(0,0,841.89,1190.55); break;}
case 'A4': default: {$size = array(0,0,595.28,841.89); break;}
case 'A5': {$size = array(0,0,419.53,595.28); break;}
case 'A6': {$size = array(0,0,297.64,419.53); break;}
case 'A7': {$size = array(0,0,209.76,297.64); break;}
case 'A8': {$size = array(0,0,147.40,209.76); break;}
case 'A9': {$size = array(0,0,104.88,147.40); break;}
case 'A10': {$size = array(0,0,73.70,104.88); break;}
case 'B0': {$size = array(0,0,2834.65,4008.19); break;}
case 'B1': {$size = array(0,0,2004.09,2834.65); break;}
case 'B2': {$size = array(0,0,1417.32,2004.09); break;}
case 'B3': {$size = array(0,0,1000.63,1417.32); break;}
case 'B4': {$size = array(0,0,708.66,1000.63); break;}
case 'B5': {$size = array(0,0,498.90,708.66); break;}
case 'B6': {$size = array(0,0,354.33,498.90); break;}
case 'B7': {$size = array(0,0,249.45,354.33); break;}
case 'B8': {$size = array(0,0,175.75,249.45); break;}
case 'B9': {$size = array(0,0,124.72,175.75); break;}
case 'B10': {$size = array(0,0,87.87,124.72); break;}
case 'C0': {$size = array(0,0,2599.37,3676.54); break;}
case 'C1': {$size = array(0,0,1836.85,2599.37); break;}
case 'C2': {$size = array(0,0,1298.27,1836.85); break;}
case 'C3': {$size = array(0,0,918.43,1298.27); break;}
case 'C4': {$size = array(0,0,649.13,918.43); break;}
case 'C5': {$size = array(0,0,459.21,649.13); break;}
case 'C6': {$size = array(0,0,323.15,459.21); break;}
case 'C7': {$size = array(0,0,229.61,323.15); break;}
case 'C8': {$size = array(0,0,161.57,229.61); break;}
case 'C9': {$size = array(0,0,113.39,161.57); break;}
case 'C10': {$size = array(0,0,79.37,113.39); break;}
case 'RA0': {$size = array(0,0,2437.80,3458.27); break;}
case 'RA1': {$size = array(0,0,1729.13,2437.80); break;}
case 'RA2': {$size = array(0,0,1218.90,1729.13); break;}
case 'RA3': {$size = array(0,0,864.57,1218.90); break;}
case 'RA4': {$size = array(0,0,609.45,864.57); break;}
case 'SRA0': {$size = array(0,0,2551.18,3628.35); break;}
case 'SRA1': {$size = array(0,0,1814.17,2551.18); break;}
case 'SRA2': {$size = array(0,0,1275.59,1814.17); break;}
case 'SRA3': {$size = array(0,0,907.09,1275.59); break;}
case 'SRA4': {$size = array(0,0,637.80,907.09); break;}
case 'LETTER': {$size = array(0,0,612.00,792.00); break;}
case 'LEGAL': {$size = array(0,0,612.00,1008.00); break;}
case 'EXECUTIVE': {$size = array(0,0,521.86,756.00); break;}
case 'FOLIO': {$size = array(0,0,612.00,936.00); break;}
// then an array was sent it to set the size
else { //size in centimeters has been passed
$size[2] = ( $paper[0] / 2.54 ) * 72;
$size[3] = ( $paper[1] / 2.54 ) * 72;
$this->ez['pageWidth']= $size[2];
$this->ez['pageHeight']= $size[3];
// also set the margins to some reasonable defaults
$this->ez['topMargin']= 30;
$this->ez['bottomMargin']= 30;
$this->ez['leftMargin']= 30;
$this->ez['rightMargin']= 30;
// set the current writing position to the top of the first page
$this->y = $this->ez['pageHeight']- $this->ez['topMargin'];
// and get the ID of the page that was created during the instancing process.
// ------------------------------------------------------------------------------
// Set Margins in centimeters
$top = ( $top / 2.54 ) * 72;
$bottom = ( $bottom / 2.54 ) * 72;
$left = ( $left / 2.54 ) * 72;
$right = ( $right / 2.54 ) * 72;
// ------------------------------------------------------------------------------
// start from the current y-position, make the set number of columne
if (isset ($this->ez['columns']) && $this->ez['columns']== 1){
// if we are already in a column mode then just return.
$def= array('gap'=> 10,'num'=> 2);
if (!isset ($options[$k])){
$this->ez['columns']= array('on'=> 1,'colNum'=> 1);
// store the current margins
$this->ez['columns']['margins']= array(
,$this->ez['rightMargin']
,$this->ez['bottomMargin']
// and store the settings for the columns
$this->ez['columns']['options']= $options;
// then reset the margins to suit the new columns
// safe enough to assume the first column here, but start from the current y-position
$this->ez['topMargin']= $this->ez['pageHeight']- $this->y;
$width= ($this->ez['pageWidth']- $this->ez['leftMargin']- $this->ez['rightMargin']- ($options['num']- 1)* $options['gap'])/ $options['num'];
$this->ez['columns']['width']= $width;
$this->ez['rightMargin']= $this->ez['pageWidth']- $this->ez['leftMargin']- $width;
// ------------------------------------------------------------------------------
if (isset ($this->ez['columns']) && $this->ez['columns']['on']== 1){
$this->ez['columns']['on']= 0;
$this->ez['leftMargin']= $this->ez['columns']['margins'][0];
$this->ez['rightMargin']= $this->ez['columns']['margins'][1];
$this->ez['topMargin']= $this->ez['columns']['margins'][2];
$this->ez['bottomMargin']= $this->ez['columns']['margins'][3];
// ------------------------------------------------------------------------------
// puts the document into insert mode. new pages are inserted until this is re-called with status=0
// by default pages wil be inserted at the start of the document
if (isset ($this->ezPages[$pageNum])){
$this->ez['insertMode']= 1;
$this->ez['insertOptions']= array('id'=> $this->ezPages[$pageNum],'pos'=> $pos);
$this->ez['insertMode']= 0;
// ------------------------------------------------------------------------------
if (isset ($this->ez['columns']) && $this->ez['columns']['on']== 1){
// check if this is just going to a new column
// increment the column number
$this->ez['columns']['colNum']++ ;
//echo $this->ez['columns']['colNum'].'<br>';
if ($this->ez['columns']['colNum'] <= $this->ez['columns']['options']['num']){
// then just reset to the top of the next column
$this->ez['columns']['colNum']= 1;
$this->ez['topMargin']= $this->ez['columns']['margins'][2];
$width = $this->ez['columns']['width'];
$this->ez['leftMargin']= $this->ez['columns']['margins'][0]+ ($this->ez['columns']['colNum']- 1)* ($this->ez['columns']['options']['gap']+ $width);
$this->ez['rightMargin']= $this->ez['pageWidth']- $this->ez['leftMargin']- $width;
//echo 'left='.$this->ez['leftMargin'].' right='.$this->ez['rightMargin'].'<br>';
// make a new page, setting the writing point back to the top
$this->y = $this->ez['pageHeight']- $this->ez['topMargin'];
// make the new page with a call to the basic class.
if (isset ($this->ez['insertMode']) && $this->ez['insertMode']== 1){
// then manipulate the insert options so that inserted pages follow each other
$this->ez['insertOptions']['id']= $id;
$this->ez['insertOptions']['pos']= 'after';
$this->y = $this->ez['pageHeight']- $this->ez['topMargin'];
// ------------------------------------------------------------------------------
// sets the margins to new values
$this->ez['topMargin']= $top;
$this->ez['bottomMargin']= $bottom;
$this->ez['leftMargin']= $left;
$this->ez['rightMargin']= $right;
// check to see if this means that the current writing position is outside the
if ($this->y > $this->ez['pageHeight']- $top){
$this->y = $this->ez['pageHeight']- $top;
if ( $this->y < $bottom){
// ------------------------------------------------------------------------------
// return the strict numbering (1,2,3,4..) number of the current page
// ------------------------------------------------------------------------------
function ezStartPageNumbers($x,$y,$size,$pos= 'left',$pattern= '{PAGENUM} of {TOTALPAGENUM}',$num= ''){
// put page numbers on the pages from here.
// place then on the 'pos' side of the coordinates (x,y).
// pos can be 'left' or 'right'
// use the given 'pattern' for display, where (PAGENUM} and {TOTALPAGENUM} are replaced
// if $num is set, then make the first page this number, the number of total pages will
// be adjusted to account for this.
// Adjust this function so that each time you 'start' page numbers then you effectively start a different batch
// return the number of the batch, so that they can be stopped in a different order if required.
if (!$pattern || !strlen($pattern)){
$pattern= '{PAGENUM} of {TOTALPAGENUM}';
if (!isset ($this->ez['pageNumbering'])){
$this->ez['pageNumbering']= array();
$i = count($this->ez['pageNumbering']);
$this->ez['pageNumbering'][$i][$this->ezPageCount]= array('x'=> $x,'y'=> $y,'pos'=> $pos,'pattern'=> $pattern,'num'=> $num,'size'=> $size);
// ------------------------------------------------------------------------------
// given a particular generic page number (ie, document numbered sequentially from beginning),
// return the page number under a particular page numbering scheme ($i)
if (!isset ($this->ez['pageNumbering']))
$this->addMessage('WARNING: page numbering called for and wasn\'t started with ezStartPageNumbers');
foreach($this->ez['pageNumbering'][$i] as $k=> $v){
$num= $pageNum- $startNum+ $start;
// ------------------------------------------------------------------------------
// if stopTotal=1 then the totalling of pages for this number will stop too
// if $next=1, then do this page, but not the next, else do not do this page either
// if $i is set, then stop that particular pagenumbering sequence.
if (!isset ($this->ez['pageNumbering'])){
$this->ez['pageNumbering']= array();
// then this has only just been started, this will over-write the start, and nothing will appear
// add a special command to the start block, telling it to stop as well
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// this will go through the pageNumbering array and add the page numbers are required
if (isset ($this->ez['pageNumbering'])){
$tmp1= $this->ez['pageNumbering'];
foreach($tmp1 as $i=> $tmp){
// do each of the page numbering systems
// firstly, find the total pages for this one
$totalPages = $totalPages1;
foreach ($this->ezPages as $pageNum=> $id){
if (isset ($tmp[$pageNum])){
// then this must be starting page numbers
$info['dnum']= $info['num']- $pageNum;
// also check for the special case of the numbering stopping and starting on the same page
if (isset ($info['stopn']) || isset ($info['stoptn']) ){
} else if ($tmp[$pageNum]== 'stop' || $tmp[$pageNum]== 'stopt'){
// then we are stopping page numbers
} else if ($status== 1 && ($tmp[$pageNum]== 'stoptn' || $tmp[$pageNum]== 'stopn')){
// then we are stopping page numbers
// then add the page numbering to this page
$num= $pageNum+ $info['dnum'];
$total = $totalPages+ $num- $pageNum;
$this->addText($info['x'],$info['y'],$info['size'],$pat);
$this->addText($info['x']- $w,$info['y'],$info['size'],$pat);
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
return $this->output($options);
// ------------------------------------------------------------------------------
// used to change the vertical position of the writing point.
if ( $this->y < $this->ez['bottomMargin']){
// ------------------------------------------------------------------------------
// used to change the vertical position of the writing point.
// changes up by a positive increment, so enter a negative number to go
// if $mod is set to 'makeSpace' and a new page is forced, then the pointed will be moved
// down on the new page, this will allow space to be reserved for graphics etc.
if ( $this->y < $this->ez['bottomMargin']){
// ------------------------------------------------------------------------------
function ezPrvtTableDrawLines($pos,$gap,$x0,$x1,$y0,$y1,$y2,$col,$inner,$outer,$opt= 1){
if ($cnt== 1 || $cnt== $n){
$this->line($x- $gap/ 2,$y0,$x- $gap/ 2,$y2);
$this->line($x0- $gap/ 2- $outer/ 2,$y0,$x1- $gap/ 2+ $outer/ 2,$y0);
// only do the second line if it is different to the first, AND each row does not have
$this->line($x0- $gap/ 2,$y1,$x1- $gap/ 2,$y1);
$this->line($x0- $gap/ 2- $outer/ 2,$y2,$x1- $gap/ 2+ $outer/ 2,$y2);
// ------------------------------------------------------------------------------
// uses ezText to add the text, and returns the height taken by the largest heading
// this page will move the headings to a new page if they will not fit completely on this one
// transaction support will be used to implement this
if (isset ($optionsAll['cols'])){
$options = $optionsAll['cols'];
// $y is the position at which the top of the table should start, so the base
// of the first text, is $y-$height-$gap-$decender, but ezText starts by dropping $height
// the return from this function is the total cell height, including gaps, and $y is adjusted
// to be the postion of the bottom line
foreach($cols as $colName=> $colHeading){
if (isset ($options[$colName]) && isset ($options[$colName]['justification'])){
$justification = $options[$colName]['justification'];
$this->ezText($colHeading,$size,array('aleft'=> $pos[$colName],'aright'=> ($maxWidth[$colName]+ $pos[$colName]),'justification'=> $justification));
$y = $y - $mx - $gap + $decender;
// $y -= $mx-$gap+$decender;
// now, if this has moved to a new page, then abort the transaction, move to a new page, and put it there
// do not check on the second time around, to avoid an infinite loop
$y = $this->y - $gap- $decender;
return $mx+ $gap* 2- $decender;
// ------------------------------------------------------------------------------
// will calculate the maximum width, taking into account that the text may be broken
foreach ($lines as $line){
// ------------------------------------------------------------------------------
function ezTable(&$data,$cols= '',$title= '',$options= ''){
// add a table of information to the pdf document
// $data is a two dimensional array
// $cols (optional) is an associative array, the keys are the names of the columns from $data
// to be presented (and in that order), the values are the titles to be given to the columns
// $title (optional) is the title to be put on the top of the table
// $options is an associative array which can contain:
// 'showLines'=> 0,1,2, default is 1 (show outside and top lines only), 2=> lines on each row
// 'showHeadings' => 0 or 1
// 'shaded'=> 0,1,2,3 default is 1 (1->alternate lines are shaded, 0->no shading, 2-> both shaded, second uses shadeCol2)
// 'shadeCol' => (r,g,b) array, defining the colour of the shading, default is (0.8,0.8,0.8)
// 'shadeCol2' => (r,g,b) array, defining the colour of the shading of the other blocks, default is (0.7,0.7,0.7)
// 'textCol' => (r,g,b) array, text colour
// 'rowGap' => 2 , the space added at the top and bottom of each row, between the text and the lines
// 'colGap' => 5 , the space on the left and right sides of each cell
// 'lineCol' => (r,g,b) array, defining the colour of the lines, default, black.
// 'xPos' => 'left','right','center','centre',or coordinate, reference coordinate in the x-direction
// 'xOrientation' => 'left','right','center','centre', position of the table w.r.t 'xPos'
// 'width'=> <number> which will specify the width of the table, if it turns out to not be this
// wide, then it will stretch the table to fit, if it is wider then each cell will be made
// proportionalty smaller, and the content may have to wrap.
// 'maxWidth'=> <number> similar to 'width', but will only make table smaller than it wants to be
// 'options' => array(<colname>=>array('justification'=>'left','width'=>100,'link'=>linkDataName),<colname>=>....)
// allow the setting of other paramaters for the individual columns
// 'minRowSpace'=> the minimum space between the bottom of each row and the bottom margin, in which a new row will be started
// if it is less, then a new page would be started, default=-100
// 'innerLineThickness'=>1
// 'outerLineThickness'=>1
// 'splitRows'=>0, 0 or 1, whether or not to allow the rows to be split across page boundaries
// 'protectRows'=>number, the number of rows to hold with the heading on page, ie, if there less than this number of
// rows on the page, then move the whole lot onto the next page, default=1
// note that the user will have had to make a font selection already or this will not
// produce a valid pdf file.
// take the columns from the first row of the data set
'shaded'=> 1,'showLines'=> 1,'shadeCol'=> array(0.8,0.8,0.8),'shadeCol2'=> array(0.7,0.7,0.7),'fontSize'=> 10,'titleFontSize'=> 12
,'titleGap'=> 5,'lineCol'=> array(0,0,0),'gap'=> 5,'xPos'=> 'centre','xOrientation'=> 'centre'
,'showHeadings'=> 1,'textCol'=> array(0,0,0),'width'=> 0,'maxWidth'=> 0,'cols'=> array(),'minRowSpace'=>- 100,'rowGap'=> 2,'colGap'=> 5
,'innerLineThickness'=> 1,'outerLineThickness'=> 1,'splitRows'=> 0,'protectRows'=> 1
foreach($defaults as $key=> $value){
if (!isset ($options[$key]) || !is_array($options[$key])){
if (!isset ($options[$key])){
$options['gap']= 2* $options['colGap'];
$middle = ($this->ez['pageWidth']- $this->ez['rightMargin'])/ 2+ ($this->ez['leftMargin'])/ 2;
// figure out the maximum widths of the text within each column
foreach($cols as $colName=> $colHeading){
// find the maximum cell widths based on the data
foreach($cols as $colName=> $colHeading){
if ($w > $maxWidth[$colName]){
// and the maximum widths to fit in the headings
foreach($cols as $colName=> $colTitle){
if ($w > $maxWidth[$colName]){
// calculate the start positions of each of the columns
foreach($maxWidth as $colName => $w){
// if the column width has been specified then set that here, also total the
// width avaliable for adjustment
if (isset ($options['cols'][$colName]) && isset ($options['cols'][$colName]['width']) && $options['cols'][$colName]['width']> 0){
$t= $t+ $options['cols'][$colName]['width'];
$maxWidth[$colName] = $options['cols'][$colName]['width']- $options['gap'];
$setWidth += $options['cols'][$colName]['width'];
$t= $t+ $w+ $options['gap'];
$setWidth += $options['gap'];
// if maxWidth is specified, and the table is too wide, and the width has not been set,
if ($options['width']== 0 && $options['maxWidth'] && ($t- $x)> $options['maxWidth']){
// then need to make this one smaller
$options['width']= $options['maxWidth'];
if ($options['width'] && $adjustmentWidth> 0 && $setWidth< $options['width']){
// first find the current widths of the columns involved in this mystery
foreach($pos as $colName=> $p){
if (!isset ($options['cols'][$last]) || !isset ($options['cols'][$last]['width']) || $options['cols'][$last]['width']<= 0){
$cols0[$last]= $p- $xq - $options['gap'];
$presentWidth += ($p- $xq - $options['gap']);
// $cols0 contains the widths of all the columns which are not set
$neededWidth = $options['width']- $setWidth;
// if needed width is negative then add it equally to each column, else get more tricky
if ($presentWidth< $neededWidth){
foreach($cols0 as $colName=> $w){
$cols0[$colName]+= ($neededWidth- $presentWidth)/ count($cols0);
while ($presentWidth> $neededWidth && $cnt< 100){
$cnt++ ; // insurance policy
// find the widest columns, and the next to widest width
foreach($cols0 as $colName=> $w){
$aWidest= array($colName);
// then figure out what the width of the widest columns would have to be to take up all the slack
$newWidestWidth = $widest - ($presentWidth- $neededWidth)/ count($aWidest);
if ($newWidestWidth > $nWidest){
// then there is space to set them to this
foreach($aWidest as $colName){
$cols0[$colName] = $newWidestWidth;
$presentWidth= $neededWidth;
// there is not space, reduce the size of the widest ones down to the next size down, and we
foreach($aWidest as $colName){
$cols0[$colName] = $nWidest;
$presentWidth= $presentWidth- ($widest- $nWidest)* count($aWidest);
// $cols0 now contains the new widths of the constrained columns.
// now need to update the $pos and $maxWidth arrays
foreach($pos as $colName=> $p){
if (!isset ($options['cols'][$colName]) || !isset ($options['cols'][$colName]['width']) || $options['cols'][$colName]['width']<= 0){
if (isset ($cols0[$colName])){
$xq += $cols0[$colName] + $options['gap'];
$maxWidth[$colName]= $cols0[$colName];
if (isset ($cols1[$colName])){
// now adjust the table to the correct location across the page
switch ($options['xPos']){
$xref = $this->ez['leftMargin'];
$xref = $this->ez['pageWidth'] - $this->ez['rightMargin'];
$xref = $options['xPos'];
switch ($options['xOrientation']){
$baseLeftMargin = $this->ez['leftMargin'];
// ok, just about ready to make me a table
$this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2]);
$this->setStrokeColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2]);
// start a transaction which will be used to regress the table, if there are not enough rows protected
if ($options['protectRows']> 0){
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
// if the title is set, then do that
if ($this->y < $this->ez['bottomMargin']){
// margins may have changed on the newpage
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
$this->addText($middle- $w/ 2,$this->y,$options['titleFontSize'],$title);
$this->y -= $options['titleGap'];
// margins may have changed on the newpage
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
$y= $this->y; // to simplify the code a bit
if ($options['showHeadings']){
// this function will move the start of the table to a new page if it does not fit on this one
$headingHeight = $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
// open an object here so that the text can be put in over the shading
// the transaction support will be used to prevent rows being split
if ($options['splitRows']== 0){
if (isset ($this->ez['columns']) && $this->ez['columns']['on']== 1){
$columnStart = $this->ez['columns']['colNum'];
while(!$abortTable && $ok == 0){
while(!$abortTable && ($newPage || $newRow)){
if ($newPage || $y< $this->ez['bottomMargin'] || (isset ($options['minRowSpace']) && $y< ($this->ez['bottomMargin']+ $options['minRowSpace'])) ){
// check that enough rows are with the heading
if ($options['protectRows']> 0 && $movedOnce== 0 && $cnt<= $options['protectRows']){
// then we need to move the whole table onto the next page
$y2= $y- $mx+ 2* $height+ $decender- $newRow* $height;
if ($options['showLines']){
if (!$options['showHeadings']){
$this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);
// and the margins may have changed, this is due to the possibility of the columns being turned on
// as the columns are managed by manipulating the margins
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
$this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2],1);
$y = $this->ez['pageHeight']- $this->ez['topMargin'];
if ($options['showHeadings']){
$this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);
// if these cells need to be split over a page, then $newPage will be set, and the remaining
// text will be placed in $leftOvers
foreach($cols as $colName=> $colTitle){
if (isset ($row[$colName])){
if (isset ($options['cols'][$colName]) && isset ($options['cols'][$colName]['link']) && strlen($options['cols'][$colName]['link'])){
$lines = explode("\n",$row[$colName]);
if (isset ($row[$options['cols'][$colName]['link']]) && strlen($row[$options['cols'][$colName]['link']])){
foreach($lines as $k=> $v){
$lines[$k]= '<c:alink:'. $row[$options['cols'][$colName]['link']]. '>'. $v. '</c:alink>';
$lines = explode("\n",$row[$colName]);
$this->y -= $options['rowGap'];
foreach ($lines as $line){
while (strlen($line) || $start){
$this->y= $this->y- $height;
if ($this->y < $this->ez['bottomMargin']){
$newPage= 1; // whether a new page is required for any of the columns
$colNewPage= 1; // whether a new page is required for this column
if (isset ($leftOvers[$colName])){
$leftOvers[$colName].= "\n". $line;
$leftOvers[$colName] = $line;
if (isset ($options['cols'][$colName]) && isset ($options['cols'][$colName]['justification']) ){
$just = $options['cols'][$colName]['justification'];
$line= $this->addTextWrap($pos[$colName],$this->y,$maxWidth[$colName],$options['fontSize'],$line,$just);
$dy= $y+ $height- $this->y+ $options['rowGap'];
if ($dy- $height* $newPage> $mx){
$mx= $dy- $height* $newPage;
// set $row to $leftOvers so that they will be processed onto the new page
// now add the shading underneath
if ($options['shaded'] && $cnt% 2== 0){
$this->setColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2],1);
$this->filledRectangle($x0- $options['gap']/ 2,$y+ $decender+ $height- $mx,$x1- $x0,$mx);
if ($options['shaded']== 2 && $cnt% 2== 1){
$this->setColor($options['shadeCol2'][0],$options['shadeCol2'][1],$options['shadeCol2'][2],1);
$this->filledRectangle($x0- $options['gap']/ 2,$y+ $decender+ $height- $mx,$x1- $x0,$mx);
if ($options['showLines']> 1){
// then draw a line on the top of each block
$this->setStrokeColor($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);
// $this->line($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx);
$this->line($x0- $options['gap']/ 2,$y+ $decender+ $height,$x1- $options['gap']/ 2,$y+ $decender+ $height);
// $this->reopenObject($textObjectId);
// checking row split over pages
if ($options['splitRows']== 0){
if ( ( ($this->ezPageCount != $pageStart) || (isset ($this->ez['columns']) && $this->ez['columns']['on']== 1 && $columnStart != $this->ez['columns']['colNum'] )) && $secondTurn== 0){
// then we need to go back and try that again !
$dm = $this->ez['leftMargin']- $baseLeftMargin;
foreach($basePos as $k=> $v){
$ok= 1; // don't go round the loop if splitting rows is allowed
} // end of while to check for row splitting
// only the outer transaction should be operational
} // end of foreach ($data as $row)
} // end of while ($abortTable)
// table has been put on the page, the rows guarded as required, commit.
if ($options['showLines']){
if (!$options['showHeadings']){
$this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);
// close the object for drawing the text on top
// ------------------------------------------------------------------------------
// this function will intially be used to implement underlining support, but could be used for a range of other
$search = array('<u>','<U>','</u>','</U>');
$replace = array('<c:uline>','<c:uline>','</c:uline>','</c:uline>');
// ------------------------------------------------------------------------------
function ezText($text,$size= 0,$options= array(),$test= 0){
// this will add a string of text to the document, starting at the current drawing
// it will wrap to keep within the margins, including optional offsets from the left
// and the right, if $size is not specified, then it will be the last one used, or
// the default value (12 I think).
// the text will go to the start of the next line when a return code "\n" is found.
// 'left'=> number, gap to leave from the left margin
// 'right'=> number, gap to leave from the right margin
// 'aleft'=> number, absolute left position (overrides 'left')
// 'aright'=> number, absolute right position (overrides 'right')
// 'justification' => 'left','right','center','centre','full'
// only set one of the next two items (leading overrides spacing)
// 'leading' => number, defines the total height taken by the line, independent of the font height.
// 'spacing' => a real number, though usually set to one of 1, 1.5, 2 (line spacing as used in word processing)
// if $test is set then this should just check if the text is going to flow onto a new page or not, returning true or false
// apply the filtering which will make the underlining function.
if (is_array($options) && isset ($options['aleft'])){
$left = $this->ez['leftMargin'] + ((is_array($options) && isset ($options['left']))? $options['left']: 0);
if (is_array($options) && isset ($options['aright'])){
$right= $options['aright'];
$right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset ($options['right']))? $options['right']: 0);
$size = $this->ez['fontSize'];
$this->ez['fontSize']= $size;
if (is_array($options) && isset ($options['justification'])){
$just = $options['justification'];
// modifications to give leading and spacing based on those given by Craig Heydenburg 1/1/02
if (is_array($options) && isset ($options['leading'])) { ## use leading instead of spacing
$height = $options['leading'];
} else if (is_array($options) && isset ($options['spacing'])) {
foreach ($lines as $line){
while (strlen($line) || $start){
$this->y= $this->y- $height;
if ($this->y < $this->ez['bottomMargin']){
// and then re-calc the left and right, in case they have changed due to columns
if (is_array($options) && isset ($options['aleft'])){
$left = $this->ez['leftMargin'] + ((is_array($options) && isset ($options['left']))? $options['left']: 0);
if (is_array($options) && isset ($options['aright'])){
$right= $options['aright'];
$right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset ($options['right']))? $options['right']: 0);
$line= $this->addTextWrap($left,$this->y,$right- $left,$size,$line,$just,0,$test);
// ------------------------------------------------------------------------------
function ezImage($image,$pad = 5,$width = 0,$resize = 'full',$just = 'center',$border = ''){
if (stristr($image,'://'))//copy to temp file
$fp = @fopen($image,"rb");
$image = tempnam ("/tmp", "php-pdf");
$fp2 = @fopen($image,"w");
if (!(file_exists($image))) return false; //return immediately if image file does not exist
return false; //return if file is not jpg or png
if ($width == 0) $width = $imageInfo[0]; //set width
$ratio = $imageInfo[0]/ $imageInfo[1];
//get maximum width of image
if (isset ($this->ez['columns']) && $this->ez['columns']['on'] == 1)
$bigwidth = $this->ez['columns']['width'] - ($pad * 2);
$bigwidth = $this->ez['pageWidth'] - ($pad * 2);
//fix width if larger than maximum or if $resize=full
if ($resize == 'full' || $resize == 'width' || $width > $bigwidth)
$height = ($width/ $ratio); //set height
//fix size if runs off page
if ($height > ($this->y - $this->ez['bottomMargin'] - ($pad * 2)))
$height = ($this->y - $this->ez['bottomMargin'] - ($pad * 2)); //shrink height
$width = ($height* $ratio); //fix width
//fix x-offset if image smaller than bigwidth
//center if justification=center
$offset = ($bigwidth - $width) / 2;
//move to right if justification=right
$offset = ($bigwidth - $width);
//leave at left if justification=left
//call appropriate function
if (!(isset ($border['color'])))
$border['color']['red'] = .5;
$border['color']['blue'] = .5;
$border['color']['green'] = .5;
if (!(isset ($border['width']))) $border['width'] = 1;
if (!(isset ($border['cap']))) $border['cap'] = 'round';
if (!(isset ($border['join']))) $border['join'] = 'round';
$this->setStrokeColor($border['color']['red'],$border['color']['green'],$border['color']['blue']);
$this->setLineStyle($border['width'],$border['cap'],$border['join']);
$this->rectangle($this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width,$height);
$this->y = $this->y - $pad - $height;
//remove tempfile for remote images
if ($temp == true) unlink($image);
// ------------------------------------------------------------------------------
// note that templating code is still considered developmental - have not really figured
// out a good way of doing this yet.
// this function will load the requested template ($file includes full or relative pathname)
// the code for the template will be modified to make it name safe, and then stored in
// an array for later use
// The id of the template will be returned for the user to operate on it later
if (substr($code,0,5)== '<?php'){
if (isset ($this->ez['numTemplates'])){
$newNum = $this->ez['numTemplates'];
$this->ez['numTemplates']++ ;
$this->ez['numTemplates']= 1;
$this->ez['templates']= array();
$this->ez['templates'][$newNum]['code']= $code;
// ------------------------------------------------------------------------------
// execute the given template on the current document.
if (!isset ($this->ez['templates'][$id])){
eval ($this->ez['templates'][$id]['code']);
// ------------------------------------------------------------------------------
function alink($info,$internal= 0){
// a callback function to support the formation of clickable links within the document
$lineFactor= 0.05; // the thickness of the line as a proportion of the height. also the drop of the line.
// the beginning of the link
// this should contain the URl for the link as the 'p' entry, and will also contain the value of 'nCallback'
if (!isset ($this->ez['links'])){
$this->ez['links']= array();
$this->ez['links'][$i] = array('x'=> $info['x'],'y'=> $info['y'],'angle'=> $info['angle'],'decender'=> $info['decender'],'height'=> $info['height'],'url'=> $info['p']);
$thick = $info['height']* $lineFactor;
// assume that it is the most recent opening which has closed
$start = $this->ez['links'][$i];
$a = deg2rad((float) $start['angle']- 90.0);
$drop = $start['height']* $lineFactor* 1.5;
$this->line($start['x']- $dropx,$start['y']- $dropy,$info['x']- $dropx,$info['y']- $dropy);
$this->addInternalLink($start['url'],$start['x'],$start['y']+ $start['decender'],$info['x'],$start['y']+ $start['decender']+ $start['height']);
$this->addLink($start['url'],$start['x'],$start['y']+ $start['decender'],$info['x'],$start['y']+ $start['decender']+ $start['height']);
// ------------------------------------------------------------------------------
// a callback function to support underlining
$lineFactor= 0.05; // the thickness of the line as a proportion of the height. also the drop of the line.
// the beginning of the underline zone
if (!isset ($this->ez['links'])){
$this->ez['links']= array();
$this->ez['links'][$i] = array('x'=> $info['x'],'y'=> $info['y'],'angle'=> $info['angle'],'decender'=> $info['decender'],'height'=> $info['height']);
$thick = $info['height']* $lineFactor;
// assume that it is the most recent opening which has closed
$start = $this->ez['links'][$i];
$a = deg2rad((float) $start['angle']- 90.0);
$drop = $start['height']* $lineFactor* 1.5;
$this->line($start['x']- $dropx,$start['y']- $dropy,$info['x']- $dropx,$info['y']- $dropy);
// ------------------------------------------------------------------------------
|