2
0

Font.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  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_FileParserDataSource */
  23. require_once 'Zend/Pdf/FileParserDataSource.php';
  24. /** Zend_Pdf_FileParserDataSource_File */
  25. require_once 'Zend/Pdf/FileParserDataSource/File.php';
  26. /** Zend_Pdf_FileParserDataSource_String */
  27. require_once 'Zend/Pdf/FileParserDataSource/String.php';
  28. /** Zend_Pdf_FileParser_Font_OpenType_TrueType */
  29. require_once 'Zend/Pdf/FileParser/Font/OpenType/TrueType.php';
  30. /** Zend_Pdf_Resource_Font_Simple_Parsed_TrueType */
  31. require_once 'Zend/Pdf/Resource/Font/Simple/Parsed/TrueType.php';
  32. /** Zend_Pdf_Resource_Font_Type0 */
  33. require_once 'Zend/Pdf/Resource/Font/Type0.php';
  34. /** Zend_Pdf_Resource_Font_CidFont_TrueType */
  35. require_once 'Zend/Pdf/Resource/Font/CidFont/TrueType.php';
  36. /** Zend_Pdf_Resource_Font_Simple_Standard_Courier */
  37. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/Courier.php';
  38. /** Zend_Pdf_Resource_Font_Simple_Standard_CourierBold */
  39. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/CourierBold.php';
  40. /** Zend_Pdf_Resource_Font_Simple_Standard_CourierBoldOblique */
  41. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/CourierBoldOblique.php';
  42. /** Zend_Pdf_Resource_Font_Simple_Standard_CourierOblique */
  43. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/CourierOblique.php';
  44. /** Zend_Pdf_Resource_Font_Simple_Standard_Helvetica */
  45. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/Helvetica.php';
  46. /** Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBold */
  47. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/HelveticaBold.php';
  48. /** Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBoldOblique */
  49. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/HelveticaBoldOblique.php';
  50. /** Zend_Pdf_Resource_Font_Simple_Standard_HelveticaOblique */
  51. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/HelveticaOblique.php';
  52. /** Zend_Pdf_Resource_Font_Simple_Standard_Symbol */
  53. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/Symbol.php';
  54. /** Zend_Pdf_Resource_Font_Simple_Standard_TimesBold */
  55. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/TimesBold.php';
  56. /** Zend_Pdf_Resource_Font_Simple_Standard_TimesBoldItalic */
  57. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/TimesBoldItalic.php';
  58. /** Zend_Pdf_Resource_Font_Simple_Standard_TimesItalic */
  59. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/TimesItalic.php';
  60. /** Zend_Pdf_Resource_Font_Simple_Standard_TimesRoman */
  61. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/TimesRoman.php';
  62. /** Zend_Pdf_Resource_Font_Simple_Standard_ZapfDingbats */
  63. require_once 'Zend/Pdf/Resource/Font/Simple/Standard/ZapfDingbats.php';
  64. /** Zend_Pdf_Resource_Font_Extracted */
  65. require_once 'Zend/Pdf/Resource/Font/Extracted.php';
  66. /**
  67. * Abstract factory class which vends {@link Zend_Pdf_Resource_Font} objects.
  68. *
  69. * Font objects themselves are normally instantiated through the factory methods
  70. * {@link fontWithName()} or {@link fontWithPath()}.
  71. *
  72. * This class is also the home for font-related constants because the name of
  73. * the true base class ({@link Zend_Pdf_Resource_Font}) is not intuitive for the
  74. * end user.
  75. *
  76. * @package Zend_Pdf
  77. * @subpackage Fonts
  78. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  79. * @license http://framework.zend.com/license/new-bsd New BSD License
  80. */
  81. abstract class Zend_Pdf_Font
  82. {
  83. /**** Class Constants ****/
  84. /* Font Types */
  85. /**
  86. * Unknown font type.
  87. */
  88. const TYPE_UNKNOWN = 0;
  89. /**
  90. * One of the standard 14 PDF fonts.
  91. */
  92. const TYPE_STANDARD = 1;
  93. /**
  94. * A PostScript Type 1 font.
  95. */
  96. const TYPE_TYPE_1 = 2;
  97. /**
  98. * A TrueType font or an OpenType font containing TrueType outlines.
  99. */
  100. const TYPE_TRUETYPE = 3;
  101. /**
  102. * Type 0 composite font.
  103. */
  104. const TYPE_TYPE_0 = 4;
  105. /**
  106. * CID font containing a PostScript Type 1 font.
  107. * These fonts are used only to construct Type 0 composite fonts and can't be used directly
  108. */
  109. const TYPE_CIDFONT_TYPE_0 = 5;
  110. /**
  111. * CID font containing a TrueType font or an OpenType font containing TrueType outlines.
  112. * These fonts are used only to construct Type 0 composite fonts and can't be used directly
  113. */
  114. const TYPE_CIDFONT_TYPE_2 = 6;
  115. /* Names of the Standard 14 PDF Fonts */
  116. /**
  117. * Name of the standard PDF font Courier.
  118. */
  119. const FONT_COURIER = 'Courier';
  120. /**
  121. * Name of the bold style of the standard PDF font Courier.
  122. */
  123. const FONT_COURIER_BOLD = 'Courier-Bold';
  124. /**
  125. * Name of the italic style of the standard PDF font Courier.
  126. */
  127. const FONT_COURIER_OBLIQUE = 'Courier-Oblique';
  128. /**
  129. * Convenience constant for a common misspelling of
  130. * {@link FONT_COURIER_OBLIQUE}.
  131. */
  132. const FONT_COURIER_ITALIC = 'Courier-Oblique';
  133. /**
  134. * Name of the bold and italic style of the standard PDF font Courier.
  135. */
  136. const FONT_COURIER_BOLD_OBLIQUE = 'Courier-BoldOblique';
  137. /**
  138. * Convenience constant for a common misspelling of
  139. * {@link FONT_COURIER_BOLD_OBLIQUE}.
  140. */
  141. const FONT_COURIER_BOLD_ITALIC = 'Courier-BoldOblique';
  142. /**
  143. * Name of the standard PDF font Helvetica.
  144. */
  145. const FONT_HELVETICA = 'Helvetica';
  146. /**
  147. * Name of the bold style of the standard PDF font Helvetica.
  148. */
  149. const FONT_HELVETICA_BOLD = 'Helvetica-Bold';
  150. /**
  151. * Name of the italic style of the standard PDF font Helvetica.
  152. */
  153. const FONT_HELVETICA_OBLIQUE = 'Helvetica-Oblique';
  154. /**
  155. * Convenience constant for a common misspelling of
  156. * {@link FONT_HELVETICA_OBLIQUE}.
  157. */
  158. const FONT_HELVETICA_ITALIC = 'Helvetica-Oblique';
  159. /**
  160. * Name of the bold and italic style of the standard PDF font Helvetica.
  161. */
  162. const FONT_HELVETICA_BOLD_OBLIQUE = 'Helvetica-BoldOblique';
  163. /**
  164. * Convenience constant for a common misspelling of
  165. * {@link FONT_HELVETICA_BOLD_OBLIQUE}.
  166. */
  167. const FONT_HELVETICA_BOLD_ITALIC = 'Helvetica-BoldOblique';
  168. /**
  169. * Name of the standard PDF font Symbol.
  170. */
  171. const FONT_SYMBOL = 'Symbol';
  172. /**
  173. * Name of the standard PDF font Times.
  174. */
  175. const FONT_TIMES_ROMAN = 'Times-Roman';
  176. /**
  177. * Convenience constant for a common misspelling of
  178. * {@link FONT_TIMES_ROMAN}.
  179. */
  180. const FONT_TIMES = 'Times-Roman';
  181. /**
  182. * Name of the bold style of the standard PDF font Times.
  183. */
  184. const FONT_TIMES_BOLD = 'Times-Bold';
  185. /**
  186. * Name of the italic style of the standard PDF font Times.
  187. */
  188. const FONT_TIMES_ITALIC = 'Times-Italic';
  189. /**
  190. * Name of the bold and italic style of the standard PDF font Times.
  191. */
  192. const FONT_TIMES_BOLD_ITALIC = 'Times-BoldItalic';
  193. /**
  194. * Name of the standard PDF font Zapf Dingbats.
  195. */
  196. const FONT_ZAPFDINGBATS = 'ZapfDingbats';
  197. /* Font Name String Types */
  198. /**
  199. * Full copyright notice for the font.
  200. */
  201. const NAME_COPYRIGHT = 0;
  202. /**
  203. * Font family name. Used to group similar styles of fonts together.
  204. */
  205. const NAME_FAMILY = 1;
  206. /**
  207. * Font style within the font family. Examples: Regular, Italic, Bold, etc.
  208. */
  209. const NAME_STYLE = 2;
  210. /**
  211. * Unique font identifier.
  212. */
  213. const NAME_ID = 3;
  214. /**
  215. * Full font name. Usually a combination of the {@link NAME_FAMILY} and
  216. * {@link NAME_STYLE} strings.
  217. */
  218. const NAME_FULL = 4;
  219. /**
  220. * Version number of the font.
  221. */
  222. const NAME_VERSION = 5;
  223. /**
  224. * PostScript name for the font. This is the name used to identify fonts
  225. * internally and within the PDF file.
  226. */
  227. const NAME_POSTSCRIPT = 6;
  228. /**
  229. * Font trademark notice. This is distinct from the {@link NAME_COPYRIGHT}.
  230. */
  231. const NAME_TRADEMARK = 7;
  232. /**
  233. * Name of the font manufacturer.
  234. */
  235. const NAME_MANUFACTURER = 8;
  236. /**
  237. * Name of the designer of the font.
  238. */
  239. const NAME_DESIGNER = 9;
  240. /**
  241. * Description of the font. May contain revision information, usage
  242. * recommendations, features, etc.
  243. */
  244. const NAME_DESCRIPTION = 10;
  245. /**
  246. * URL of the font vendor. Some fonts may contain a unique serial number
  247. * embedded in this URL, which is used for licensing.
  248. */
  249. const NAME_VENDOR_URL = 11;
  250. /**
  251. * URL of the font designer ({@link NAME_DESIGNER}).
  252. */
  253. const NAME_DESIGNER_URL = 12;
  254. /**
  255. * Plain language licensing terms for the font.
  256. */
  257. const NAME_LICENSE = 13;
  258. /**
  259. * URL of more detailed licensing information for the font.
  260. */
  261. const NAME_LICENSE_URL = 14;
  262. /**
  263. * Preferred font family. Used by some fonts to work around a Microsoft
  264. * Windows limitation where only four fonts styles can share the same
  265. * {@link NAME_FAMILY} value.
  266. */
  267. const NAME_PREFERRED_FAMILY = 16;
  268. /**
  269. * Preferred font style. A more descriptive string than {@link NAME_STYLE}.
  270. */
  271. const NAME_PREFERRED_STYLE = 17;
  272. /**
  273. * Suggested text to use as a representative sample of the font.
  274. */
  275. const NAME_SAMPLE_TEXT = 19;
  276. /**
  277. * PostScript CID findfont name.
  278. */
  279. const NAME_CID_NAME = 20;
  280. /* Font Weights */
  281. /**
  282. * Thin font weight.
  283. */
  284. const WEIGHT_THIN = 100;
  285. /**
  286. * Extra-light (Ultra-light) font weight.
  287. */
  288. const WEIGHT_EXTRA_LIGHT = 200;
  289. /**
  290. * Light font weight.
  291. */
  292. const WEIGHT_LIGHT = 300;
  293. /**
  294. * Normal (Regular) font weight.
  295. */
  296. const WEIGHT_NORMAL = 400;
  297. /**
  298. * Medium font weight.
  299. */
  300. const WEIGHT_MEDIUM = 500;
  301. /**
  302. * Semi-bold (Demi-bold) font weight.
  303. */
  304. const WEIGHT_SEMI_BOLD = 600;
  305. /**
  306. * Bold font weight.
  307. */
  308. const WEIGHT_BOLD = 700;
  309. /**
  310. * Extra-bold (Ultra-bold) font weight.
  311. */
  312. const WEIGHT_EXTRA_BOLD = 800;
  313. /**
  314. * Black (Heavy) font weight.
  315. */
  316. const WEIGHT_BLACK = 900;
  317. /* Font Widths */
  318. /**
  319. * Ultra-condensed font width. Typically 50% of normal.
  320. */
  321. const WIDTH_ULTRA_CONDENSED = 1;
  322. /**
  323. * Extra-condensed font width. Typically 62.5% of normal.
  324. */
  325. const WIDTH_EXTRA_CONDENSED = 2;
  326. /**
  327. * Condensed font width. Typically 75% of normal.
  328. */
  329. const WIDTH_CONDENSED = 3;
  330. /**
  331. * Semi-condensed font width. Typically 87.5% of normal.
  332. */
  333. const WIDTH_SEMI_CONDENSED = 4;
  334. /**
  335. * Normal (Medium) font width.
  336. */
  337. const WIDTH_NORMAL = 5;
  338. /**
  339. * Semi-expanded font width. Typically 112.5% of normal.
  340. */
  341. const WIDTH_SEMI_EXPANDED = 6;
  342. /**
  343. * Expanded font width. Typically 125% of normal.
  344. */
  345. const WIDTH_EXPANDED = 7;
  346. /**
  347. * Extra-expanded font width. Typically 150% of normal.
  348. */
  349. const WIDTH_EXTRA_EXPANDED = 8;
  350. /**
  351. * Ultra-expanded font width. Typically 200% of normal.
  352. */
  353. const WIDTH_ULTRA_EXPANDED = 9;
  354. /* Font Embedding Options */
  355. /**
  356. * Do not embed the font in the PDF document.
  357. */
  358. const EMBED_DONT_EMBED = 0x01;
  359. /**
  360. * Embed, but do not subset the font in the PDF document.
  361. */
  362. const EMBED_DONT_SUBSET = 0x02;
  363. /**
  364. * Embed, but do not compress the font in the PDF document.
  365. */
  366. const EMBED_DONT_COMPRESS = 0x04;
  367. /**
  368. * Suppress the exception normally thrown if the font cannot be embedded
  369. * due to its copyright bits being set.
  370. */
  371. const EMBED_SUPPRESS_EMBED_EXCEPTION = 0x08;
  372. /**** Class Variables ****/
  373. /**
  374. * Array whose keys are the unique PostScript names of instantiated fonts.
  375. * The values are the font objects themselves.
  376. * @var array
  377. */
  378. private static $_fontNames = array();
  379. /**
  380. * Array whose keys are the md5 hash of the full paths on disk for parsed
  381. * fonts. The values are the font objects themselves.
  382. * @var array
  383. */
  384. private static $_fontFilePaths = array();
  385. /**** Public Interface ****/
  386. /* Factory Methods */
  387. /**
  388. * Returns a {@link Zend_Pdf_Resource_Font} object by full name.
  389. *
  390. * This is the preferred method to obtain one of the standard 14 PDF fonts.
  391. *
  392. * The result of this method is cached, preventing unnecessary duplication
  393. * of font objects. Repetitive calls for a font with the same name will
  394. * return the same object.
  395. *
  396. * The $embeddingOptions parameter allows you to set certain flags related
  397. * to font embedding. You may combine options by OR-ing them together. See
  398. * the EMBED_ constants defined in {@link Zend_Pdf_Font} for the list of
  399. * available options and their descriptions. Note that this value is only
  400. * used when creating a font for the first time. If a font with the same
  401. * name already exists, you will get that object and the options you specify
  402. * here will be ignored. This is because fonts are only embedded within the
  403. * PDF file once.
  404. *
  405. * If the font name supplied does not match the name of a previously
  406. * instantiated object and it is not one of the 14 standard PDF fonts, an
  407. * exception will be thrown.
  408. *
  409. * @param string $name Full PostScript name of font.
  410. * @param integer $embeddingOptions (optional) Options for font embedding.
  411. * @return Zend_Pdf_Resource_Font
  412. * @throws Zend_Pdf_Exception
  413. */
  414. public static function fontWithName($name, $embeddingOptions = 0)
  415. {
  416. /* First check the cache. Don't duplicate font objects.
  417. */
  418. if (isset(Zend_Pdf_Font::$_fontNames[$name])) {
  419. return Zend_Pdf_Font::$_fontNames[$name];
  420. }
  421. /**
  422. * @todo It would be cool to be able to have a mapping of font names to
  423. * file paths in a configuration file for frequently used custom
  424. * fonts. This would allow a user to use custom fonts without having
  425. * to hard-code file paths all over the place. Table this idea until
  426. * {@link Zend_Config} is ready.
  427. */
  428. /* Not an existing font and no mapping in the config file. Check to see
  429. * if this is one of the standard 14 PDF fonts.
  430. */
  431. switch ($name) {
  432. case Zend_Pdf_Font::FONT_COURIER:
  433. $font = new Zend_Pdf_Resource_Font_Simple_Standard_Courier();
  434. break;
  435. case Zend_Pdf_Font::FONT_COURIER_BOLD:
  436. $font = new Zend_Pdf_Resource_Font_Simple_Standard_CourierBold();
  437. break;
  438. case Zend_Pdf_Font::FONT_COURIER_OBLIQUE:
  439. $font = new Zend_Pdf_Resource_Font_Simple_Standard_CourierOblique();
  440. break;
  441. case Zend_Pdf_Font::FONT_COURIER_BOLD_OBLIQUE:
  442. $font = new Zend_Pdf_Resource_Font_Simple_Standard_CourierBoldOblique();
  443. break;
  444. case Zend_Pdf_Font::FONT_HELVETICA:
  445. $font = new Zend_Pdf_Resource_Font_Simple_Standard_Helvetica();
  446. break;
  447. case Zend_Pdf_Font::FONT_HELVETICA_BOLD:
  448. $font = new Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBold();
  449. break;
  450. case Zend_Pdf_Font::FONT_HELVETICA_OBLIQUE:
  451. $font = new Zend_Pdf_Resource_Font_Simple_Standard_HelveticaOblique();
  452. break;
  453. case Zend_Pdf_Font::FONT_HELVETICA_BOLD_OBLIQUE:
  454. $font = new Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBoldOblique();
  455. break;
  456. case Zend_Pdf_Font::FONT_SYMBOL:
  457. $font = new Zend_Pdf_Resource_Font_Simple_Standard_Symbol();
  458. break;
  459. case Zend_Pdf_Font::FONT_TIMES_ROMAN:
  460. $font = new Zend_Pdf_Resource_Font_Simple_Standard_TimesRoman();
  461. break;
  462. case Zend_Pdf_Font::FONT_TIMES_BOLD:
  463. $font = new Zend_Pdf_Resource_Font_Simple_Standard_TimesBold();
  464. break;
  465. case Zend_Pdf_Font::FONT_TIMES_ITALIC:
  466. $font = new Zend_Pdf_Resource_Font_Simple_Standard_TimesItalic();
  467. break;
  468. case Zend_Pdf_Font::FONT_TIMES_BOLD_ITALIC:
  469. $font = new Zend_Pdf_Resource_Font_Simple_Standard_TimesBoldItalic();
  470. break;
  471. case Zend_Pdf_Font::FONT_ZAPFDINGBATS:
  472. $font = new Zend_Pdf_Resource_Font_Simple_Standard_ZapfDingbats();
  473. break;
  474. default:
  475. throw new Zend_Pdf_Exception("Unknown font name: $name",
  476. Zend_Pdf_Exception::BAD_FONT_NAME);
  477. }
  478. /* Add this new font to the cache array and return it for use.
  479. */
  480. Zend_Pdf_Font::$_fontNames[$name] = $font;
  481. return $font;
  482. }
  483. /**
  484. * Returns a {@link Zend_Pdf_Resource_Font} object by file path.
  485. *
  486. * The result of this method is cached, preventing unnecessary duplication
  487. * of font objects. Repetitive calls for the font with the same path will
  488. * return the same object.
  489. *
  490. * The $embeddingOptions parameter allows you to set certain flags related
  491. * to font embedding. You may combine options by OR-ing them together. See
  492. * the EMBED_ constants defined in {@link Zend_Pdf_Font} for the list of
  493. * available options and their descriptions. Note that this value is only
  494. * used when creating a font for the first time. If a font with the same
  495. * name already exists, you will get that object and the options you specify
  496. * here will be ignored. This is because fonts are only embedded within the
  497. * PDF file once.
  498. *
  499. * If the file path supplied does not match the path of a previously
  500. * instantiated object or the font type cannot be determined, an exception
  501. * will be thrown.
  502. *
  503. * @param string $filePath Full path to the font file.
  504. * @param integer $embeddingOptions (optional) Options for font embedding.
  505. * @return Zend_Pdf_Resource_Font
  506. * @throws Zend_Pdf_Exception
  507. */
  508. public static function fontWithPath($filePath, $embeddingOptions = 0)
  509. {
  510. /* First check the cache. Don't duplicate font objects.
  511. */
  512. $filePathKey = md5($filePath);
  513. if (isset(Zend_Pdf_Font::$_fontFilePaths[$filePathKey])) {
  514. return Zend_Pdf_Font::$_fontFilePaths[$filePathKey];
  515. }
  516. /* Create a file parser data source object for this file. File path and
  517. * access permission checks are handled here.
  518. */
  519. $dataSource = new Zend_Pdf_FileParserDataSource_File($filePath);
  520. /* Attempt to determine the type of font. We can't always trust file
  521. * extensions, but try that first since it's fastest.
  522. */
  523. $fileExtension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
  524. /* If it turns out that the file is named improperly and we guess the
  525. * wrong type, we'll get null instead of a font object.
  526. */
  527. switch ($fileExtension) {
  528. case 'ttf':
  529. $font = Zend_Pdf_Font::_extractTrueTypeFont($dataSource, $embeddingOptions);
  530. break;
  531. default:
  532. /* Unrecognized extension. Try to determine the type by actually
  533. * parsing it below.
  534. */
  535. $font = null;
  536. break;
  537. }
  538. if ($font === null) {
  539. /* There was no match for the file extension or the extension was
  540. * wrong. Attempt to detect the type of font by actually parsing it.
  541. * We'll do the checks in order of most likely format to try to
  542. * reduce the detection time.
  543. */
  544. // OpenType
  545. // TrueType
  546. if (($font === null) && ($fileExtension != 'ttf')) {
  547. $font = Zend_Pdf_Font::_extractTrueTypeFont($dataSource, $embeddingOptions);
  548. }
  549. // Type 1 PostScript
  550. // Mac OS X dfont
  551. // others?
  552. }
  553. /* Done with the data source object.
  554. */
  555. $dataSource = null;
  556. if ($font !== null) {
  557. /* Parsing was successful. Add this font instance to the cache arrays
  558. * and return it for use.
  559. */
  560. $fontName = $font->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT, '', '');
  561. Zend_Pdf_Font::$_fontNames[$fontName] = $font;
  562. $filePathKey = md5($filePath);
  563. Zend_Pdf_Font::$_fontFilePaths[$filePathKey] = $font;
  564. return $font;
  565. } else {
  566. /* The type of font could not be determined. Give up.
  567. */
  568. throw new Zend_Pdf_Exception("Cannot determine font type: $filePath",
  569. Zend_Pdf_Exception::CANT_DETERMINE_FONT_TYPE);
  570. }
  571. }
  572. /**** Internal Methods ****/
  573. /* Font Extraction Methods */
  574. /**
  575. * Attempts to extract a TrueType font from the data source.
  576. *
  577. * If the font parser throws an exception that suggests the data source
  578. * simply doesn't contain a TrueType font, catches it and returns null. If
  579. * an exception is thrown that suggests the TrueType font is corrupt or
  580. * otherwise unusable, throws that exception. If successful, returns the
  581. * font object.
  582. *
  583. * @param Zend_Pdf_FileParserDataSource $dataSource
  584. * @param integer $embeddingOptions Options for font embedding.
  585. * @return Zend_Pdf_Resource_Font_OpenType_TrueType May also return null if
  586. * the data source does not appear to contain a TrueType font.
  587. * @throws Zend_Pdf_Exception
  588. */
  589. protected static function _extractTrueTypeFont($dataSource, $embeddingOptions)
  590. {
  591. try {
  592. $fontParser = new Zend_Pdf_FileParser_Font_OpenType_TrueType($dataSource);
  593. $fontParser->parse();
  594. if ($fontParser->isAdobeLatinSubset) {
  595. $font = new Zend_Pdf_Resource_Font_Simple_Parsed_TrueType($fontParser, $embeddingOptions);
  596. } else {
  597. /* Use Composite Type 0 font which supports Unicode character mapping */
  598. $cidFont = new Zend_Pdf_Resource_Font_CidFont_TrueType($fontParser, $embeddingOptions);
  599. $font = new Zend_Pdf_Resource_Font_Type0($cidFont);
  600. }
  601. } catch (Zend_Pdf_Exception $exception) {
  602. /* The following exception codes suggest that this isn't really a
  603. * TrueType font. If we caught such an exception, simply return
  604. * null. For all other cases, it probably is a TrueType font but has
  605. * a problem; throw the exception again.
  606. */
  607. $fontParser = null;
  608. switch ($exception->getCode()) {
  609. case Zend_Pdf_Exception::WRONG_FONT_TYPE: // break intentionally omitted
  610. case Zend_Pdf_Exception::BAD_TABLE_COUNT: // break intentionally omitted
  611. case Zend_Pdf_Exception::BAD_MAGIC_NUMBER:
  612. return null;
  613. default:
  614. throw $exception;
  615. }
  616. }
  617. return $font;
  618. }
  619. }