File indexing completed on 2024-12-22 05:36:56
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 /** 0025 * Abstract helper class for {@link Zend_Pdf_Resource_Font} which manages font 0026 * character maps. 0027 * 0028 * Defines the public interface for concrete subclasses which are responsible 0029 * for mapping Unicode characters to the font's glyph numbers. Also provides 0030 * shared utility methods. 0031 * 0032 * Cmap objects should ordinarily be obtained through the factory method 0033 * {@link cmapWithTypeData()}. 0034 * 0035 * The supported character map types are those found in the OpenType spec. For 0036 * additional detail on the internal binary format of these tables, see: 0037 * <ul> 0038 * <li>{@link http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6cmap.html} 0039 * <li>{@link http://www.microsoft.com/OpenType/OTSpec/cmap.htm} 0040 * <li>{@link http://partners.adobe.com/public/developer/opentype/index_cmap.html} 0041 * </ul> 0042 * 0043 * @todo Write code for Zend_Pdf_FontCmap_HighByteMapping class. 0044 * @todo Write code for Zend_Pdf_FontCmap_MixedCoverage class. 0045 * @todo Write code for Zend_Pdf_FontCmap_TrimmedArray class. 0046 * @todo Write code for Zend_Pdf_FontCmap_SegmentedCoverage class. 0047 * 0048 * @package Zend_Pdf 0049 * @subpackage Fonts 0050 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0051 * @license http://framework.zend.com/license/new-bsd New BSD License 0052 */ 0053 abstract class Zend_Pdf_Cmap 0054 { 0055 /**** Class Constants ****/ 0056 0057 0058 /* Cmap Table Types */ 0059 0060 /** 0061 * Byte Encoding character map table type. 0062 */ 0063 const TYPE_BYTE_ENCODING = 0x00; 0064 0065 /** 0066 * High Byte Mapping character map table type. 0067 */ 0068 const TYPE_HIGH_BYTE_MAPPING = 0x02; 0069 0070 /** 0071 * Segment Value to Delta Mapping character map table type. 0072 */ 0073 const TYPE_SEGMENT_TO_DELTA = 0x04; 0074 0075 /** 0076 * Trimmed Table character map table type. 0077 */ 0078 const TYPE_TRIMMED_TABLE = 0x06; 0079 0080 /** 0081 * Mixed Coverage character map table type. 0082 */ 0083 const TYPE_MIXED_COVERAGE = 0x08; 0084 0085 /** 0086 * Trimmed Array character map table type. 0087 */ 0088 const TYPE_TRIMMED_ARRAY = 0x0a; 0089 0090 /** 0091 * Segmented Coverage character map table type. 0092 */ 0093 const TYPE_SEGMENTED_COVERAGE = 0x0c; 0094 0095 /** 0096 * Static Byte Encoding character map table type. Variant of 0097 * {@link TYPE_BYTEENCODING}. 0098 */ 0099 const TYPE_BYTE_ENCODING_STATIC = 0xf1; 0100 0101 /** 0102 * Unknown character map table type. 0103 */ 0104 const TYPE_UNKNOWN = 0xff; 0105 0106 0107 /* Special Glyph Names */ 0108 0109 /** 0110 * Glyph representing missing characters. 0111 */ 0112 const MISSING_CHARACTER_GLYPH = 0x00; 0113 0114 0115 0116 /**** Public Interface ****/ 0117 0118 0119 /* Factory Methods */ 0120 0121 /** 0122 * Instantiates the appropriate concrete subclass based on the type of cmap 0123 * table and returns the instance. 0124 * 0125 * The cmap type must be one of the following values: 0126 * <ul> 0127 * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING} 0128 * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING_STATIC} 0129 * <li>{@link Zend_Pdf_Cmap::TYPE_HIGH_BYTE_MAPPING} 0130 * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENT_TO_DELTA} 0131 * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE} 0132 * <li>{@link Zend_Pdf_Cmap::TYPE_MIXED_COVERAGE} 0133 * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_ARRAY} 0134 * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENTED_COVERAGE} 0135 * </ul> 0136 * 0137 * Throws an exception if the table type is invalid or the cmap table data 0138 * cannot be validated. 0139 * 0140 * @param integer $cmapType Type of cmap. 0141 * @param mixed $cmapData Cmap table data. Usually a string or array. 0142 * @return Zend_Pdf_Cmap 0143 * @throws Zend_Pdf_Exception 0144 */ 0145 public static function cmapWithTypeData($cmapType, $cmapData) 0146 { 0147 switch ($cmapType) { 0148 case Zend_Pdf_Cmap::TYPE_BYTE_ENCODING: 0149 // require_once 'Zend/Pdf/Cmap/ByteEncoding.php'; 0150 return new Zend_Pdf_Cmap_ByteEncoding($cmapData); 0151 0152 case Zend_Pdf_Cmap::TYPE_BYTE_ENCODING_STATIC: 0153 // require_once 'Zend/Pdf/Cmap/ByteEncoding/Static.php'; 0154 return new Zend_Pdf_Cmap_ByteEncoding_Static($cmapData); 0155 0156 case Zend_Pdf_Cmap::TYPE_HIGH_BYTE_MAPPING: 0157 // require_once 'Zend/Pdf/Exception.php'; 0158 throw new Zend_Pdf_Exception('High byte mapping cmap currently unsupported', 0159 Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED); 0160 0161 case Zend_Pdf_Cmap::TYPE_SEGMENT_TO_DELTA: 0162 // require_once 'Zend/Pdf/Cmap/SegmentToDelta.php'; 0163 return new Zend_Pdf_Cmap_SegmentToDelta($cmapData); 0164 0165 case Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE: 0166 // require_once 'Zend/Pdf/Cmap/TrimmedTable.php'; 0167 return new Zend_Pdf_Cmap_TrimmedTable($cmapData); 0168 0169 case Zend_Pdf_Cmap::TYPE_MIXED_COVERAGE: 0170 // require_once 'Zend/Pdf/Exception.php'; 0171 throw new Zend_Pdf_Exception('Mixed coverage cmap currently unsupported', 0172 Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED); 0173 0174 case Zend_Pdf_Cmap::TYPE_TRIMMED_ARRAY: 0175 // require_once 'Zend/Pdf/Exception.php'; 0176 throw new Zend_Pdf_Exception('Trimmed array cmap currently unsupported', 0177 Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED); 0178 0179 case Zend_Pdf_Cmap::TYPE_SEGMENTED_COVERAGE: 0180 // require_once 'Zend/Pdf/Exception.php'; 0181 throw new Zend_Pdf_Exception('Segmented coverage cmap currently unsupported', 0182 Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED); 0183 0184 default: 0185 // require_once 'Zend/Pdf/Exception.php'; 0186 throw new Zend_Pdf_Exception("Unknown cmap type: $cmapType", 0187 Zend_Pdf_Exception::CMAP_UNKNOWN_TYPE); 0188 } 0189 } 0190 0191 0192 /* Abstract Methods */ 0193 0194 /** 0195 * Object constructor 0196 * 0197 * Parses the raw binary table data. Throws an exception if the table is 0198 * malformed. 0199 * 0200 * @param string $cmapData Raw binary cmap table data. 0201 * @throws Zend_Pdf_Exception 0202 */ 0203 abstract public function __construct($cmapData); 0204 0205 /** 0206 * Returns an array of glyph numbers corresponding to the Unicode characters. 0207 * 0208 * If a particular character doesn't exist in this font, the special 'missing 0209 * character glyph' will be substituted. 0210 * 0211 * See also {@link glyphNumberForCharacter()}. 0212 * 0213 * @param array $characterCodes Array of Unicode character codes (code points). 0214 * @return array Array of glyph numbers. 0215 */ 0216 abstract public function glyphNumbersForCharacters($characterCodes); 0217 0218 /** 0219 * Returns the glyph number corresponding to the Unicode character. 0220 * 0221 * If a particular character doesn't exist in this font, the special 'missing 0222 * character glyph' will be substituted. 0223 * 0224 * See also {@link glyphNumbersForCharacters()} which is optimized for bulk 0225 * operations. 0226 * 0227 * @param integer $characterCode Unicode character code (code point). 0228 * @return integer Glyph number. 0229 */ 0230 abstract public function glyphNumberForCharacter($characterCode); 0231 0232 /** 0233 * Returns an array containing the Unicode characters that have entries in 0234 * this character map. 0235 * 0236 * @return array Unicode character codes. 0237 */ 0238 abstract public function getCoveredCharacters(); 0239 0240 /** 0241 * Returns an array containing the glyphs numbers that have entries in this character map. 0242 * Keys are Unicode character codes (integers) 0243 * 0244 * This functionality is partially covered by glyphNumbersForCharacters(getCoveredCharacters()) 0245 * call, but this method do it in more effective way (prepare complete list instead of searching 0246 * glyph for each character code). 0247 * 0248 * @internal 0249 * @return array Array representing <Unicode character code> => <glyph number> pairs. 0250 */ 0251 abstract public function getCoveredCharactersGlyphs(); 0252 0253 0254 /**** Internal Methods ****/ 0255 0256 0257 /* Internal Utility Methods */ 0258 0259 /** 0260 * Extracts a signed 2-byte integer from a string. 0261 * 0262 * Integers are always big-endian. Throws an exception if the index is out 0263 * of range. 0264 * 0265 * @param string &$data 0266 * @param integer $index Position in string of integer. 0267 * @return integer 0268 * @throws Zend_Pdf_Exception 0269 */ 0270 protected function _extractInt2(&$data, $index) 0271 { 0272 if (($index < 0) | (($index + 1) > strlen($data))) { 0273 // require_once 'Zend/Pdf/Exception.php'; 0274 throw new Zend_Pdf_Exception("Index out of range: $index", 0275 Zend_Pdf_Exception::INDEX_OUT_OF_RANGE); 0276 } 0277 $number = ord($data[$index]); 0278 if (($number & 0x80) == 0x80) { // negative 0279 $number = ~((((~ $number) & 0xff) << 8) | ((~ ord($data[++$index])) & 0xff)); 0280 } else { 0281 $number = ($number << 8) | ord($data[++$index]); 0282 } 0283 return $number; 0284 } 0285 0286 /** 0287 * Extracts an unsigned 2-byte integer from a string. 0288 * 0289 * Integers are always big-endian. Throws an exception if the index is out 0290 * of range. 0291 * 0292 * @param string &$data 0293 * @param integer $index Position in string of integer. 0294 * @return integer 0295 * @throws Zend_Pdf_Exception 0296 */ 0297 protected function _extractUInt2(&$data, $index) 0298 { 0299 if (($index < 0) | (($index + 1) > strlen($data))) { 0300 // require_once 'Zend/Pdf/Exception.php'; 0301 throw new Zend_Pdf_Exception("Index out of range: $index", 0302 Zend_Pdf_Exception::INDEX_OUT_OF_RANGE); 0303 } 0304 $number = (ord($data[$index]) << 8) | ord($data[++$index]); 0305 return $number; 0306 } 0307 0308 /** 0309 * Extracts an unsigned 4-byte integer from a string. 0310 * 0311 * Integers are always big-endian. Throws an exception if the index is out 0312 * of range. 0313 * 0314 * NOTE: If you ask for a 4-byte unsigned integer on a 32-bit machine, the 0315 * resulting value WILL BE SIGNED because PHP uses signed integers internally 0316 * for everything. To guarantee portability, be sure to use bitwise or 0317 * similar operators on large integers! 0318 * 0319 * @param string &$data 0320 * @param integer $index Position in string of integer. 0321 * @return integer 0322 * @throws Zend_Pdf_Exception 0323 */ 0324 protected function _extractUInt4(&$data, $index) 0325 { 0326 if (($index < 0) | (($index + 3) > strlen($data))) { 0327 // require_once 'Zend/Pdf/Exception.php'; 0328 throw new Zend_Pdf_Exception("Index out of range: $index", 0329 Zend_Pdf_Exception::INDEX_OUT_OF_RANGE); 0330 } 0331 $number = (ord($data[$index]) << 24) | (ord($data[++$index]) << 16) | 0332 (ord($data[++$index]) << 8) | ord($data[++$index]); 0333 return $number; 0334 } 0335 0336 }