You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
7.7 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  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-2014 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /** Zend_Pdf_Cmap */
  23. // require_once 'Zend/Pdf/Cmap.php';
  24. /**
  25. * Implements the "trimmed table mapping" character map (type 6).
  26. *
  27. * This table type is preferred over the {@link Zend_Pdf_Cmap_SegmentToDelta}
  28. * table when the Unicode characters covered by the font fall into a single
  29. * contiguous range.
  30. *
  31. * @package Zend_Pdf
  32. * @subpackage Fonts
  33. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  34. * @license http://framework.zend.com/license/new-bsd New BSD License
  35. */
  36. class Zend_Pdf_Cmap_TrimmedTable extends Zend_Pdf_Cmap
  37. {
  38. /**** Instance Variables ****/
  39. /**
  40. * The starting character code covered by this table.
  41. * @var integer
  42. */
  43. protected $_startCode = 0;
  44. /**
  45. * The ending character code covered by this table.
  46. * @var integer
  47. */
  48. protected $_endCode = 0;
  49. /**
  50. * Glyph index array. Stores the actual glyph numbers.
  51. * @var array
  52. */
  53. protected $_glyphIndexArray = array();
  54. /**** Public Interface ****/
  55. /* Concrete Class Implementation */
  56. /**
  57. * Returns an array of glyph numbers corresponding to the Unicode characters.
  58. *
  59. * If a particular character doesn't exist in this font, the special 'missing
  60. * character glyph' will be substituted.
  61. *
  62. * See also {@link glyphNumberForCharacter()}.
  63. *
  64. * @param array $characterCodes Array of Unicode character codes (code points).
  65. * @return array Array of glyph numbers.
  66. */
  67. public function glyphNumbersForCharacters($characterCodes)
  68. {
  69. $glyphNumbers = array();
  70. foreach ($characterCodes as $key => $characterCode) {
  71. if (($characterCode < $this->_startCode) || ($characterCode > $this->_endCode)) {
  72. $glyphNumbers[$key] = Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH;
  73. continue;
  74. }
  75. $glyphIndex = $characterCode - $this->_startCode;
  76. $glyphNumbers[$key] = $this->_glyphIndexArray[$glyphIndex];
  77. }
  78. return $glyphNumbers;
  79. }
  80. /**
  81. * Returns the glyph number corresponding to the Unicode character.
  82. *
  83. * If a particular character doesn't exist in this font, the special 'missing
  84. * character glyph' will be substituted.
  85. *
  86. * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
  87. * operations.
  88. *
  89. * @param integer $characterCode Unicode character code (code point).
  90. * @return integer Glyph number.
  91. */
  92. public function glyphNumberForCharacter($characterCode)
  93. {
  94. if (($characterCode < $this->_startCode) || ($characterCode > $this->_endCode)) {
  95. return Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH;
  96. }
  97. $glyphIndex = $characterCode - $this->_startCode;
  98. return $this->_glyphIndexArray[$glyphIndex];
  99. }
  100. /**
  101. * Returns an array containing the Unicode characters that have entries in
  102. * this character map.
  103. *
  104. * @return array Unicode character codes.
  105. */
  106. public function getCoveredCharacters()
  107. {
  108. $characterCodes = array();
  109. for ($code = $this->_startCode; $code <= $this->_endCode; $code++) {
  110. $characterCodes[] = $code;
  111. }
  112. return $characterCodes;
  113. }
  114. /**
  115. * Returns an array containing the glyphs numbers that have entries in this character map.
  116. * Keys are Unicode character codes (integers)
  117. *
  118. * This functionality is partially covered by glyphNumbersForCharacters(getCoveredCharacters())
  119. * call, but this method do it in more effective way (prepare complete list instead of searching
  120. * glyph for each character code).
  121. *
  122. * @internal
  123. * @return array Array representing <Unicode character code> => <glyph number> pairs.
  124. */
  125. public function getCoveredCharactersGlyphs()
  126. {
  127. $glyphNumbers = array();
  128. for ($code = $this->_startCode; $code <= $this->_endCode; $code++) {
  129. $glyphNumbers[$code] = $this->_glyphIndexArray[$code - $this->_startCode];
  130. }
  131. return $glyphNumbers;
  132. }
  133. /* Object Lifecycle */
  134. /**
  135. * Object constructor
  136. *
  137. * Parses the raw binary table data. Throws an exception if the table is
  138. * malformed.
  139. *
  140. * @param string $cmapData Raw binary cmap table data.
  141. * @throws Zend_Pdf_Exception
  142. */
  143. public function __construct($cmapData)
  144. {
  145. /* Sanity check: The table should be at least 9 bytes in size.
  146. */
  147. $actualLength = strlen($cmapData);
  148. if ($actualLength < 9) {
  149. // require_once 'Zend/Pdf/Exception.php';
  150. throw new Zend_Pdf_Exception('Insufficient table data',
  151. Zend_Pdf_Exception::CMAP_TABLE_DATA_TOO_SMALL);
  152. }
  153. /* Sanity check: Make sure this is right data for this table type.
  154. */
  155. $type = $this->_extractUInt2($cmapData, 0);
  156. if ($type != Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE) {
  157. // require_once 'Zend/Pdf/Exception.php';
  158. throw new Zend_Pdf_Exception('Wrong cmap table type',
  159. Zend_Pdf_Exception::CMAP_WRONG_TABLE_TYPE);
  160. }
  161. $length = $this->_extractUInt2($cmapData, 2);
  162. if ($length != $actualLength) {
  163. // require_once 'Zend/Pdf/Exception.php';
  164. throw new Zend_Pdf_Exception("Table length ($length) does not match actual length ($actualLength)",
  165. Zend_Pdf_Exception::CMAP_WRONG_TABLE_LENGTH);
  166. }
  167. /* Mapping tables should be language-independent. The font may not work
  168. * as expected if they are not. Unfortunately, many font files in the
  169. * wild incorrectly record a language ID in this field, so we can't
  170. * call this a failure.
  171. */
  172. $language = $this->_extractUInt2($cmapData, 4);
  173. if ($language != 0) {
  174. // Record a warning here somehow?
  175. }
  176. $this->_startCode = $this->_extractUInt2($cmapData, 6);
  177. $entryCount = $this->_extractUInt2($cmapData, 8);
  178. $expectedCount = ($length - 10) >> 1;
  179. if ($entryCount != $expectedCount) {
  180. // require_once 'Zend/Pdf/Exception.php';
  181. throw new Zend_Pdf_Exception("Entry count is wrong; expected: $expectedCount; actual: $entryCount",
  182. Zend_Pdf_Exception::CMAP_WRONG_ENTRY_COUNT);
  183. }
  184. $this->_endCode = $this->_startCode + $entryCount - 1;
  185. $offset = 10;
  186. for ($i = 0; $i < $entryCount; $i++, $offset += 2) {
  187. $this->_glyphIndexArray[] = $this->_extractUInt2($cmapData, $offset);
  188. }
  189. /* Sanity check: After reading all of the data, we should be at the end
  190. * of the table.
  191. */
  192. if ($offset != $length) {
  193. // require_once 'Zend/Pdf/Exception.php';
  194. throw new Zend_Pdf_Exception("Ending offset ($offset) does not match length ($length)",
  195. Zend_Pdf_Exception::CMAP_FINAL_OFFSET_NOT_LENGTH);
  196. }
  197. }
  198. }