2
0

Font.php 15 KB

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