2
0

Font.php 15 KB

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