📄 class.pdf.php
字号:
$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; file_put_contents($dir . 'php_' . $name . '.afm', '$this->fonts[$font]=' . var_export($data, true) . ';'); } 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++; //$this->numFonts = md5($fontName); $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. $tmp = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); $data = file_get_contents($fbfile); set_magic_quotes_runtime($tmp); // 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']; } } } if ($set && isset($this->fonts[$fontName])) { // so if for some reason the font was not set in the last one then it will not be selected $this->currentBaseFont = $fontName; // the next lines mean that if a new font is selected, then the current text state will be // applied to it as well. $this->currentFont = $this->currentBaseFont; $this->currentFontNum = $this->fonts[$this->currentFont]['fontNum']; //$this->setCurrentFont(); } return $this->currentFontNum; //return $this->numObj; } /** * sets up the current font, based on the font families, and the current text state * note that this system is quite flexible, a bold-italic font can be completely different to a * italic-bold font, and even bold-bold will have to be defined within the family to have meaning * This function is to be called whenever the currentTextState is changed, it will update * the currentFont setting to whatever the appropriatte family one is. * If the user calls selectFont themselves then that will reset the currentBaseFont, and the currentFont * This function will change the currentFont to whatever it should be, but will not change the * currentBaseFont. * * @access private */ function setCurrentFont() { // if (strlen($this->currentBaseFont) == 0){ // // then assume an initial font // $this->selectFont('./fonts/Helvetica.afm'); // } // $cf = substr($this->currentBaseFont,strrpos($this->currentBaseFont,'/')+1); // if (strlen($this->currentTextState) // && isset($this->fontFamilies[$cf]) // && isset($this->fontFamilies[$cf][$this->currentTextState])){ // // then we are in some state or another // // and this font has a family, and the current setting exists within it // // select the font, then return it // $nf = substr($this->currentBaseFont,0,strrpos($this->currentBaseFont,'/')+1).$this->fontFamilies[$cf][$this->currentTextState]; // $this->selectFont($nf,'',0); // $this->currentFont = $nf; // $this->currentFontNum = $this->fonts[$nf]['fontNum']; // } else { // // the this font must not have the right family member for the current state // // simply assume the base font $this->currentFont = $this->currentBaseFont; $this->currentFontNum = $this->fonts[$this->currentFont]['fontNum']; // } } /** * function for the user to find out what the ID is of the first page that was created during * startup - useful if they wish to add something to it later. */ function getFirstPageId() { return $this->firstPageId; } /** * add content to the currently active object * * @access private */ function addContent($content) { $this->objects[$this->currentContents]['c'].= $content; } /** * sets the colour for fill operations */ function setColor($r, $g, $b, $force = 0) { if ($r >= 0 && ($force || $r != $this->currentColour['r'] || $g != $this->currentColour['g'] || $b != $this->currentColour['b'])) { $this->objects[$this->currentContents]['c'].= "\n".sprintf('%.3f', $r) .' '.sprintf('%.3f', $g) .' '.sprintf('%.3f', $b) .' rg'; $this->currentColour = array('r' => $r, 'g' => $g, 'b' => $b); } } /** * sets the colour for stroke operations */ function setStrokeColor($r, $g, $b, $force = 0) { if ($r >= 0 && ($force || $r != $this->currentStrokeColour['r'] || $g != $this->currentStrokeColour['g'] || $b != $this->currentStrokeColour['b'])) { $this->objects[$this->currentContents]['c'].= "\n".sprintf('%.3f', $r) .' '.sprintf('%.3f', $g) .' '.sprintf('%.3f', $b) .' RG'; $this->currentStrokeColour = array('r' => $r, 'g' => $g, 'b' => $b); } } /** * Set the graphics state for compositions */ function setGraphicsState($parameters) { // Create a new graphics state object // FIXME: should actually keep track of states that have already been created... $this->numObj++; $this->o_extGState($this->numObj, 'new', $parameters); $this->objects[ $this->currentContents ]['c'].= "\n/GS" . $this->numStates . " gs"; } /** * Set current blend mode & opacity for lines. * * Valid blend modes are: * * Normal, Multiply, Screen, Overlay, Darken, Lighten, * ColorDogde, ColorBurn, HardLight, SoftLight, Difference, * Exclusion * * @param string $mode the blend mode to use * @param float $opacity 0.0 fully transparent, 1.0 fully opaque */ function setLineTransparency($mode, $opacity) { static $blend_modes = array("Normal", "Multiply", "Screen", "Overlay", "Darken", "Lighten", "ColorDogde", "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion"); if ( !in_array($mode, $blend_modes) ) $mode = "Normal"; // Only create a new graphics state if required if ( $mode == $this->currentLineTransparency["mode"] && $opacity == $this->currentLineTransparency["opacity"] ) return; $options = array("BM" => "/$mode", "CA" => (float)$opacity); $this->setGraphicsState($options); } /** * Set current blend mode & opacity for filled objects. * * Valid blend modes are: * * Normal, Multiply, Screen, Overlay, Darken, Lighten, * ColorDogde, ColorBurn, HardLight, SoftLight, Difference, * Exclusion * * @param string $mode the blend mode to use * @param float $opacity 0.0 fully transparent, 1.0 fully opaque */ function setFillTransparency($mode, $opacity) { static $blend_modes = array("Normal", "Multiply", "Screen", "Overlay", "Darken", "Lighten", "ColorDogde", "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion"); if ( !in_array($mode, $blend_modes) ) $mode = "Normal"; if ( $mode == $this->currentFillTransparency["mode"] && $opacity == $this->currentFillTransparency["opacity"] ) return; $options = array("BM" => "/$mode", "ca" => (float)$opacity); $this->setGraphicsState($options); } /** * draw a line from one set of coordinates to another */ function line($x1, $y1, $x2, $y2) { $this->objects[$this->currentContents]['c'] .= "\n".sprintf('%.3f', $x1) .' '.sprintf('%.3f', $y1) .' m '.sprintf('%.3f', $x2) .' '.sprintf('%.3f', $y2) .' l S'; } /** * draw a bezier curve based on 4 control points */ function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3) { // in the current line style, draw a bezier curve from (x0,y0) to (x3,y3) using the other two points // as the control points for the curve. $this->objects[$this->currentContents]['c'] .= "\n".sprintf('%.3f', $x0) .' '.sprintf('%.3f', $y0) .' m '.sprintf('%.3f', $x1) .' '.sprintf('%.3f', $y1); $this->objects[$this->currentContents]['c'] .= ' '.sprintf('%.3f', $x2) .' '.sprintf('%.3f', $y2) .' '.sprintf('%.3f', $x3) .' '.sprintf('%.3f', $y3) .' c S'; } /** * draw a part of an ellipse */ function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSeg = 8) { $this->ellipse($x0, $y0, $r1, $r2, $angle, $nSeg, $astart, $afinish, 0); } /** * draw a filled ellipse */ function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360) { return $this->ellipse($x0, $y0, $r1, $r2 = 0, $angle, $nSeg, $astart, $afinish, 1, 1); } /** * draw an ellipse * note that the part and filled ellipse are just special cases of this function * * draws an ellipse in the current line style * centered at $x0,$y0, radii $r1,$r2 * if $r2 is not set, then a circle is drawn * nSeg is not allowed to be less than 2, as this will simply draw a line (and will even draw a * pretty crappy shape at 2, as we are approximating with bezier curves. */ function ellipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360, $close = 1, $fill = 0) { if ($r1 == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -