File indexing completed on 2024-12-29 05:27:55
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Pdf 0017 * @subpackage Fonts 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** Internally used classes */ 0025 // require_once 'Zend/Pdf/Element/Name.php'; 0026 0027 0028 /** Zend_Pdf_Resource_Font */ 0029 // require_once 'Zend/Pdf/Resource/Font.php'; 0030 0031 /** 0032 * Adobe PDF Simple fonts implementation 0033 * 0034 * PDF simple fonts functionality is presented by Adobe Type 1 0035 * (including standard PDF Type1 built-in fonts) and TrueType fonts support. 0036 * 0037 * Both fonts have the following properties: 0038 * - Glyphs in the font are selected by single-byte character codes obtained from a 0039 * string that is shown by the text-showing operators. Logically, these codes index 0040 * into a table of 256 glyphs; the mapping from codes to glyphs is called the font’s 0041 * encoding. 0042 * PDF specification provides a possibility to specify any user defined encoding in addition 0043 * to the standard built-in encodings: Standard-Encoding, MacRomanEncoding, WinAnsiEncoding, 0044 * and PDFDocEncoding, but Zend_Pdf simple fonts implementation operates only with 0045 * Windows ANSI encoding (except Symbol and ZapfDingbats built-in fonts). 0046 * 0047 * - Each glyph has a single set of metrics, including a horizontal displacement or 0048 * width. That is, simple fonts support only horizontal writing mode. 0049 * 0050 * 0051 * The code in this class is common to both types. However, you will only deal 0052 * directly with subclasses. 0053 * 0054 * Font objects should be normally be obtained from the factory methods 0055 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}. 0056 * 0057 * @package Zend_Pdf 0058 * @subpackage Fonts 0059 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0060 * @license http://framework.zend.com/license/new-bsd New BSD License 0061 */ 0062 abstract class Zend_Pdf_Resource_Font_Simple extends Zend_Pdf_Resource_Font 0063 { 0064 /** 0065 * Object representing the font's cmap (character to glyph map). 0066 * @var Zend_Pdf_Cmap 0067 */ 0068 protected $_cmap = null; 0069 0070 /** 0071 * Array containing the widths of each of the glyphs contained in the font. 0072 * 0073 * Keys are integers starting from 0, which coresponds to Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH. 0074 * 0075 * Font character map may contain gaps for actually used glyphs, nevertheless glyphWidths array 0076 * contains widths for all glyphs even they are unused. 0077 * 0078 * @var array 0079 */ 0080 protected $_glyphWidths = null; 0081 0082 /** 0083 * Width for glyphs missed in the font 0084 * 0085 * Note: Adobe PDF specfication (V1.4 - V1.6) doesn't define behavior for rendering 0086 * characters missed in the standard PDF fonts (such us 0x7F (DEL) Windows ANSI code) 0087 * Adobe Font Metrics files doesn't also define metrics for "missed glyph". 0088 * We provide character width as "0" for this case, but actually it depends on PDF viewer 0089 * implementation. 0090 * 0091 * @var integer 0092 */ 0093 protected $_missingGlyphWidth = 0; 0094 0095 0096 /**** Public Interface ****/ 0097 0098 0099 /* Object Lifecycle */ 0100 0101 /** 0102 * Object constructor 0103 * 0104 */ 0105 public function __construct() 0106 { 0107 parent::__construct(); 0108 0109 /** 0110 * @todo 0111 * It's easy to add other encodings support now (Standard-Encoding, MacRomanEncoding, 0112 * PDFDocEncoding, MacExpertEncoding, Symbol, and ZapfDingbats). 0113 * Steps for the implementation: 0114 * - completely describe all PDF single byte encodings in the documentation 0115 * - implement non-WinAnsi encodings processing into encodeString()/decodeString() methods 0116 * 0117 * These encodings will be automatically supported for standard builtin PDF fonts as well 0118 * as for external fonts. 0119 */ 0120 $this->_resource->Encoding = new Zend_Pdf_Element_Name('WinAnsiEncoding'); 0121 } 0122 0123 /** 0124 * Returns an array of glyph numbers corresponding to the Unicode characters. 0125 * 0126 * If a particular character doesn't exist in this font, the special 'missing 0127 * character glyph' will be substituted. 0128 * 0129 * See also {@link glyphNumberForCharacter()}. 0130 * 0131 * @param array $characterCodes Array of Unicode character codes (code points). 0132 * @return array Array of glyph numbers. 0133 */ 0134 public function glyphNumbersForCharacters($characterCodes) 0135 { 0136 return $this->_cmap->glyphNumbersForCharacters($characterCodes); 0137 } 0138 0139 /** 0140 * Returns the glyph number corresponding to the Unicode character. 0141 * 0142 * If a particular character doesn't exist in this font, the special 'missing 0143 * character glyph' will be substituted. 0144 * 0145 * See also {@link glyphNumbersForCharacters()} which is optimized for bulk 0146 * operations. 0147 * 0148 * @param integer $characterCode Unicode character code (code point). 0149 * @return integer Glyph number. 0150 */ 0151 public function glyphNumberForCharacter($characterCode) 0152 { 0153 return $this->_cmap->glyphNumberForCharacter($characterCode); 0154 } 0155 0156 /** 0157 * Returns a number between 0 and 1 inclusive that indicates the percentage 0158 * of characters in the string which are covered by glyphs in this font. 0159 * 0160 * Since no one font will contain glyphs for the entire Unicode character 0161 * range, this method can be used to help locate a suitable font when the 0162 * actual contents of the string are not known. 0163 * 0164 * Note that some fonts lie about the characters they support. Additionally, 0165 * fonts don't usually contain glyphs for control characters such as tabs 0166 * and line breaks, so it is rare that you will get back a full 1.0 score. 0167 * The resulting value should be considered informational only. 0168 * 0169 * @param string $string 0170 * @param string $charEncoding (optional) Character encoding of source text. 0171 * If omitted, uses 'current locale'. 0172 * @return float 0173 */ 0174 public function getCoveredPercentage($string, $charEncoding = '') 0175 { 0176 /* Convert the string to UTF-16BE encoding so we can match the string's 0177 * character codes to those found in the cmap. 0178 */ 0179 if ($charEncoding != 'UTF-16BE') { 0180 if (PHP_OS != 'AIX') { // AIX doesnt know what UTF-16BE is 0181 $string = iconv($charEncoding, 'UTF-16BE', $string); 0182 } 0183 } 0184 0185 $charCount = (PHP_OS != 'AIX') ? iconv_strlen($string, 'UTF-16BE') : strlen($string); 0186 if ($charCount == 0) { 0187 return 0; 0188 } 0189 0190 /* Fetch the covered character code list from the font's cmap. 0191 */ 0192 $coveredCharacters = $this->_cmap->getCoveredCharacters(); 0193 0194 /* Calculate the score by doing a lookup for each character. 0195 */ 0196 $score = 0; 0197 $maxIndex = strlen($string); 0198 for ($i = 0; $i < $maxIndex; $i++) { 0199 /** 0200 * @todo Properly handle characters encoded as surrogate pairs. 0201 */ 0202 $charCode = (ord($string[$i]) << 8) | ord($string[++$i]); 0203 /* This could probably be optimized a bit with a binary search... 0204 */ 0205 if (in_array($charCode, $coveredCharacters)) { 0206 $score++; 0207 } 0208 } 0209 return $score / $charCount; 0210 } 0211 0212 /** 0213 * Returns the widths of the glyphs. 0214 * 0215 * The widths are expressed in the font's glyph space. You are responsible 0216 * for converting to user space as necessary. See {@link unitsPerEm()}. 0217 * 0218 * See also {@link widthForGlyph()}. 0219 * 0220 * @param array &$glyphNumbers Array of glyph numbers. 0221 * @return array Array of glyph widths (integers). 0222 */ 0223 public function widthsForGlyphs($glyphNumbers) 0224 { 0225 $widths = array(); 0226 foreach ($glyphNumbers as $key => $glyphNumber) { 0227 if (!isset($this->_glyphWidths[$glyphNumber])) { 0228 $widths[$key] = $this->_missingGlyphWidth; 0229 } else { 0230 $widths[$key] = $this->_glyphWidths[$glyphNumber]; 0231 } 0232 } 0233 return $widths; 0234 } 0235 0236 /** 0237 * Returns the width of the glyph. 0238 * 0239 * Like {@link widthsForGlyphs()} but used for one glyph at a time. 0240 * 0241 * @param integer $glyphNumber 0242 * @return integer 0243 */ 0244 public function widthForGlyph($glyphNumber) 0245 { 0246 if (!isset($this->_glyphWidths[$glyphNumber])) { 0247 return $this->_missingGlyphWidth; 0248 } 0249 return $this->_glyphWidths[$glyphNumber]; 0250 } 0251 0252 /** 0253 * Convert string to the font encoding. 0254 * 0255 * The method is used to prepare string for text drawing operators 0256 * 0257 * @param string $string 0258 * @param string $charEncoding Character encoding of source text. 0259 * @return string 0260 */ 0261 public function encodeString($string, $charEncoding) 0262 { 0263 if (PHP_OS == 'AIX') { 0264 return $string; // returning here b/c AIX doesnt know what CP1252 is 0265 } 0266 0267 return iconv($charEncoding, 'CP1252//IGNORE', $string); 0268 } 0269 0270 /** 0271 * Convert string from the font encoding. 0272 * 0273 * The method is used to convert strings retrieved from existing content streams 0274 * 0275 * @param string $string 0276 * @param string $charEncoding Character encoding of resulting text. 0277 * @return string 0278 */ 0279 public function decodeString($string, $charEncoding) 0280 { 0281 return iconv('CP1252', $charEncoding, $string); 0282 } 0283 }