** * add text to the document, at a specified location, size and angle on the page */ function addText($x,$y,$size,$text,$angle=0,$wordSpaceAdjust=0){ if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');} // if there are any open callbacks, then they should be called, to show the start of the line if ($this->nCallback>0){ for ($i=$this->nCallback;$i>0;$i--){ // call each function $info = array('x'=>$x,'y'=>$y,'angle'=>$angle,'status'=>'sol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']); $func = $this->callback[$i]['f']; $this->$func($info); } } if ($angle==0){ $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Td'; } else { $a = deg2rad((float)$angle); $tmp = "\n".'BT '; $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' '; $tmp .= sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Tm'; $this->objects[$this->currentContents]['c'] .= $tmp; } if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){ $this->wordSpaceAdjust=$wordSpaceAdjust; $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw'; } $len=strlen($text); $start=0; for ($i=0;$i<$len;$i++){ $f=1; $directive = $this->PRVTcheckTextDirective($text,$i,$f); if ($directive){ // then we should write what we need to if ($i>$start){ $part = substr($text,$start,$i-$start); $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf '; $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj'; } if ($f){ // then there was nothing drastic done here, restore the contents $this->setCurrentFont(); } else { $this->objects[$this->currentContents]['c'] .= ' ET'; $f=1; $xp=$x; $yp=$y; $directive = $this->PRVTcheckTextDirective1($text,$i,$f,1,$xp,$yp,$size,$angle,$wordSpaceAdjust); // restart the text object if ($angle==0){ $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Td'; } else { $a = deg2rad((float)$angle); $tmp = "\n".'BT '; $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' '; $tmp .= sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Tm'; $this->objects[$this->currentContents]['c'] .= $tmp; } if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){ $this->wordSpaceAdjust=$wordSpaceAdjust; $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw'; } } // and move the writing point to the next piece of text $i=$i+$directive-1; $start=$i+1; } } if ($start<$len){ $part = substr($text,$start); $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf '; $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj'; } $this->objects[$this->currentContents]['c'].=' ET'; // if there are any open callbacks, then they should be called, to show the end of the line if ($this->nCallback>0){ for ($i=$this->nCallback;$i>0;$i--){ // call each function $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,$text); $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'eol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']); $func = $this->callback[$i]['f']; $this->$func($info); } } } /** * calculate how wide a given text string will be on a page, at a given size. * this can be called externally, but is alse used by the other class functions */ function getTextWidth($size,$text){ // this function should not change any of the settings, though it will need to // track any directives which change during calculation, so copy them at the start // and put them back at the end. $store_currentTextState = $this->currentTextState; if (!$this->numFonts){ $this->selectFont('./fonts/Helvetica'); } // converts a number or a float to a string so it can get the width $text = "$text"; // hmm, this is where it all starts to get tricky - use the font information to // calculate the width of each character, add them up and convert to user units $w=0; $len=strlen($text); $cf = $this->currentFont; for ($i=0;$i<$len;$i++){ $f=1; $directive = $this->PRVTcheckTextDirective($text,$i,$f); if ($directive){ if ($f){ $this->setCurrentFont(); $cf = $this->currentFont; } $i=$i+$directive-1; } else { $char=ord($text[$i]); if (isset($this->fonts[$cf]['differences'][$char])){ // then this character is being replaced by another $name = $this->fonts[$cf]['differences'][$char]; if (isset($this->fonts[$cf]['C'][$name]['WX'])){ $w+=$this->fonts[$cf]['C'][$name]['WX']; } } else if (isset($this->fonts[$cf]['C'][$char]['WX'])){ $w+=$this->fonts[$cf]['C'][$char]['WX']; } } } $this->currentTextState = $store_currentTextState; $this->setCurrentFont(); return $w*$size/1000; } /** * do a part of the calculation for sorting out the justification of the text * * @access private */ function PRVTadjustWrapText($text,$actual,$width,&$x,&$adjust,$justification){ switch ($justification){ case 'left': return; break; case 'right': $x+=$width-$actual; break; case 'center': case 'centre': $x+=($width-$actual)/2; break; case 'full': // count the number of words $words = explode(' ',$text); $nspaces=count($words)-1; if ($nspaces>0){ $adjust = ($width-$actual)/$nspaces; } else { $adjust=0; } break; } } /** * add text to the page, but ensure that it fits within a certain width * if it does not fit then put in as much as possible, splitting at word boundaries * and return the remainder. * justification and angle can also be specified for the text */ function addTextWrap($x,$y,$width,$size,$text,$justification='left',$angle=0,$test=0){ // this will display the text, and if it goes beyond the width $width, will backtrack to the // previous space or hyphen, and return the remainder of the text. // $justification can be set to 'left','right','center','centre','full' // need to store the initial text state, as this will change during the width calculation // but will need to be re-set before printing, so that the chars work out right $store_currentTextState = $this->currentTextState; if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');} if ($width<=0){ // error, pretend it printed ok, otherwise risking a loop return ''; } $w=0; $break=0; $breakWidth=0; $len=strlen($text); $cf = $this->currentFont; $tw = $width/$size*1000; for ($i=0;$i<$len;$i++){ $f=1; $directive = $this->PRVTcheckTextDirective($text,$i,$f); if ($directive){ if ($f){ $this->setCurrentFont(); $cf = $this->currentFont; } $i=$i+$directive-1; } else { $cOrd = ord($text[$i]); if (isset($this->fonts[$cf]['differences'][$cOrd])){ // then this character is being replaced by another $cOrd2 = $this->fonts[$cf]['differences'][$cOrd]; } else { $cOrd2 = $cOrd; } if (isset($this->fonts[$cf]['C'][$cOrd2]['WX'])){ $w+=$this->fonts[$cf]['C'][$cOrd2]['WX']; } if ($w>$tw){ // then we need to truncate this line if ($break>0){ // then we have somewhere that we can split :) if ($text[$break]==' '){ $tmp = substr($text,0,$break); } else { $tmp = substr($text,0,$break+1); } $adjust=0; $this->PRVTadjustWrapText($tmp,$breakWidth,$width,$x,$adjust,$justification); // reset the text state $this->currentTextState = $store_currentTextState; $this->setCurrentFont(); if (!$test){ $this->addText($x,$y,$size,$tmp,$angle,$adjust); } return substr($text,$break+1); } else { // just split before the current character $tmp = substr($text,0,$i); $adjust=0; $ctmp=ord($text[$i]); if (isset($this->fonts[$cf]['differences'][$ctmp])){ $ctmp=$this->fonts[$cf]['differences'][$ctmp]; } $tmpw=($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000; $this->PRVTadjustWrapText($tmp,$tmpw,$width,$x,$adjust,$justification); // reset the text state $this->currentTextState = $store_currentTextState; $this->setCurrentFont(); if (!$test){ $this->addText($x,$y,$size,$tmp,$angle,$adjust); } return substr($text,$i); } } if ($text[$i]=='-'){ $break=$i; $breakWidth = $w*$size/1000; } if ($text[$i]==' '){ $break=$i; $ctmp=ord($text[$i]); if (isset($this->fonts[$cf]['differences'][$ctmp])){ $ctmp=$this->fonts[$cf]['differences'][$ctmp]; } $breakWidth = ($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000; } } } // then there was no need to break this line if ($justification=='full'){ $justification='left'; } $adjust=0; $tmpw=$w*$size/1000; $this->PRVTadjustWrapText($text,$tmpw,$width,$x,$adjust,$justification); // reset the text state $this->currentTextState = $store_currentTextState; $this->setCurrentFont(); if (!$test){ $this->addText($x,$y,$size,$text,$angle,$adjust,$angle); } return ''; } /** * this will be called at a new page to return the state to what it was on the * end of the previous page, before the stack was closed down * This is to get around not being able to have open 'q' across pages * */ function saveState($pageEnd=0){ if ($pageEnd){ // this will be called at a new page to return the state to what it was on the // end of the previous page, before the stack was closed down // This is to get around not being able to have open 'q' across pages $opt = $this->stateStack[$pageEnd]; // ok to use this as stack starts numbering at 1 $this->setColor($opt['col']['r'],$opt['col']['g'],$opt['col']['b'],1); $this->setStrokeColor($opt['str']['r'],$opt['str']['g'],$opt['str']['b'],1); $this->objects[$this->currentContents]['c'].="\n".$opt['lin']; // $this->currentLineStyle = $opt['lin']; } else { $this->nStateStack++; $this->stateStack[$this->nStateStack]=array( 'col'=>$this->currentColour ,'str'=>$this->currentStrokeColour ,'lin'=>$this->currentLineStyle ); } $this->objects[$this->currentContents]['c'].="\nq"; } /** * restore a previously saved state */ function restoreState($pageEnd=0){ if (!$pageEnd){ $n = $this->nStateStack; $this->currentColour = $this->stateStack[$n]['col']; $this->currentStrokeColour = $this->stateStack[$n]['str']; $this->objects[$this->currentContents]['c'].="\n".$this->stateStack[$n]['lin']; $this->currentLineStyle = $this->stateStack[$n]['lin']; unset($this->stateStack[$n]); $this->nStateStack--; } $this->objects[$this->currentContents]['c'].="\nQ"; } /** * make a loose object, the output will go into this object, until it is closed, then will revert to * the current one. * this object will not appear until it is included within a page. * the function will return the object number */ function openObject(){ $this->nStack++; $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage); // add a new object of the content type, to hold the data flow $this->numObj++; $this->o_contents($this->numObj,'new'); $this->currentContents=$this->numObj; $this->looseObjects[$this->numObj]=1; return $this->numObj; } /** * open an existing object for editing */ function reopenObject($id){ $this->nStack++; $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage); $this->currentContents=$id; // also if this object is the primary contents for a page, then set the current page to its parent if (isset($this->objects[$id]['onPage'])){ $this->currentPage = $this->objects[$id]['onPage']; } } /** * close an object */ function closeObject(){ // close the object, as long as there was one open in the first place, which will be indicated by // an objectId on the stack. if ($this->nStack>0){ $this->currentContents=$this->stack[$this->nStack]['c']; $this->currentPage=$this->stack[$this->nStack]['p']; $this->nStack--; // easier to probably not worry about removing the old entries, they will be overwritten // if there are new ones. } } /** * stop an object from appearing on pages from this point on */ function stopObject($id){ // if an object has been appearing on pages up to now, then stop it, this page will // be the last one that could contian it. if (isset($this->addLooseObjects[$id])){ $this->addLooseObjects[$id]=''; } } /** * after an object has been created, it wil only show if it has been added, using this function. */ function addObject($id,$options='add'){ // add the specified object to the page if (isset($this->looseObjects[$id]) && $this->currentContents!=$id){ // then it is a valid object, and it is not being added to itself switch($options){ case 'all': // then this object is to be added to this page (done in the next block) and // all future new pages. $this->addLooseObjects[$id]='all'; case 'add': if (isset($this->objects[$this->currentContents]['onPage'])){ // then the destination contents is the primary for the page // (though this object is actually added to that page) $this->o_page($this->objects[$this->currentContents]['onPage'],'content',$id); } break; case 'even': $this->addLooseObjects[$id]='even'; $pageObjectId=$this->objects[$this->currentContents]['onPage']; if ($this->objects[$pageObjectId]['info']['pageNum']%2==0){ $this->addObject($id); // hacky huh :) } break; case 'odd': $this->addLooseObjects[$id]='odd'; $pageObjectId=$this->objects[$this->currentContents]['onPage']; if ($this->objects[$pageObjectId]['info']['pageNum']%2==1){ $this->addObject($id); // hacky huh :) } break; case 'next': $this->addLooseObjects[$id]='all'; break; case 'nexteven': $this->addLooseObjects[$id]='even'; break; case 'nextodd': $this->addLooseObjects[$id]='odd'; break; } } } /** * add content to the documents info object */ function addInfo($label,$value=0){ // this will only work if the label is one of the valid ones. // modify this so that arrays can be passed as well. // if $label is an array then assume that it is key=>value pairs // else assume that they are both scalar, anything else will probably error if (is_array($label)){ foreach ($label as $l=>$v){ $this->o_info($this->infoObject,$l,$v); } } else { $this->o_info($this->infoObject,$label,$value); } } /** * set the viewer preferences of the document, it is up to the browser to obey these. */ function setPreferences($label,$value=0){ // this will only work if the label is one of the valid ones. if (is_array($label)){ foreach ($label as $l=>$v){ $this->o_catalog($this->catalogId,'viewerPreferences',array($l=>$v)); } } else { $this->o_catalog($this->catalogId,'viewerPreferences',array($label=>$value)); } } /** * extract an integer from a position in a byte stream * * @access private */ function PRVT_getBytes(&$data,$pos,$num){ // return the integer represented by $num bytes from $pos within $data $ret=0; for ($i=0;$i<$num;$i++){ $ret=$ret*256; $ret+=ord($data[$pos+$i]); } return $ret; } /** * add a PNG image into the document, from a file * this should work with remote files */ function addPngFromFile($file,$x,$y,$w=0,$h=0){ // read in a png file, interpret it, then add to the system $error=0; $tmp = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); $fp = @fopen($file,'rb'); if ($fp){ $data=''; while(!feof($fp)){ $data .= fread($fp,1024); } fclose($fp); } else { $error = 1; $errormsg = 'trouble opening file: '.$file; } set_magic_quotes_runtime($tmp); if (!$error){ $header = chr(137).chr(80).chr(78).chr(71).chr(13).chr(10).chr(26).chr(10); if (substr($data,0,8)!=$header){ $error=1; $errormsg = 'this file does not have a valid header'; } } if (!$error){ // set pointer $p = 8; $len = strlen($data); // cycle through the file, identifying chunks $haveHeader=0; $info=array(); $idata=''; $pdata=''; while ($p<$len){ $chunkLen = $this->PRVT_getBytes($data,$p,4); $chunkType = substr($data,$p+4,4); // echo $chunkType.' - '.$chunkLen.'
'; switch($chunkType){ case 'IHDR': // this is where all the file information comes from $info['width']=$this->PRVT_getBytes($data,$p+8,4); $info['height']=$this->PRVT_getBytes($data,$p+12,4); $info['bitDepth']=ord($data[$p+16]); $info['colorType']=ord($data[$p+17]); $info['compressionMethod']=ord($data[$p+18]); $info['filterMethod']=ord($data[$p+19]); $info['interlaceMethod']=ord($data[$p+20]); //print_r($info); $haveHeader=1; if ($info['compressionMethod']!=0){ $error=1; $errormsg = 'unsupported compression method'; } if ($info['filterMethod']!=0){ $error=1; $errormsg = 'unsupported filter method'; } break; case 'PLTE': $pdata.=substr($data,$p+8,$chunkLen); break; case 'IDAT': $idata.=substr($data,$p+8,$chunkLen); break; case 'tRNS': //this chunk can only occur once and it must occur after the PLTE chunk and before IDAT chunk //print "tRNS found, color type = ".$info['colorType']."
"; $transparency = array(); if ($info['colorType'] == 3) { // indexed color, rbg /* corresponding to entries in the plte chunk Alpha for palette index 0: 1 byte Alpha for palette index 1: 1 byte ...etc... */ // there will be one entry for each palette entry. up until the last non-opaque entry. // set up an array, stretching over all palette entries which will be o (opaque) or 1 (transparent) $transparency['type']='indexed'; $numPalette = strlen($pdata)/3; $trans=0; for ($i=$chunkLen;$i>=0;$i--){ if (ord($data[$p+8+$i])==0){ $trans=$i; } } $transparency['data'] = $trans; } elseif($info['colorType'] == 0) { // grayscale /* corresponding to entries in the plte chunk Gray: 2 bytes, range 0 .. (2^bitdepth)-1 */ // $transparency['grayscale']=$this->PRVT_getBytes($data,$p+8,2); // g = grayscale $transparency['type']='indexed'; $transparency['data'] = ord($data[$p+8+1]); } elseif($info['colorType'] == 2) { // truecolor /* corresponding to entries in the plte chunk Red: 2 bytes, range 0 .. (2^bitdepth)-1 Green: 2 bytes, range 0 .. (2^bitdepth)-1 Blue: 2 bytes, range 0 .. (2^bitdepth)-1 */ $transparency['r']=$this->PRVT_getBytes($data,$p+8,2); // r from truecolor $transparency['g']=$this->PRVT_getBytes($data,$p+10,2); // g from truecolor $transparency['b']=$this->PRVT_getBytes($data,$p+12,2); // b from truecolor } else { //unsupported transparency type } // KS End new code break; default: break; } $p += $chunkLen+12; } if(!$haveHeader){ $error = 1; $errormsg = 'information header is missing'; } if (isset($info['interlaceMethod']) && $info['interlaceMethod']){ $error = 1; $errormsg = 'There appears to be no support for interlaced images in pdf.'; } } if (!$error && $info['bitDepth'] > 8){ $error = 1; $errormsg = 'only bit depth of 8 or less is supported'; } if (!$error){ if ($info['colorType']!=2 && $info['colorType']!=0 && $info['colorType']!=3){ $error = 1; $errormsg = 'transparancey alpha channel not supported, transparency only supported for palette images.'; } else { switch ($info['colorType']){ case 3: $color = 'DeviceRGB'; $ncolor=1; break; case 2: $color = 'DeviceRGB'; $ncolor=3; break; case 0: $color = 'DeviceGray'; $ncolor=1; break; } } } if ($error){ $this->addMessage('PNG error - ('.$file.') '.$errormsg); return; } if ($w==0){ $w=$h/$info['height']*$info['width']; } if ($h==0){ $h=$w*$info['height']/$info['width']; } //print_r($info); // so this image is ok... add it in. $this->numImages++; $im=$this->numImages; $label='I'.$im; $this->numObj++; // $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$idata,'iw'=>$w,'ih'=>$h,'type'=>'png','ic'=>$info['width'])); $options = array('label'=>$label,'data'=>$idata,'bitsPerComponent'=>$info['bitDepth'],'pdata'=>$pdata ,'iw'=>$info['width'],'ih'=>$info['height'],'type'=>'png','color'=>$color,'ncolor'=>$ncolor); if (isset($transparency)){ $options['transparency']=$transparency; } $this->o_image($this->numObj,'new',$options); $this->objects[$this->currentContents]['c'].="\nq"; $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm"; $this->objects[$this->currentContents]['c'].="\n/".$label.' Do'; $this->objects[$this->currentContents]['c'].="\nQ"; } /** * add a JPEG image into the document, from a file */ function addJpegFromFile($img,$x,$y,$w=0,$h=0){ // attempt to add a jpeg image straight from a file, using no GD commands // note that this function is unable to operate on a remote file. if (!file_exists($img)){ return; } $tmp=getimagesize($img); $imageWidth=$tmp[0]; $imageHeight=$tmp[1]; if (isset($tmp['channels'])){ $channels = $tmp['channels']; } else { $channels = 3; } if ($w<=0 && $h<=0){ $w=$imageWidth; } if ($w==0){ $w=$h/$imageHeight*$imageWidth; } if ($h==0){ $h=$w*$imageHeight/$imageWidth; } $fp=fopen($img,'rb'); $tmp = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); $data = fread($fp,filesize($img)); set_magic_quotes_runtime($tmp); fclose($fp); $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight,$channels); } /** * add an image into the document, from a GD object * this function is not all that reliable, and I would probably encourage people to use * the file based functions */ function addImage(&$img,$x,$y,$w=0,$h=0,$quality=75){ // add a new image into the current location, as an external object // add the image at $x,$y, and with width and height as defined by $w & $h // note that this will only work with full colour images and makes them jpg images for display // later versions could present lossless image formats if there is interest. // there seems to be some problem here in that images that have quality set above 75 do not appear // not too sure why this is, but in the meantime I have restricted this to 75. if ($quality>75){ $quality=75; } // if the width or height are set to zero, then set the other one based on keeping the image // height/width ratio the same, if they are both zero, then give up :) $imageWidth=imagesx($img); $imageHeight=imagesy($img); if ($w<=0 && $h<=0){ return; } if ($w==0){ $w=$h/$imageHeight*$imageWidth; } if ($h==0){ $h=$w*$imageHeight/$imageWidth; } // gotta get the data out of the img.. // so I write to a temp file, and then read it back.. soo ugly, my apologies. $tmpDir='/tmp'; $tmpName=tempnam($tmpDir,'img'); imagejpeg($img,$tmpName,$quality); $fp=fopen($tmpName,'rb'); $tmp = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); $fp = @fopen($tmpName,'rb'); if ($fp){ $data=''; while(!feof($fp)){ $data .= fread($fp,1024); } fclose($fp); } else { $error = 1; $errormsg = 'trouble opening file'; } // $data = fread($fp,filesize($tmpName)); set_magic_quotes_runtime($tmp); // fclose($fp); unlink($tmpName); $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight); } /** * common code used by the two JPEG adding functions * * @access private */ function addJpegImage_common(&$data,$x,$y,$w=0,$h=0,$imageWidth,$imageHeight,$channels=3){ // note that this function is not to be called externally // it is just the common code between the GD and the file options $this->numImages++; $im=$this->numImages; $label='I'.$im; $this->numObj++; $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$data,'iw'=>$imageWidth,'ih'=>$imageHeight,'channels'=>$channels)); $this->objects[$this->currentContents]['c'].="\nq"; $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm"; $this->objects[$this->currentContents]['c'].="\n/".$label.' Do'; $this->objects[$this->currentContents]['c'].="\nQ"; } /** * specify where the document should open when it first starts */ function openHere($style,$a=0,$b=0,$c=0){ // this function will open the document at a specified page, in a specified style // the values for style, and the required paramters are: // 'XYZ' left, top, zoom // 'Fit' // 'FitH' top // 'FitV' left // 'FitR' left,bottom,right // 'FitB' // 'FitBH' top // 'FitBV' left $this->numObj++; $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c)); $id = $this->catalogId; $this->o_catalog($id,'openHere',$this->numObj); } /** * create a labelled destination within the document */ function addDestination($label,$style,$a=0,$b=0,$c=0){ // associates the given label with the destination, it is done this way so that a destination can be specified after // it has been linked to // styles are the same as the 'openHere' function $this->numObj++; $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c)); $id = $this->numObj; // store the label->idf relationship, note that this means that labels can be used only once $this->destinations["$label"]=$id; } /** * define font families, this is used to initialize the font families for the default fonts * and for the user to add new ones for their fonts. The default bahavious can be overridden should * that be desired. */ function setFontFamily($family,$options=''){ if (!is_array($options)){ if ($family=='init'){ // set the known family groups // these font families will be used to enable bold and italic markers to be included // within text streams. html forms will be used... $this->fontFamilies['Helvetica.afm']=array( 'b'=>'Helvetica-Bold.afm' ,'i'=>'Helvetica-Oblique.afm' ,'bi'=>'Helvetica-BoldOblique.afm' ,'ib'=>'Helvetica-BoldOblique.afm' ); $this->fontFamilies['Courier.afm']=array( 'b'=>'Courier-Bold.afm' ,'i'=>'Courier-Oblique.afm' ,'bi'=>'Courier-BoldOblique.afm' ,'ib'=>'Courier-BoldOblique.afm' ); $this->fontFamilies['Times-Roman.afm']=array( 'b'=>'Times-Bold.afm' ,'i'=>'Times-Italic.afm' ,'bi'=>'Times-BoldItalic.afm' ,'ib'=>'Times-BoldItalic.afm' ); } } else { // the user is trying to set a font family // note that this can also be used to set the base ones to something else if (strlen($family)){ $this->fontFamilies[$family] = $options; } } } /** * used to add messages for use in debugging */ function addMessage($message){ $this->messages.=$message."\n"; } /** * a few functions which should allow the document to be treated transactionally. */ function transaction($action){ switch ($action){ case 'start': // store all the data away into the checkpoint variable $data = get_object_vars($this); $this->checkpoint = $data; unset($data); break; case 'commit': if (is_array($this->checkpoint) && isset($this->checkpoint['checkpoint'])){ $tmp = $this->checkpoint['checkpoint']; $this->checkpoint = $tmp; unset($tmp); } else { $this->checkpoint=''; } break; case 'rewind': // do not destroy the current checkpoint, but move us back to the state then, so that we can try again if (is_array($this->checkpoint)){ // can only abort if were inside a checkpoint $tmp = $this->checkpoint; foreach ($tmp as $k=>$v){ if ($k != 'checkpoint'){ $this->$k=$v; } } unset($tmp); } break; case 'abort': if (is_array($this->checkpoint)){ // can only abort if were inside a checkpoint $tmp = $this->checkpoint; foreach ($tmp as $k=>$v){ $this->$k=$v; } unset($tmp); } break; } } } // end of class ?>
Fatal error: Class 'Cpdf' not found in /home/clight/public_html/includes/class.ezpdf.php on line 5