PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/devblocks/libs/ZendFramework/Zend/Pdf/Resource/Font.php

https://github.com/sluther/portsensor
PHP | 580 lines | 160 code | 63 blank | 357 comment | 22 complexity | e340879526a12ac39fbd03636a27c987 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  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. * @package Zend_Pdf
  16. * @subpackage Fonts
  17. * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. */
  20. /** Zend_Pdf_Resource */
  21. require_once 'Zend/Pdf/Resource.php';
  22. /** Zend_Pdf_Exception */
  23. require_once 'Zend/Pdf/Exception.php';
  24. /** Zend_Pdf_Cmap */
  25. require_once 'Zend/Pdf/Cmap.php';
  26. /**
  27. * Abstract class which manages PDF fonts.
  28. *
  29. * Defines the public interface and creates shared storage for concrete
  30. * subclasses which are responsible for generating the font's information
  31. * dictionaries, mapping characters to glyphs, and providing both overall font
  32. * and glyph-specific metric data.
  33. *
  34. * Font objects should be normally be obtained from the factory methods
  35. * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}.
  36. *
  37. * @package Zend_Pdf
  38. * @subpackage Fonts
  39. * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  40. * @license http://framework.zend.com/license/new-bsd New BSD License
  41. */
  42. abstract class Zend_Pdf_Resource_Font extends Zend_Pdf_Resource
  43. {
  44. /**** Instance Variables ****/
  45. /**
  46. * Object representing the font's cmap (character to glyph map).
  47. * @var Zend_Pdf_Cmap
  48. */
  49. public $cmap = null;
  50. /**
  51. * The type of font. Use TYPE_ constants defined in {@link Zend_Pdf_Font}.
  52. * @var integer
  53. */
  54. protected $_fontType = Zend_Pdf_Font::TYPE_UNKNOWN;
  55. /**
  56. * Array containing descriptive names for the font. See {@link fontName()}.
  57. * @var array
  58. */
  59. protected $_fontNames = array();
  60. /**
  61. * Flag indicating whether or not this font is bold.
  62. * @var boolean
  63. */
  64. protected $_isBold = false;
  65. /**
  66. * Flag indicating whether or not this font is italic.
  67. * @var boolean
  68. */
  69. protected $_isItalic = false;
  70. /**
  71. * Flag indicating whether or not this font is monospaced.
  72. * @var boolean
  73. */
  74. protected $_isMonospace = false;
  75. /**
  76. * The position below the text baseline of the underline (in glyph units).
  77. * @var integer
  78. */
  79. protected $_underlinePosition = 0;
  80. /**
  81. * The thickness of the underline (in glyph units).
  82. * @var integer
  83. */
  84. protected $_underlineThickness = 0;
  85. /**
  86. * The position above the text baseline of the strikethrough (in glyph units).
  87. * @var integer
  88. */
  89. protected $_strikePosition = 0;
  90. /**
  91. * The thickness of the strikethrough (in glyph units).
  92. * @var integer
  93. */
  94. protected $_strikeThickness = 0;
  95. /**
  96. * Number of glyph units per em. See {@link getUnitsPerEm()}.
  97. * @var integer
  98. */
  99. protected $_unitsPerEm = 0;
  100. /**
  101. * Typographical ascent. See {@link getAscent()}.
  102. * @var integer
  103. */
  104. protected $_ascent = 0;
  105. /**
  106. * Typographical descent. See {@link getDescent()}.
  107. * @var integer
  108. */
  109. protected $_descent = 0;
  110. /**
  111. * Typographical line gap. See {@link getLineGap()}.
  112. * @var integer
  113. */
  114. protected $_lineGap = 0;
  115. /**
  116. * Array containing the widths of each of the glyphs contained in the font.
  117. * @var array
  118. */
  119. protected $_glyphWidths = null;
  120. /**
  121. * The highest integer index in the glyph widths array.
  122. * @var integer
  123. */
  124. protected $_glyphMaxIndex = 0;
  125. /**
  126. * Font embedding options. See discussion in {@link __construct()}.
  127. * @var integer
  128. */
  129. private $_embeddingOptions = 0;
  130. /**** Public Interface ****/
  131. /* Object Lifecycle */
  132. /**
  133. * Object constructor.
  134. *
  135. * The $embeddingOptions parameter allows you to set certain flags related
  136. * to font embedding. You may combine options by OR-ing them together. See
  137. * the EMBED_ constants defined in {@link Zend_Pdf_Font} for the list of
  138. * available options and their descriptions.
  139. *
  140. * @param integer $embeddingOptions (optional) Options for font embedding.
  141. * Only used for certain font types.
  142. */
  143. public function __construct($embeddingOptions = 0)
  144. {
  145. parent::__construct(new Zend_Pdf_Element_Dictionary());
  146. $this->_resource->Type = new Zend_Pdf_Element_Name('Font');
  147. $this->_embeddingOptions = $embeddingOptions;
  148. }
  149. /* Object Magic Methods */
  150. /**
  151. * Returns the full name of the font in the encoding method of the current
  152. * locale. Transliterates any characters that cannot be naturally
  153. * represented in that character set.
  154. *
  155. * @return string
  156. */
  157. public function __toString()
  158. {
  159. return $this->getFontName(Zend_Pdf_Font::NAME_FULL, '', '//TRANSLIT');
  160. }
  161. /* Accessors */
  162. /**
  163. * Returns the type of font.
  164. *
  165. * @return integer One of the TYPE_ constants defined in
  166. * {@link Zend_Pdf_Font}.
  167. */
  168. public function getFontType()
  169. {
  170. return $this->_fontType;
  171. }
  172. /**
  173. * Returns the specified descriptive name for the font.
  174. *
  175. * The font name type is usually one of the following:
  176. * <ul>
  177. * <li>{@link Zend_Pdf_Font::NAME_FULL}
  178. * <li>{@link Zend_Pdf_Font::NAME_FAMILY}
  179. * <li>{@link Zend_Pdf_Font::NAME_PREFERRED_FAMILY}
  180. * <li>{@link Zend_Pdf_Font::NAME_STYLE}
  181. * <li>{@link Zend_Pdf_Font::NAME_PREFERRED_STYLE}
  182. * <li>{@link Zend_Pdf_Font::NAME_DESCRIPTION}
  183. * <li>{@link Zend_Pdf_Font::NAME_SAMPLE_TEXT}
  184. * <li>{@link Zend_Pdf_Font::NAME_ID}
  185. * <li>{@link Zend_Pdf_Font::NAME_VERSION}
  186. * <li>{@link Zend_Pdf_Font::NAME_POSTSCRIPT}
  187. * <li>{@link Zend_Pdf_Font::NAME_CID_NAME}
  188. * <li>{@link Zend_Pdf_Font::NAME_DESIGNER}
  189. * <li>{@link Zend_Pdf_Font::NAME_DESIGNER_URL}
  190. * <li>{@link Zend_Pdf_Font::NAME_MANUFACTURER}
  191. * <li>{@link Zend_Pdf_Font::NAME_VENDOR_URL}
  192. * <li>{@link Zend_Pdf_Font::NAME_COPYRIGHT}
  193. * <li>{@link Zend_Pdf_Font::NAME_TRADEMARK}
  194. * <li>{@link Zend_Pdf_Font::NAME_LICENSE}
  195. * <li>{@link Zend_Pdf_Font::NAME_LICENSE_URL}
  196. * </ul>
  197. *
  198. * Note that not all names are available for all fonts. In addition, some
  199. * fonts may contain additional names, whose indicies are in the range
  200. * 256 to 32767 inclusive, which are used for certain font layout features.
  201. *
  202. * If the preferred language translation is not available, uses the first
  203. * available translation for the name, which is usually English.
  204. *
  205. * If the requested name does not exist, returns null.
  206. *
  207. * All names are stored internally as Unicode strings, using UTF-16BE
  208. * encoding. You may optionally supply a different resulting character set.
  209. *
  210. * @param integer $nameType Type of name requested.
  211. * @param mixed $language Preferred language (string) or array of languages
  212. * in preferred order. Use the ISO 639 standard 2-letter language codes.
  213. * @param string $characterSet (optional) Desired resulting character set.
  214. * You may use any character set supported by {@link iconv()};
  215. * @return string
  216. */
  217. public function getFontName($nameType, $language, $characterSet = null)
  218. {
  219. if (! isset($this->_fontNames[$nameType])) {
  220. return null;
  221. }
  222. $name = null;
  223. if (is_array($language)) {
  224. foreach ($language as $code) {
  225. if (isset($this->_fontNames[$nameType][$code])) {
  226. $name = $this->_fontNames[$nameType][$code];
  227. break;
  228. }
  229. }
  230. } else {
  231. if (isset($this->_fontNames[$nameType][$language])) {
  232. $name = $this->_fontNames[$nameType][$language];
  233. }
  234. }
  235. /* If the preferred language could not be found, use whatever is first.
  236. */
  237. if (is_null($name)) {
  238. $name = reset($this->_fontNames[$nameType]);
  239. }
  240. /* Convert the character set if requested.
  241. */
  242. if ((! is_null($characterSet)) && ($characterSet != 'UTF-16BE')) {
  243. $name = iconv('UTF-16BE', $characterSet, $name);
  244. }
  245. return $name;
  246. }
  247. /**
  248. * Returns the suggested position below the text baseline of the underline
  249. * in glyph units.
  250. *
  251. * This value is usually negative.
  252. *
  253. * @return integer
  254. */
  255. public function getUnderlinePosition()
  256. {
  257. return $this->_underlinePosition;
  258. }
  259. /**
  260. * Returns the suggested line thickness of the underline in glyph units.
  261. *
  262. * @return integer
  263. */
  264. public function getUnderlineThickness()
  265. {
  266. return $this->_underlineThickness;
  267. }
  268. /**
  269. * Returns the suggested position above the text baseline of the
  270. * strikethrough in glyph units.
  271. *
  272. * @return integer
  273. */
  274. public function getStrikePosition()
  275. {
  276. return $this->_strikePosition;
  277. }
  278. /**
  279. * Returns the suggested line thickness of the strikethrough in glyph units.
  280. *
  281. * @return integer
  282. */
  283. public function getStrikeThickness()
  284. {
  285. return $this->_strikeThickness;
  286. }
  287. /**
  288. * Returns the number of glyph units per em.
  289. *
  290. * Used to convert glyph space to user space. Frequently used in conjunction
  291. * with {@link widthsForGlyphs()} to calculate the with of a run of text.
  292. *
  293. * @return integer
  294. */
  295. public function getUnitsPerEm()
  296. {
  297. return $this->_unitsPerEm;
  298. }
  299. /**
  300. * Returns the typographic ascent in font glyph units.
  301. *
  302. * The typographic ascent is the distance from the font's baseline to the
  303. * top of the text frame. It is frequently used to locate the initial
  304. * baseline for a paragraph of text inside a given rectangle.
  305. *
  306. * @return integer
  307. */
  308. public function getAscent()
  309. {
  310. return $this->_ascent;
  311. }
  312. /**
  313. * Returns the typographic descent in font glyph units.
  314. *
  315. * The typographic descent is the distance below the font's baseline to the
  316. * bottom of the text frame. It is always negative.
  317. *
  318. * @return integer
  319. */
  320. public function getDescent()
  321. {
  322. return $this->_descent;
  323. }
  324. /**
  325. * Returns the typographic line gap in font glyph units.
  326. *
  327. * The typographic line gap is the distance between the bottom of the text
  328. * frame of one line to the top of the text frame of the next. It is
  329. * typically combined with the typographical ascent and descent to determine
  330. * the font's total line height (or leading).
  331. *
  332. * @return integer
  333. */
  334. public function getLineGap()
  335. {
  336. return $this->_lineGap;
  337. }
  338. /**
  339. * Returns the suggested line height (or leading) in font glyph units.
  340. *
  341. * This value is determined by adding together the values of the typographic
  342. * ascent, descent, and line gap. This value yields the suggested line
  343. * spacing as determined by the font developer.
  344. *
  345. * It should be noted that this is only a guideline; layout engines will
  346. * frequently modify this value to achieve special effects such as double-
  347. * spacing.
  348. *
  349. * @return integer
  350. */
  351. public function getLineHeight()
  352. {
  353. return $this->_ascent - $this->_descent + $this->_lineGap;
  354. }
  355. /* Information and Conversion Methods */
  356. /**
  357. * Returns a number between 0 and 1 inclusive that indicates the percentage
  358. * of characters in the string which are covered by glyphs in this font.
  359. *
  360. * Since no one font will contain glyphs for the entire Unicode character
  361. * range, this method can be used to help locate a suitable font when the
  362. * actual contents of the string are not known.
  363. *
  364. * Note that some fonts lie about the characters they support. Additionally,
  365. * fonts don't usually contain glyphs for control characters such as tabs
  366. * and line breaks, so it is rare that you will get back a full 1.0 score.
  367. * The resulting value should be considered informational only.
  368. *
  369. * @param string $string
  370. * @param string $charEncoding (optional) Character encoding of source text.
  371. * If omitted, uses 'current locale'.
  372. * @return float
  373. */
  374. public function getCoveredPercentage($string, $charEncoding = '')
  375. {
  376. /* Convert the string to UTF-16BE encoding so we can match the string's
  377. * character codes to those found in the cmap.
  378. */
  379. if ($charEncoding != 'UTF-16BE') {
  380. $string = iconv($charEncoding, 'UTF-16BE', $string);
  381. }
  382. $charCount = iconv_strlen($string, 'UTF-16BE');
  383. if ($charCount == 0) {
  384. return 0;
  385. }
  386. /* Fetch the covered character code list from the font's cmap.
  387. */
  388. $coveredCharacters = $this->cmap->getCoveredCharacters();
  389. /* Calculate the score by doing a lookup for each character.
  390. */
  391. $score = 0;
  392. $maxIndex = strlen($string);
  393. for ($i = 0; $i < $maxIndex; $i++) {
  394. /**
  395. * @todo Properly handle characters encoded as surrogate pairs.
  396. */
  397. $charCode = (ord($string[$i]) << 8) | ord($string[++$i]);
  398. /* This could probably be optimized a bit with a binary search...
  399. */
  400. if (in_array($charCode, $coveredCharacters)) {
  401. $score++;
  402. }
  403. }
  404. return $score / $charCount;
  405. }
  406. /**
  407. * Returns the widths of the glyphs.
  408. *
  409. * The widths are expressed in the font's glyph space. You are responsible
  410. * for converting to user space as necessary. See {@link unitsPerEm()}.
  411. *
  412. * Throws an exception if the glyph number is out of range.
  413. *
  414. * See also {@link widthForGlyph()}.
  415. *
  416. * @param array &$glyphNumbers Array of glyph numbers.
  417. * @return array Array of glyph widths (integers).
  418. * @throws Zend_Pdf_Exception
  419. */
  420. public function widthsForGlyphs(&$glyphNumbers)
  421. {
  422. $widths = array();
  423. foreach ($glyphNumbers as $key => $glyphNumber) {
  424. if (($glyphNumber < 0) || ($glyphNumber > $this->_glyphMaxIndex)) {
  425. throw new Zend_Pdf_Exception("Glyph number is out of range: $glyphNumber",
  426. Zend_Pdf_Exception::GLYPH_OUT_OF_RANGE);
  427. }
  428. $widths[$key] = $this->_glyphWidths[$glyphNumber];
  429. }
  430. return $widths;
  431. }
  432. /**
  433. * Returns the width of the glyph.
  434. *
  435. * Like {@link widthsForGlyphs()} but used for one glyph at a time.
  436. *
  437. * @param integer $glyphNumber
  438. * @return integer
  439. * @throws Zend_Pdf_Exception
  440. */
  441. public function widthForGlyph($glyphNumber)
  442. {
  443. if (($glyphNumber < 0) || ($glyphNumber > $this->_glyphMaxIndex)) {
  444. throw new Zend_Pdf_Exception("Glyph number is out of range: $glyphNumber",
  445. Zend_Pdf_Exception::GLYPH_OUT_OF_RANGE);
  446. }
  447. return $this->_glyphWidths[$glyphNumber];
  448. }
  449. /**
  450. * Convert string from local encoding to Windows ANSI encoding.
  451. *
  452. * NOTE: This method may disappear in a future revision of the framework
  453. * once the font subsetting and Unicode support code is complete. At that
  454. * point, there may be multiple ways of encoding strings depending on
  455. * intended usage. You should treat this method as framework internal
  456. * use only.
  457. *
  458. * @param string $string
  459. * @param string $charEncoding Character encoding of source text.
  460. * @return string
  461. */
  462. public function encodeString($string, $charEncoding)
  463. {
  464. /* The $charEncoding paramater will go away once the remainder of the
  465. * layout code is completed. At that point, all strings will be handled
  466. * internally as UTF-16BE-encoded...
  467. */
  468. return iconv($charEncoding, 'CP1252//IGNORE', $string);
  469. }
  470. /**
  471. * Convert string from Windows ANSI encoding to local encoding.
  472. *
  473. * NOTE: This method may disappear in a future revision of the framework
  474. * once the font subsetting and Unicode support code is complete. At that
  475. * point, there may be multiple ways of encoding strings depending on
  476. * intended usage. You should treat this method as framework internal
  477. * use only.
  478. *
  479. * @param string $string
  480. * @param string $charEncoding Character encoding of resulting text.
  481. * @return string
  482. */
  483. public function decodeString($string, $charEncoding)
  484. {
  485. return iconv('CP1252', $charEncoding, $string);
  486. }
  487. /**** Internal Methods ****/
  488. /**
  489. * If the font's glyph space is not 1000 units per em, converts the value.
  490. *
  491. * @param integer $value
  492. * @return integer
  493. */
  494. protected function _toEmSpace($value)
  495. {
  496. if ($this->_unitsPerEm == 1000) {
  497. return $value;
  498. }
  499. return ceil(($value / $this->_unitsPerEm) * 1000); // always round up
  500. }
  501. /**
  502. * Returns true if the embedding option has been set for this font.
  503. *
  504. * The embedding options are stored as a bitfield. Multiple options may be
  505. * set at the same time.
  506. *
  507. * This is only used by certain subclasses.
  508. *
  509. * @param integer $embeddingOption
  510. * @return boolean
  511. */
  512. protected function _isEmbeddingOptionSet($embeddingOption)
  513. {
  514. $isSet = (($this->_embeddingOptions & $embeddingOption) == $embeddingOption);
  515. return $isSet;
  516. }
  517. }