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.

530 lines
15 KiB

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