/framework/vendor/zend/Zend/Pdf/Resource/Font/Simple.php
PHP | 283 lines | 74 code | 24 blank | 185 comment | 14 complexity | 5cd4c221ac1cbbe3d688859666b751e2 MD5 | raw file
1<?php 2/** 3 * Zend Framework 4 * 5 * LICENSE 6 * 7 * This source file is subject to the new BSD license that is bundled 8 * with this package in the file LICENSE.txt. 9 * It is also available through the world-wide-web at this URL: 10 * http://framework.zend.com/license/new-bsd 11 * If you did not receive a copy of the license and are unable to 12 * obtain it through the world-wide-web, please send an email 13 * to license@zend.com so we can send you a copy immediately. 14 * 15 * @category Zend 16 * @package Zend_Pdf 17 * @subpackage Fonts 18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 19 * @license http://framework.zend.com/license/new-bsd New BSD License 20 * @version $Id: Simple.php 20096 2010-01-06 02:05:09Z bkarwin $ 21 */ 22 23 24/** Internally used classes */ 25require_once 'Zend/Pdf/Element/Name.php'; 26 27 28/** Zend_Pdf_Resource_Font */ 29require_once 'Zend/Pdf/Resource/Font.php'; 30 31/** 32 * Adobe PDF Simple fonts implementation 33 * 34 * PDF simple fonts functionality is presented by Adobe Type 1 35 * (including standard PDF Type1 built-in fonts) and TrueType fonts support. 36 * 37 * Both fonts have the following properties: 38 * - Glyphs in the font are selected by single-byte character codes obtained from a 39 * string that is shown by the text-showing operators. Logically, these codes index 40 * into a table of 256 glyphs; the mapping from codes to glyphs is called the font̢۪s 41 * encoding. 42 * PDF specification provides a possibility to specify any user defined encoding in addition 43 * to the standard built-in encodings: Standard-Encoding, MacRomanEncoding, WinAnsiEncoding, 44 * and PDFDocEncoding, but Zend_Pdf simple fonts implementation operates only with 45 * Windows ANSI encoding (except Symbol and ZapfDingbats built-in fonts). 46 * 47 * - Each glyph has a single set of metrics, including a horizontal displacement or 48 * width. That is, simple fonts support only horizontal writing mode. 49 * 50 * 51 * The code in this class is common to both types. However, you will only deal 52 * directly with subclasses. 53 * 54 * Font objects should be normally be obtained from the factory methods 55 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}. 56 * 57 * @package Zend_Pdf 58 * @subpackage Fonts 59 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 60 * @license http://framework.zend.com/license/new-bsd New BSD License 61 */ 62abstract class Zend_Pdf_Resource_Font_Simple extends Zend_Pdf_Resource_Font 63{ 64 /** 65 * Object representing the font's cmap (character to glyph map). 66 * @var Zend_Pdf_Cmap 67 */ 68 protected $_cmap = null; 69 70 /** 71 * Array containing the widths of each of the glyphs contained in the font. 72 * 73 * Keys are integers starting from 0, which coresponds to Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH. 74 * 75 * Font character map may contain gaps for actually used glyphs, nevertheless glyphWidths array 76 * contains widths for all glyphs even they are unused. 77 * 78 * @var array 79 */ 80 protected $_glyphWidths = null; 81 82 /** 83 * Width for glyphs missed in the font 84 * 85 * Note: Adobe PDF specfication (V1.4 - V1.6) doesn't define behavior for rendering 86 * characters missed in the standard PDF fonts (such us 0x7F (DEL) Windows ANSI code) 87 * Adobe Font Metrics files doesn't also define metrics for "missed glyph". 88 * We provide character width as "0" for this case, but actually it depends on PDF viewer 89 * implementation. 90 * 91 * @var integer 92 */ 93 protected $_missingGlyphWidth = 0; 94 95 96 /**** Public Interface ****/ 97 98 99 /* Object Lifecycle */ 100 101 /** 102 * Object constructor 103 * 104 */ 105 public function __construct() 106 { 107 parent::__construct(); 108 109 /** 110 * @todo 111 * It's easy to add other encodings support now (Standard-Encoding, MacRomanEncoding, 112 * PDFDocEncoding, MacExpertEncoding, Symbol, and ZapfDingbats). 113 * Steps for the implementation: 114 * - completely describe all PDF single byte encodings in the documentation 115 * - implement non-WinAnsi encodings processing into encodeString()/decodeString() methods 116 * 117 * These encodings will be automatically supported for standard builtin PDF fonts as well 118 * as for external fonts. 119 */ 120 $this->_resource->Encoding = new Zend_Pdf_Element_Name('WinAnsiEncoding'); 121 } 122 123 /** 124 * Returns an array of glyph numbers corresponding to the Unicode characters. 125 * 126 * If a particular character doesn't exist in this font, the special 'missing 127 * character glyph' will be substituted. 128 * 129 * See also {@link glyphNumberForCharacter()}. 130 * 131 * @param array $characterCodes Array of Unicode character codes (code points). 132 * @return array Array of glyph numbers. 133 */ 134 public function glyphNumbersForCharacters($characterCodes) 135 { 136 return $this->_cmap->glyphNumbersForCharacters($characterCodes); 137 } 138 139 /** 140 * Returns the glyph number corresponding to the Unicode character. 141 * 142 * If a particular character doesn't exist in this font, the special 'missing 143 * character glyph' will be substituted. 144 * 145 * See also {@link glyphNumbersForCharacters()} which is optimized for bulk 146 * operations. 147 * 148 * @param integer $characterCode Unicode character code (code point). 149 * @return integer Glyph number. 150 */ 151 public function glyphNumberForCharacter($characterCode) 152 { 153 return $this->_cmap->glyphNumberForCharacter($characterCode); 154 } 155 156 /** 157 * Returns a number between 0 and 1 inclusive that indicates the percentage 158 * of characters in the string which are covered by glyphs in this font. 159 * 160 * Since no one font will contain glyphs for the entire Unicode character 161 * range, this method can be used to help locate a suitable font when the 162 * actual contents of the string are not known. 163 * 164 * Note that some fonts lie about the characters they support. Additionally, 165 * fonts don't usually contain glyphs for control characters such as tabs 166 * and line breaks, so it is rare that you will get back a full 1.0 score. 167 * The resulting value should be considered informational only. 168 * 169 * @param string $string 170 * @param string $charEncoding (optional) Character encoding of source text. 171 * If omitted, uses 'current locale'. 172 * @return float 173 */ 174 public function getCoveredPercentage($string, $charEncoding = '') 175 { 176 /* Convert the string to UTF-16BE encoding so we can match the string's 177 * character codes to those found in the cmap. 178 */ 179 if ($charEncoding != 'UTF-16BE') { 180 if (PHP_OS != 'AIX') { // AIX doesnt know what UTF-16BE is 181 $string = iconv($charEncoding, 'UTF-16BE', $string); 182 } 183 } 184 185 $charCount = (PHP_OS != 'AIX') ? iconv_strlen($string, 'UTF-16BE') : strlen($string); 186 if ($charCount == 0) { 187 return 0; 188 } 189 190 /* Fetch the covered character code list from the font's cmap. 191 */ 192 $coveredCharacters = $this->_cmap->getCoveredCharacters(); 193 194 /* Calculate the score by doing a lookup for each character. 195 */ 196 $score = 0; 197 $maxIndex = strlen($string); 198 for ($i = 0; $i < $maxIndex; $i++) { 199 /** 200 * @todo Properly handle characters encoded as surrogate pairs. 201 */ 202 $charCode = (ord($string[$i]) << 8) | ord($string[++$i]); 203 /* This could probably be optimized a bit with a binary search... 204 */ 205 if (in_array($charCode, $coveredCharacters)) { 206 $score++; 207 } 208 } 209 return $score / $charCount; 210 } 211 212 /** 213 * Returns the widths of the glyphs. 214 * 215 * The widths are expressed in the font's glyph space. You are responsible 216 * for converting to user space as necessary. See {@link unitsPerEm()}. 217 * 218 * See also {@link widthForGlyph()}. 219 * 220 * @param array &$glyphNumbers Array of glyph numbers. 221 * @return array Array of glyph widths (integers). 222 */ 223 public function widthsForGlyphs($glyphNumbers) 224 { 225 $widths = array(); 226 foreach ($glyphNumbers as $key => $glyphNumber) { 227 if (!isset($this->_glyphWidths[$glyphNumber])) { 228 $widths[$key] = $this->_missingGlyphWidth; 229 } else { 230 $widths[$key] = $this->_glyphWidths[$glyphNumber]; 231 } 232 } 233 return $widths; 234 } 235 236 /** 237 * Returns the width of the glyph. 238 * 239 * Like {@link widthsForGlyphs()} but used for one glyph at a time. 240 * 241 * @param integer $glyphNumber 242 * @return integer 243 */ 244 public function widthForGlyph($glyphNumber) 245 { 246 if (!isset($this->_glyphWidths[$glyphNumber])) { 247 return $this->_missingGlyphWidth; 248 } 249 return $this->_glyphWidths[$glyphNumber]; 250 } 251 252 /** 253 * Convert string to the font encoding. 254 * 255 * The method is used to prepare string for text drawing operators 256 * 257 * @param string $string 258 * @param string $charEncoding Character encoding of source text. 259 * @return string 260 */ 261 public function encodeString($string, $charEncoding) 262 { 263 if (PHP_OS == 'AIX') { 264 return $string; // returning here b/c AIX doesnt know what CP1252 is 265 } 266 267 return iconv($charEncoding, 'CP1252//IGNORE', $string); 268 } 269 270 /** 271 * Convert string from the font encoding. 272 * 273 * The method is used to convert strings retrieved from existing content streams 274 * 275 * @param string $string 276 * @param string $charEncoding Character encoding of resulting text. 277 * @return string 278 */ 279 public function decodeString($string, $charEncoding) 280 { 281 return iconv('CP1252', $charEncoding, $string); 282 } 283}