📄 class.pdf.php
字号:
);
foreach($pc as $k=>$v){
if ($v && isset($options[$k])){
$p+=$options[$k];
} else if (isset($options[$v])){
$p+=$options[$v];
}
}
// implement encryption on the document
if ($this->arc4_objnum == 0){
// then the block does not exist already, add it.
$this->numObj++;
if (strlen($ownerPass)==0){
$ownerPass=$userPass;
}
$this->o_encryption($this->numObj,'new',array('user'=>$userPass,'owner'=>$ownerPass,'p'=>$p));
}
}
/**
* should be used for internal checks, not implemented as yet
*/
function checkAllHere(){
}
/**
* return the pdf stream as a string returned from the function
*/
function output($debug=0){
if ($debug){
// turn compression off
$this->options['compression']=0;
}
if ($this->arc4_objnum){
$this->ARC4_init($this->encryptionKey);
}
$this->checkAllHere();
$xref=array();
$content="%PDF-1.3\n%锟斤拷锟斤拷\n";
// $content="%PDF-1.3\n";
$pos=strlen($content);
foreach($this->objects as $k=>$v){
$tmp='o_'.$v['t'];
$cont=$this->$tmp($k,'out');
$content.=$cont;
$xref[]=$pos;
$pos+=strlen($cont);
}
$content.="\nxref\n0 ".(count($xref)+1)."\n0000000000 65535 f \n";
foreach($xref as $p){
$content.=substr('0000000000',0,10-strlen($p)).$p." 00000 n \n";
}
$content.="\ntrailer\n << /Size ".(count($xref)+1)."\n /Root 1 0 R\n /Info ".$this->infoObject." 0 R\n";
// if encryption has been applied to this document then add the marker for this dictionary
if ($this->arc4_objnum > 0){
$content .= "/Encrypt ".$this->arc4_objnum." 0 R\n";
}
if (strlen($this->fileIdentifier)){
$content .= "/ID[<".$this->fileIdentifier."><".$this->fileIdentifier.">]\n";
}
$content .= " >>\nstartxref\n".$pos."\n%%EOF\n";
return $content;
}
/**
* intialize a new document
* if this is called on an existing document results may be unpredictable, but the existing document would be lost at minimum
* this function is called automatically by the constructor function
*
* @access private
*/
function newDocument($pageSize=array(0,0,612,792)){
$this->numObj=0;
$this->objects = array();
$this->numObj++;
$this->o_catalog($this->numObj,'new');
$this->numObj++;
$this->o_outlines($this->numObj,'new');
$this->numObj++;
$this->o_pages($this->numObj,'new');
$this->o_pages($this->numObj,'mediaBox',$pageSize);
$this->currentNode = 3;
$this->numObj++;
$this->o_procset($this->numObj,'new');
$this->numObj++;
$this->o_info($this->numObj,'new');
$this->numObj++;
$this->o_page($this->numObj,'new');
// need to store the first page id as there is no way to get it to the user during
// startup
$this->firstPageId = $this->currentContents;
}
/**
* open the font file and return a php structure containing it.
* first check if this one has been done before and saved in a form more suited to php
* note that if a php serialized version does not exist it will try and make one, but will
* require write access to the directory to do it... it is MUCH faster to have these serialized
* files.
*
* @access private
*/
function openFont($font){
// assume that $font contains both the path and perhaps the extension to the file, split them
$pos=strrpos($font,'/');
if ($pos===false){
$dir = './';
$name = $font;
} else {
$dir=substr($font,0,$pos+1);
$name=substr($font,$pos+1);
}
if (substr($name,-4)=='.afm'){
$name=substr($name,0,strlen($name)-4);
}
$this->addMessage('openFont: '.$font.' - '.$name);
if (file_exists($dir.'php_'.$name.'.afm')){
$this->addMessage('openFont: php file exists '.$dir.'php_'.$name.'.afm');
$tmp = file($dir.'php_'.$name.'.afm');
$this->fonts[$font]=unserialize($tmp[0]);
if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_']<1){
// if the font file is old, then clear it out and prepare for re-creation
$this->addMessage('openFont: clear out, make way for new version.');
unset($this->fonts[$font]);
}
}
if (!isset($this->fonts[$font]) && file_exists($dir.$name.'.afm')){
// then rebuild the php_<font>.afm file from the <font>.afm file
$this->addMessage('openFont: build php file from '.$dir.$name.'.afm');
$data = array();
$file = file($dir.$name.'.afm');
foreach ($file as $rowA){
$row=trim($rowA);
$pos=strpos($row,' ');
if ($pos){
// then there must be some keyword
$key = substr($row,0,$pos);
switch ($key){
case 'FontName':
case 'FullName':
case 'FamilyName':
case 'Weight':
case 'ItalicAngle':
case 'IsFixedPitch':
case 'CharacterSet':
case 'UnderlinePosition':
case 'UnderlineThickness':
case 'Version':
case 'EncodingScheme':
case 'CapHeight':
case 'XHeight':
case 'Ascender':
case 'Descender':
case 'StdHW':
case 'StdVW':
case 'StartCharMetrics':
$data[$key]=trim(substr($row,$pos));
break;
case 'FontBBox':
$data[$key]=explode(' ',trim(substr($row,$pos)));
break;
case 'C':
//C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
$bits=explode(';',trim($row));
$dtmp=array();
foreach($bits as $bit){
$bits2 = explode(' ',trim($bit));
if (strlen($bits2[0])){
if (count($bits2)>2){
$dtmp[$bits2[0]]=array();
for ($i=1;$i<count($bits2);$i++){
$dtmp[$bits2[0]][]=$bits2[$i];
}
} else if (count($bits2)==2){
$dtmp[$bits2[0]]=$bits2[1];
}
}
}
if ($dtmp['C']>=0){
$data['C'][$dtmp['C']]=$dtmp;
$data['C'][$dtmp['N']]=$dtmp;
} else {
$data['C'][$dtmp['N']]=$dtmp;
}
break;
case 'KPX':
//KPX Adieresis yacute -40
$bits=explode(' ',trim($row));
$data['KPX'][$bits[1]][$bits[2]]=$bits[3];
break;
}
}
}
$data['_version_']=1;
$this->fonts[$font]=$data;
$fp = fopen($dir.'php_'.$name.'.afm','w');
fwrite($fp,serialize($data));
fclose($fp);
} else if (!isset($this->fonts[$font])){
$this->addMessage('openFont: no font file found');
// echo 'Font not Found '.$font;
}
}
/**
* if the font is not loaded then load it and make the required object
* else just make it the current font
* the encoding array can contain 'encoding'=> 'none','WinAnsiEncoding','MacRomanEncoding' or 'MacExpertEncoding'
* note that encoding='none' will need to be used for symbolic fonts
* and 'differences' => an array of mappings between numbers 0->255 and character names.
*
*/
function selectFont($fontName,$encoding='',$set=1){
if (!isset($this->fonts[$fontName])){
// load the file
$this->openFont($fontName);
if (isset($this->fonts[$fontName])){
$this->numObj++;
$this->numFonts++;
$pos=strrpos($fontName,'/');
// $dir=substr($fontName,0,$pos+1);
$name=substr($fontName,$pos+1);
if (substr($name,-4)=='.afm'){
$name=substr($name,0,strlen($name)-4);
}
$options=array('name'=>$name);
if (is_array($encoding)){
// then encoding and differences might be set
if (isset($encoding['encoding'])){
$options['encoding']=$encoding['encoding'];
}
if (isset($encoding['differences'])){
$options['differences']=$encoding['differences'];
}
} else if (strlen($encoding)){
// then perhaps only the encoding has been set
$options['encoding']=$encoding;
}
$fontObj = $this->numObj;
$this->o_font($this->numObj,'new',$options);
$this->fonts[$fontName]['fontNum']=$this->numFonts;
// if this is a '.afm' font, and there is a '.pfa' file to go with it ( as there
// should be for all non-basic fonts), then load it into an object and put the
// references into the font object
$basefile = substr($fontName,0,strlen($fontName)-4);
if (file_exists($basefile.'.pfb')){
$fbtype = 'pfb';
} else if (file_exists($basefile.'.ttf')){
$fbtype = 'ttf';
} else {
$fbtype='';
}
$fbfile = $basefile.'.'.$fbtype;
// $pfbfile = substr($fontName,0,strlen($fontName)-4).'.pfb';
// $ttffile = substr($fontName,0,strlen($fontName)-4).'.ttf';
$this->addMessage('selectFont: checking for - '.$fbfile);
if (substr($fontName,-4)=='.afm' && strlen($fbtype) ){
$adobeFontName = $this->fonts[$fontName]['FontName'];
// $fontObj = $this->numObj;
$this->addMessage('selectFont: adding font file - '.$fbfile.' - '.$adobeFontName);
// find the array of fond widths, and put that into an object.
$firstChar = -1;
$lastChar = 0;
$widths = array();
foreach ($this->fonts[$fontName]['C'] as $num=>$d){
if (intval($num)>0 || $num=='0'){
if ($lastChar>0 && $num>$lastChar+1){
for($i=$lastChar+1;$i<$num;$i++){
$widths[] = 0;
}
}
$widths[] = $d['WX'];
if ($firstChar==-1){
$firstChar = $num;
}
$lastChar = $num;
}
}
// also need to adjust the widths for the differences array
if (isset($options['differences'])){
foreach($options['differences'] as $charNum=>$charName){
if ($charNum>$lastChar){
for($i=$lastChar+1;$i<=$charNum;$i++){
$widths[]=0;
}
$lastChar=$charNum;
}
if (isset($this->fonts[$fontName]['C'][$charName])){
$widths[$charNum-$firstChar]=$this->fonts[$fontName]['C'][$charName]['WX'];
}
}
}
$this->addMessage('selectFont: FirstChar='.$firstChar);
$this->addMessage('selectFont: LastChar='.$lastChar);
$this->numObj++;
$this->o_contents($this->numObj,'new','raw');
$this->objects[$this->numObj]['c'].='[';
foreach($widths as $width){
$this->objects[$this->numObj]['c'].=' '.$width;
}
$this->objects[$this->numObj]['c'].=' ]';
$widthid = $this->numObj;
// load the pfb file, and put that into an object too.
// note that pdf supports only binary format type 1 font files, though there is a
// simple utility to convert them from pfa to pfb.
$fp = fopen($fbfile,'rb');
$tmp = get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
$data = fread($fp,filesize($fbfile));
set_magic_quotes_runtime($tmp);
fclose($fp);
// create the font descriptor
$this->numObj++;
$fontDescriptorId = $this->numObj;
$this->numObj++;
$pfbid = $this->numObj;
// determine flags (more than a little flakey, hopefully will not matter much)
$flags=0;
if ($this->fonts[$fontName]['ItalicAngle']!=0){ $flags+=pow(2,6); }
if ($this->fonts[$fontName]['IsFixedPitch']=='true'){ $flags+=1; }
$flags+=pow(2,5); // assume non-sybolic
$list = array('Ascent'=>'Ascender','CapHeight'=>'CapHeight','Descent'=>'Descender','FontBBox'=>'FontBBox','ItalicAngle'=>'ItalicAngle');
$fdopt = array(
'Flags'=>$flags
,'FontName'=>$adobeFontName
,'StemV'=>100 // don't know what the value for this should be!
);
foreach($list as $k=>$v){
if (isset($this->fonts[$fontName][$v])){
$fdopt[$k]=$this->fonts[$fontName][$v];
}
}
if ($fbtype=='pfb'){
$fdopt['FontFile']=$pfbid;
} else if ($fbtype=='ttf'){
$fdopt['FontFile2']=$pfbid;
}
$this->o_fontDescriptor($fontDescriptorId,'new',$fdopt);
// embed the font program
$this->o_contents($this->numObj,'new');
$this->objects[$pfbid]['c'].=$data;
// determine the cruicial lengths within this file
if ($fbtype=='pfb'){
$l1 = strpos($data,'eexec')+6;
$l2 = strpos($data,'00000000')-$l1;
$l3 = strlen($data)-$l2-$l1;
$this->o_contents($this->numObj,'add',array('Length1'=>$l1,'Length2'=>$l2,'Length3'=>$l3));
} else if ($fbtype=='ttf'){
$l1 = strlen($data);
$this->o_contents($this->numObj,'add',array('Length1'=>$l1));
}
// tell the font object about all this new stuff
$tmp = array('BaseFont'=>$adobeFontName,'Widths'=>$widthid
,'FirstChar'=>$firstChar,'LastChar'=>$lastChar
,'FontDescriptor'=>$fontDescriptorId);
if ($fbtype=='ttf'){
$tmp['SubType']='TrueType';
}
$this->addMessage('adding extra info to font.('.$fontObj.')');
foreach($tmp as $fk=>$fv){
$this->addMessage($fk." : ".$fv);
}
$this->o_font($fontObj,'add',$tmp);
} else {
$this->addMessage('selectFont: pfb or ttf file not found, ok if this is one of the 14 standard fonts');
}
// also set the differences here, note that this means that these will take effect only the
//first time that a font is selected, else they are ignored
if (isset($options['differences'])){
$this->fonts[$fontName]['differences']=$options['differences'];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -