PageRenderTime 36ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Pdf/Cmap.php

https://bitbucket.org/jfrubiom/zendframework-1.x
PHP | 336 lines | 92 code | 45 blank | 199 comment | 7 complexity | f1be7f3750dd43b760d3758cfef02167 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-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Cmap.php 24593 2012-01-05 20:35:02Z matthew $
  21. */
  22. /**
  23. * Abstract helper class for {@link Zend_Pdf_Resource_Font} which manages font
  24. * character maps.
  25. *
  26. * Defines the public interface for concrete subclasses which are responsible
  27. * for mapping Unicode characters to the font's glyph numbers. Also provides
  28. * shared utility methods.
  29. *
  30. * Cmap objects should ordinarily be obtained through the factory method
  31. * {@link cmapWithTypeData()}.
  32. *
  33. * The supported character map types are those found in the OpenType spec. For
  34. * additional detail on the internal binary format of these tables, see:
  35. * <ul>
  36. * <li>{@link http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6cmap.html}
  37. * <li>{@link http://www.microsoft.com/OpenType/OTSpec/cmap.htm}
  38. * <li>{@link http://partners.adobe.com/public/developer/opentype/index_cmap.html}
  39. * </ul>
  40. *
  41. * @todo Write code for Zend_Pdf_FontCmap_HighByteMapping class.
  42. * @todo Write code for Zend_Pdf_FontCmap_MixedCoverage class.
  43. * @todo Write code for Zend_Pdf_FontCmap_TrimmedArray class.
  44. * @todo Write code for Zend_Pdf_FontCmap_SegmentedCoverage class.
  45. *
  46. * @package Zend_Pdf
  47. * @subpackage Fonts
  48. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  49. * @license http://framework.zend.com/license/new-bsd New BSD License
  50. */
  51. abstract class Zend_Pdf_Cmap
  52. {
  53. /**** Class Constants ****/
  54. /* Cmap Table Types */
  55. /**
  56. * Byte Encoding character map table type.
  57. */
  58. const TYPE_BYTE_ENCODING = 0x00;
  59. /**
  60. * High Byte Mapping character map table type.
  61. */
  62. const TYPE_HIGH_BYTE_MAPPING = 0x02;
  63. /**
  64. * Segment Value to Delta Mapping character map table type.
  65. */
  66. const TYPE_SEGMENT_TO_DELTA = 0x04;
  67. /**
  68. * Trimmed Table character map table type.
  69. */
  70. const TYPE_TRIMMED_TABLE = 0x06;
  71. /**
  72. * Mixed Coverage character map table type.
  73. */
  74. const TYPE_MIXED_COVERAGE = 0x08;
  75. /**
  76. * Trimmed Array character map table type.
  77. */
  78. const TYPE_TRIMMED_ARRAY = 0x0a;
  79. /**
  80. * Segmented Coverage character map table type.
  81. */
  82. const TYPE_SEGMENTED_COVERAGE = 0x0c;
  83. /**
  84. * Static Byte Encoding character map table type. Variant of
  85. * {@link TYPE_BYTEENCODING}.
  86. */
  87. const TYPE_BYTE_ENCODING_STATIC = 0xf1;
  88. /**
  89. * Unknown character map table type.
  90. */
  91. const TYPE_UNKNOWN = 0xff;
  92. /* Special Glyph Names */
  93. /**
  94. * Glyph representing missing characters.
  95. */
  96. const MISSING_CHARACTER_GLYPH = 0x00;
  97. /**** Public Interface ****/
  98. /* Factory Methods */
  99. /**
  100. * Instantiates the appropriate concrete subclass based on the type of cmap
  101. * table and returns the instance.
  102. *
  103. * The cmap type must be one of the following values:
  104. * <ul>
  105. * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING}
  106. * <li>{@link Zend_Pdf_Cmap::TYPE_BYTE_ENCODING_STATIC}
  107. * <li>{@link Zend_Pdf_Cmap::TYPE_HIGH_BYTE_MAPPING}
  108. * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENT_TO_DELTA}
  109. * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE}
  110. * <li>{@link Zend_Pdf_Cmap::TYPE_MIXED_COVERAGE}
  111. * <li>{@link Zend_Pdf_Cmap::TYPE_TRIMMED_ARRAY}
  112. * <li>{@link Zend_Pdf_Cmap::TYPE_SEGMENTED_COVERAGE}
  113. * </ul>
  114. *
  115. * Throws an exception if the table type is invalid or the cmap table data
  116. * cannot be validated.
  117. *
  118. * @param integer $cmapType Type of cmap.
  119. * @param mixed $cmapData Cmap table data. Usually a string or array.
  120. * @return Zend_Pdf_Cmap
  121. * @throws Zend_Pdf_Exception
  122. */
  123. public static function cmapWithTypeData($cmapType, $cmapData)
  124. {
  125. switch ($cmapType) {
  126. case Zend_Pdf_Cmap::TYPE_BYTE_ENCODING:
  127. require_once 'Zend/Pdf/Cmap/ByteEncoding.php';
  128. return new Zend_Pdf_Cmap_ByteEncoding($cmapData);
  129. case Zend_Pdf_Cmap::TYPE_BYTE_ENCODING_STATIC:
  130. require_once 'Zend/Pdf/Cmap/ByteEncoding/Static.php';
  131. return new Zend_Pdf_Cmap_ByteEncoding_Static($cmapData);
  132. case Zend_Pdf_Cmap::TYPE_HIGH_BYTE_MAPPING:
  133. require_once 'Zend/Pdf/Exception.php';
  134. throw new Zend_Pdf_Exception('High byte mapping cmap currently unsupported',
  135. Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED);
  136. case Zend_Pdf_Cmap::TYPE_SEGMENT_TO_DELTA:
  137. require_once 'Zend/Pdf/Cmap/SegmentToDelta.php';
  138. return new Zend_Pdf_Cmap_SegmentToDelta($cmapData);
  139. case Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE:
  140. require_once 'Zend/Pdf/Cmap/TrimmedTable.php';
  141. return new Zend_Pdf_Cmap_TrimmedTable($cmapData);
  142. case Zend_Pdf_Cmap::TYPE_MIXED_COVERAGE:
  143. require_once 'Zend/Pdf/Exception.php';
  144. throw new Zend_Pdf_Exception('Mixed coverage cmap currently unsupported',
  145. Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED);
  146. case Zend_Pdf_Cmap::TYPE_TRIMMED_ARRAY:
  147. require_once 'Zend/Pdf/Exception.php';
  148. throw new Zend_Pdf_Exception('Trimmed array cmap currently unsupported',
  149. Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED);
  150. case Zend_Pdf_Cmap::TYPE_SEGMENTED_COVERAGE:
  151. require_once 'Zend/Pdf/Exception.php';
  152. throw new Zend_Pdf_Exception('Segmented coverage cmap currently unsupported',
  153. Zend_Pdf_Exception::CMAP_TYPE_UNSUPPORTED);
  154. default:
  155. require_once 'Zend/Pdf/Exception.php';
  156. throw new Zend_Pdf_Exception("Unknown cmap type: $cmapType",
  157. Zend_Pdf_Exception::CMAP_UNKNOWN_TYPE);
  158. }
  159. }
  160. /* Abstract Methods */
  161. /**
  162. * Object constructor
  163. *
  164. * Parses the raw binary table data. Throws an exception if the table is
  165. * malformed.
  166. *
  167. * @param string $cmapData Raw binary cmap table data.
  168. * @throws Zend_Pdf_Exception
  169. */
  170. abstract public function __construct($cmapData);
  171. /**
  172. * Returns an array of glyph numbers corresponding to the Unicode characters.
  173. *
  174. * If a particular character doesn't exist in this font, the special 'missing
  175. * character glyph' will be substituted.
  176. *
  177. * See also {@link glyphNumberForCharacter()}.
  178. *
  179. * @param array $characterCodes Array of Unicode character codes (code points).
  180. * @return array Array of glyph numbers.
  181. */
  182. abstract public function glyphNumbersForCharacters($characterCodes);
  183. /**
  184. * Returns the glyph number corresponding to the Unicode character.
  185. *
  186. * If a particular character doesn't exist in this font, the special 'missing
  187. * character glyph' will be substituted.
  188. *
  189. * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
  190. * operations.
  191. *
  192. * @param integer $characterCode Unicode character code (code point).
  193. * @return integer Glyph number.
  194. */
  195. abstract public function glyphNumberForCharacter($characterCode);
  196. /**
  197. * Returns an array containing the Unicode characters that have entries in
  198. * this character map.
  199. *
  200. * @return array Unicode character codes.
  201. */
  202. abstract public function getCoveredCharacters();
  203. /**
  204. * Returns an array containing the glyphs numbers that have entries in this character map.
  205. * Keys are Unicode character codes (integers)
  206. *
  207. * This functionality is partially covered by glyphNumbersForCharacters(getCoveredCharacters())
  208. * call, but this method do it in more effective way (prepare complete list instead of searching
  209. * glyph for each character code).
  210. *
  211. * @internal
  212. * @return array Array representing <Unicode character code> => <glyph number> pairs.
  213. */
  214. abstract public function getCoveredCharactersGlyphs();
  215. /**** Internal Methods ****/
  216. /* Internal Utility Methods */
  217. /**
  218. * Extracts a signed 2-byte integer from a string.
  219. *
  220. * Integers are always big-endian. Throws an exception if the index is out
  221. * of range.
  222. *
  223. * @param string &$data
  224. * @param integer $index Position in string of integer.
  225. * @return integer
  226. * @throws Zend_Pdf_Exception
  227. */
  228. protected function _extractInt2(&$data, $index)
  229. {
  230. if (($index < 0) | (($index + 1) > strlen($data))) {
  231. require_once 'Zend/Pdf/Exception.php';
  232. throw new Zend_Pdf_Exception("Index out of range: $index",
  233. Zend_Pdf_Exception::INDEX_OUT_OF_RANGE);
  234. }
  235. $number = ord($data[$index]);
  236. if (($number & 0x80) == 0x80) { // negative
  237. $number = ~((((~ $number) & 0xff) << 8) | ((~ ord($data[++$index])) & 0xff));
  238. } else {
  239. $number = ($number << 8) | ord($data[++$index]);
  240. }
  241. return $number;
  242. }
  243. /**
  244. * Extracts an unsigned 2-byte integer from a string.
  245. *
  246. * Integers are always big-endian. Throws an exception if the index is out
  247. * of range.
  248. *
  249. * @param string &$data
  250. * @param integer $index Position in string of integer.
  251. * @return integer
  252. * @throws Zend_Pdf_Exception
  253. */
  254. protected function _extractUInt2(&$data, $index)
  255. {
  256. if (($index < 0) | (($index + 1) > strlen($data))) {
  257. require_once 'Zend/Pdf/Exception.php';
  258. throw new Zend_Pdf_Exception("Index out of range: $index",
  259. Zend_Pdf_Exception::INDEX_OUT_OF_RANGE);
  260. }
  261. $number = (ord($data[$index]) << 8) | ord($data[++$index]);
  262. return $number;
  263. }
  264. /**
  265. * Extracts an unsigned 4-byte integer from a string.
  266. *
  267. * Integers are always big-endian. Throws an exception if the index is out
  268. * of range.
  269. *
  270. * NOTE: If you ask for a 4-byte unsigned integer on a 32-bit machine, the
  271. * resulting value WILL BE SIGNED because PHP uses signed integers internally
  272. * for everything. To guarantee portability, be sure to use bitwise or
  273. * similar operators on large integers!
  274. *
  275. * @param string &$data
  276. * @param integer $index Position in string of integer.
  277. * @return integer
  278. * @throws Zend_Pdf_Exception
  279. */
  280. protected function _extractUInt4(&$data, $index)
  281. {
  282. if (($index < 0) | (($index + 3) > strlen($data))) {
  283. require_once 'Zend/Pdf/Exception.php';
  284. throw new Zend_Pdf_Exception("Index out of range: $index",
  285. Zend_Pdf_Exception::INDEX_OUT_OF_RANGE);
  286. }
  287. $number = (ord($data[$index]) << 24) | (ord($data[++$index]) << 16) |
  288. (ord($data[++$index]) << 8) | ord($data[++$index]);
  289. return $number;
  290. }
  291. }