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.
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
25 * Abstract helper class for {@link Zend_Pdf_Resource_Font} which manages font
28 * Defines the public interface for concrete subclasses which are responsible
29 * for mapping Unicode characters to the font's glyph numbers. Also provides
30 * shared utility methods.
32 * Cmap objects should ordinarily be obtained through the factory method
33 * {@link cmapWithTypeData()}.
35 * The supported character map types are those found in the OpenType spec. For
36 * additional detail on the internal binary format of these tables, see:
38 * <li>{@link http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6cmap.html}
39 * <li>{@link http://www.microsoft.com/OpenType/OTSpec/cmap.htm}
40 * <li>{@link http://partners.adobe.com/public/developer/opentype/index_cmap.html}
43 * @todo Write code for Zend_Pdf_FontCmap_HighByteMapping class.
44 * @todo Write code for Zend_Pdf_FontCmap_MixedCoverage class.
45 * @todo Write code for Zend_Pdf_FontCmap_TrimmedArray class.
46 * @todo Write code for Zend_Pdf_FontCmap_SegmentedCoverage class.
50 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
51 * @license http://framework.zend.com/license/new-bsd New BSD License
53 abstract class Zend_Pdf_Cmap
55 /**** Class Constants ****/
58 /* Cmap Table Types */
61 * Byte Encoding character map table type.
63 const TYPE_BYTE_ENCODING
= 0x00;
66 * High Byte Mapping character map table type.
68 const TYPE_HIGH_BYTE_MAPPING
= 0x02;
71 * Segment Value to Delta Mapping character map table type.
73 const TYPE_SEGMENT_TO_DELTA
= 0x04;
76 * Trimmed Table character map table type.
78 const TYPE_TRIMMED_TABLE
= 0x06;
81 * Mixed Coverage character map table type.
83 const TYPE_MIXED_COVERAGE
= 0x08;
86 * Trimmed Array character map table type.
88 const TYPE_TRIMMED_ARRAY
= 0x0a;
91 * Segmented Coverage character map table type.
93 const TYPE_SEGMENTED_COVERAGE
= 0x0c;
96 * Static Byte Encoding character map table type. Variant of
97 * {@link TYPE_BYTEENCODING}.
99 const TYPE_BYTE_ENCODING_STATIC
= 0xf1;
102 * Unknown character map table type.
104 const TYPE_UNKNOWN
= 0xff;
107 /* Special Glyph Names */
110 * Glyph representing missing characters.
112 const MISSING_CHARACTER_GLYPH
= 0x00;
116 /**** Public Interface ****/
119 /* Factory Methods */
122 * Instantiates the appropriate concrete subclass based on the type of cmap
123 * table and returns the instance.
125 * The cmap type must be one of the following values:
127 * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING}
128 * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING_STATIC}
129 * <li>{@link Zend_Pdf_Cmap::TYPE_HIGH_BYTE_MAPPING}
130 * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENT_TO_DELTA}
131 * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE}
132 * <li>{@link Zend_Pdf_Cmap::TYPE_MIXED_COVERAGE}
133 * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_ARRAY}
134 * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENTED_COVERAGE}
137 * Throws an exception if the table type is invalid or the cmap table data
138 * cannot be validated.
140 * @param integer $cmapType Type of cmap.
141 * @param mixed $cmapData Cmap table data. Usually a string or array.
142 * @return Zend_Pdf_Cmap
143 * @throws Zend_Pdf_Exception
145 public static function cmapWithTypeData($cmapType, $cmapData)
148 case Zend_Pdf_Cmap
::TYPE_BYTE_ENCODING
:
149 require_once 'Zend/Pdf/Cmap/ByteEncoding.php';
150 return new Zend_Pdf_Cmap_ByteEncoding($cmapData);
152 case Zend_Pdf_Cmap
::TYPE_BYTE_ENCODING_STATIC
:
153 require_once 'Zend/Pdf/Cmap/ByteEncoding/Static.php';
154 return new Zend_Pdf_Cmap_ByteEncoding_Static($cmapData);
156 case Zend_Pdf_Cmap
::TYPE_HIGH_BYTE_MAPPING
:
157 require_once 'Zend/Pdf/Exception.php';
158 throw new Zend_Pdf_Exception('High byte mapping cmap currently unsupported',
159 Zend_Pdf_Exception
::CMAP_TYPE_UNSUPPORTED
);
161 case Zend_Pdf_Cmap
::TYPE_SEGMENT_TO_DELTA
:
162 require_once 'Zend/Pdf/Cmap/SegmentToDelta.php';
163 return new Zend_Pdf_Cmap_SegmentToDelta($cmapData);
165 case Zend_Pdf_Cmap
::TYPE_TRIMMED_TABLE
:
166 require_once 'Zend/Pdf/Cmap/TrimmedTable.php';
167 return new Zend_Pdf_Cmap_TrimmedTable($cmapData);
169 case Zend_Pdf_Cmap
::TYPE_MIXED_COVERAGE
:
170 require_once 'Zend/Pdf/Exception.php';
171 throw new Zend_Pdf_Exception('Mixed coverage cmap currently unsupported',
172 Zend_Pdf_Exception
::CMAP_TYPE_UNSUPPORTED
);
174 case Zend_Pdf_Cmap
::TYPE_TRIMMED_ARRAY
:
175 require_once 'Zend/Pdf/Exception.php';
176 throw new Zend_Pdf_Exception('Trimmed array cmap currently unsupported',
177 Zend_Pdf_Exception
::CMAP_TYPE_UNSUPPORTED
);
179 case Zend_Pdf_Cmap
::TYPE_SEGMENTED_COVERAGE
:
180 require_once 'Zend/Pdf/Exception.php';
181 throw new Zend_Pdf_Exception('Segmented coverage cmap currently unsupported',
182 Zend_Pdf_Exception
::CMAP_TYPE_UNSUPPORTED
);
185 require_once 'Zend/Pdf/Exception.php';
186 throw new Zend_Pdf_Exception("Unknown cmap type: $cmapType",
187 Zend_Pdf_Exception
::CMAP_UNKNOWN_TYPE
);
192 /* Abstract Methods */
197 * Parses the raw binary table data. Throws an exception if the table is
200 * @param string $cmapData Raw binary cmap table data.
201 * @throws Zend_Pdf_Exception
203 abstract public function __construct($cmapData);
206 * Returns an array of glyph numbers corresponding to the Unicode characters.
208 * If a particular character doesn't exist in this font, the special 'missing
209 * character glyph' will be substituted.
211 * See also {@link glyphNumberForCharacter()}.
213 * @param array $characterCodes Array of Unicode character codes (code points).
214 * @return array Array of glyph numbers.
216 abstract public function glyphNumbersForCharacters($characterCodes);
219 * Returns the glyph number corresponding to the Unicode character.
221 * If a particular character doesn't exist in this font, the special 'missing
222 * character glyph' will be substituted.
224 * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
227 * @param integer $characterCode Unicode character code (code point).
228 * @return integer Glyph number.
230 abstract public function glyphNumberForCharacter($characterCode);
233 * Returns an array containing the Unicode characters that have entries in
234 * this character map.
236 * @return array Unicode character codes.
238 abstract public function getCoveredCharacters();
241 * Returns an array containing the glyphs numbers that have entries in this character map.
242 * Keys are Unicode character codes (integers)
244 * This functionality is partially covered by glyphNumbersForCharacters(getCoveredCharacters())
245 * call, but this method do it in more effective way (prepare complete list instead of searching
246 * glyph for each character code).
249 * @return array Array representing <Unicode character code> => <glyph number> pairs.
251 abstract public function getCoveredCharactersGlyphs();
254 /**** Internal Methods ****/
257 /* Internal Utility Methods */
260 * Extracts a signed 2-byte integer from a string.
262 * Integers are always big-endian. Throws an exception if the index is out
265 * @param string &$data
266 * @param integer $index Position in string of integer.
268 * @throws Zend_Pdf_Exception
270 protected function _extractInt2(&$data, $index)
272 if (($index < 0) |
(($index +
1) > strlen($data))) {
273 require_once 'Zend/Pdf/Exception.php';
274 throw new Zend_Pdf_Exception("Index out of range: $index",
275 Zend_Pdf_Exception
::INDEX_OUT_OF_RANGE
);
277 $number = ord($data[$index]);
278 if (($number & 0x80) == 0x80) { // negative
279 $number = ~
((((~
$number) & 0xff) << 8) |
((~
ord($data[++
$index])) & 0xff));
281 $number = ($number << 8) |
ord($data[++
$index]);
287 * Extracts an unsigned 2-byte integer from a string.
289 * Integers are always big-endian. Throws an exception if the index is out
292 * @param string &$data
293 * @param integer $index Position in string of integer.
295 * @throws Zend_Pdf_Exception
297 protected function _extractUInt2(&$data, $index)
299 if (($index < 0) |
(($index +
1) > strlen($data))) {
300 require_once 'Zend/Pdf/Exception.php';
301 throw new Zend_Pdf_Exception("Index out of range: $index",
302 Zend_Pdf_Exception
::INDEX_OUT_OF_RANGE
);
304 $number = (ord($data[$index]) << 8) |
ord($data[++
$index]);
309 * Extracts an unsigned 4-byte integer from a string.
311 * Integers are always big-endian. Throws an exception if the index is out
314 * NOTE: If you ask for a 4-byte unsigned integer on a 32-bit machine, the
315 * resulting value WILL BE SIGNED because PHP uses signed integers internally
316 * for everything. To guarantee portability, be sure to use bitwise or
317 * similar operators on large integers!
319 * @param string &$data
320 * @param integer $index Position in string of integer.
322 * @throws Zend_Pdf_Exception
324 protected function _extractUInt4(&$data, $index)
326 if (($index < 0) |
(($index +
3) > strlen($data))) {
327 require_once 'Zend/Pdf/Exception.php';
328 throw new Zend_Pdf_Exception("Index out of range: $index",
329 Zend_Pdf_Exception
::INDEX_OUT_OF_RANGE
);
331 $number = (ord($data[$index]) << 24) |
(ord($data[++
$index]) << 16) |
332 (ord($data[++
$index]) << 8) |
ord($data[++
$index]);