PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/include/PHPExcel/Writer/PDF/include/font_metrics.cls.php

https://bitbucket.org/ite/on-track-code-base
PHP | 335 lines | 175 code | 50 blank | 110 comment | 21 complexity | 0336321db3aae28fc213efdbe182f818 MD5 | raw file
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://www.dompdf.com/
  5. * @author Benj Carson <benjcarson@digitaljunkies.ca>
  6. * @author Helmut Tischer <htischer@weihenstephan.org>
  7. * @author Fabien Ménager <fabien.menager@gmail.com>
  8. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  9. * @version $Id: font_metrics.cls.php 469 2012-02-05 22:25:30Z fabien.menager $
  10. */
  11. require_once DOMPDF_LIB_DIR . "/class.pdf.php";
  12. require_once DOMPDF_LIB_DIR . "/php-font-lib/classes/font.cls.php";
  13. /**
  14. * Name of the font cache file
  15. *
  16. * This file must be writable by the webserver process only to update it
  17. * with save_font_families() after adding the .afm file references of a new font family
  18. * with Font_Metrics::save_font_families().
  19. * This is typically done only from command line with load_font.php on converting
  20. * ttf fonts to ufm with php-font-lib.
  21. *
  22. * Declared here because PHP5 prevents constants from being declared with expressions
  23. */
  24. if (!defined("__DOMPDF_FONT_CACHE_FILE")) {
  25. if (file_exists(DOMPDF_FONT_DIR . "dompdf_font_family_cache")) {
  26. define('__DOMPDF_FONT_CACHE_FILE', DOMPDF_FONT_DIR . "dompdf_font_family_cache");
  27. } else {
  28. define('__DOMPDF_FONT_CACHE_FILE', DOMPDF_FONT_DIR . "dompdf_font_family_cache.dist.php");
  29. }
  30. }
  31. /**
  32. * The font metrics class
  33. *
  34. * This class provides information about fonts and text. It can resolve
  35. * font names into actual installed font files, as well as determine the
  36. * size of text in a particular font and size.
  37. *
  38. * @static
  39. * @package dompdf
  40. */
  41. class Font_Metrics {
  42. /**
  43. * @see __DOMPDF_FONT_CACHE_FILE
  44. */
  45. const CACHE_FILE = __DOMPDF_FONT_CACHE_FILE;
  46. /**
  47. * Underlying {@link Canvas} object to perform text size calculations
  48. *
  49. * @var Canvas
  50. */
  51. static protected $_pdf = null;
  52. /**
  53. * Array of font family names to font files
  54. *
  55. * Usually cached by the {@link load_font.php} script
  56. *
  57. * @var array
  58. */
  59. static protected $_font_lookup = array();
  60. /**
  61. * Class initialization
  62. *
  63. */
  64. static function init(Canvas $canvas = null) {
  65. if (!self::$_pdf) {
  66. if (!$canvas) {
  67. $canvas = Canvas_Factory::get_instance();
  68. }
  69. self::$_pdf = $canvas;
  70. }
  71. }
  72. /**
  73. * Calculates text size, in points
  74. *
  75. * @param string $text the text to be sized
  76. * @param string $font the desired font
  77. * @param float $size the desired font size
  78. * @param float $spacing word spacing, if any
  79. * @return float
  80. */
  81. static function get_text_width($text, $font, $size, $word_spacing = 0, $char_spacing = 0) {
  82. //return self::$_pdf->get_text_width($text, $font, $size, $word_spacing, $char_spacing);
  83. // @todo Make sure this cache is efficient before enabling it
  84. static $cache = array();
  85. if ( $text === "" ) {
  86. return 0;
  87. }
  88. // Don't cache long strings
  89. $use_cache = !isset($text[50]); // Faster than strlen
  90. $key = "$font/$size/$word_spacing/$char_spacing";
  91. if ( $use_cache && isset($cache[$key][$text]) ) {
  92. return $cache[$key]["$text"];
  93. }
  94. $width = self::$_pdf->get_text_width($text, $font, $size, $word_spacing, $char_spacing);
  95. if ( $use_cache ) {
  96. $cache[$key][$text] = $width;
  97. }
  98. return $width;
  99. }
  100. /**
  101. * Calculates font height
  102. *
  103. * @param string $font
  104. * @param float $size
  105. * @return float
  106. */
  107. static function get_font_height($font, $size) {
  108. return self::$_pdf->get_font_height($font, $size);
  109. }
  110. /**
  111. * Resolves a font family & subtype into an actual font file
  112. *
  113. * Subtype can be one of 'normal', 'bold', 'italic' or 'bold_italic'. If
  114. * the particular font family has no suitable font file, the default font
  115. * ({@link DOMPDF_DEFAULT_FONT}) is used. The font file returned
  116. * is the absolute pathname to the font file on the system.
  117. *
  118. * @param string $family
  119. * @param string $subtype
  120. * @return string
  121. */
  122. static function get_font($family, $subtype = "normal") {
  123. /* Allow calling for various fonts in search path. Therefore not immediately
  124. * return replacement on non match.
  125. * Only when called with NULL try replacement.
  126. * When this is also missing there is really trouble.
  127. * If only the subtype fails, nevertheless return failure.
  128. * Only on checking the fallback font, check various subtypes on same font.
  129. */
  130. if ( $family ) {
  131. $family = str_replace( array("'", '"'), "", mb_strtolower($family));
  132. $subtype = mb_strtolower($subtype);
  133. if ( isset(self::$_font_lookup[$family][$subtype]) ) {
  134. return self::$_font_lookup[$family][$subtype];
  135. }
  136. return null;
  137. }
  138. $family = DOMPDF_DEFAULT_FONT;
  139. if ( isset(self::$_font_lookup[$family][$subtype]) ) {
  140. return self::$_font_lookup[$family][$subtype];
  141. }
  142. foreach ( self::$_font_lookup[$family] as $sub => $font ) {
  143. if (strpos($subtype, $sub) !== false) {
  144. return $font;
  145. }
  146. }
  147. if ($subtype !== "normal") {
  148. foreach ( self::$_font_lookup[$family] as $sub => $font ) {
  149. if ($sub !== "normal") {
  150. return $font;
  151. }
  152. }
  153. }
  154. $subtype = "normal";
  155. if ( isset(self::$_font_lookup[$family][$subtype]) ) {
  156. return self::$_font_lookup[$family][$subtype];
  157. }
  158. return null;
  159. }
  160. static function get_family($family) {
  161. $family = str_replace( array("'", '"'), "", mb_strtolower($family));
  162. if ( isset(self::$_font_lookup[$family]) ) {
  163. return self::$_font_lookup[$family];
  164. }
  165. return null;
  166. }
  167. /**
  168. * Saves the stored font family cache
  169. *
  170. * The name and location of the cache file are determined by {@link
  171. * Font_Metrics::CACHE_FILE}. This file should be writable by the
  172. * webserver process.
  173. *
  174. * @see Font_Metrics::load_font_families()
  175. */
  176. static function save_font_families() {
  177. // replace the path to the DOMPDF font directory with "DOMPDF_FONT_DIR" (allows for more portability)
  178. $cache_data = var_export(self::$_font_lookup, true);
  179. $cache_data = str_replace('\''.DOMPDF_FONT_DIR , 'DOMPDF_FONT_DIR . \'' , $cache_data);
  180. $cache_data = "<"."?php return $cache_data ?".">";
  181. file_put_contents(self::CACHE_FILE, $cache_data);
  182. }
  183. /**
  184. * Loads the stored font family cache
  185. *
  186. * @see save_font_families()
  187. */
  188. static function load_font_families() {
  189. if ( !is_readable(self::CACHE_FILE) )
  190. return;
  191. self::$_font_lookup = require_once(self::CACHE_FILE);
  192. // If the font family cache is still in the old format
  193. if ( self::$_font_lookup === 1 ) {
  194. $cache_data = file_get_contents(self::CACHE_FILE);
  195. file_put_contents(self::CACHE_FILE, "<"."?php return $cache_data ?".">");
  196. self::$_font_lookup = require_once(self::CACHE_FILE);
  197. }
  198. }
  199. static function get_type($type) {
  200. if (preg_match("/bold/i", $type)) {
  201. if (preg_match("/italic|oblique/i", $type)) {
  202. $type = "bold_italic";
  203. }
  204. else {
  205. $type = "bold";
  206. }
  207. }
  208. elseif (preg_match("/italic|oblique/i", $type)) {
  209. $type = "italic";
  210. }
  211. else {
  212. $type = "normal";
  213. }
  214. return $type;
  215. }
  216. static function install_fonts($files) {
  217. $names = array();
  218. foreach($files as $file) {
  219. $font = Font::load($file);
  220. $records = $font->getData("name", "records");
  221. $type = self::get_type($records[2]);
  222. $names[mb_strtolower($records[1])][$type] = $file;
  223. }
  224. return $names;
  225. }
  226. static function get_system_fonts() {
  227. $files = glob("/usr/share/fonts/truetype/*.ttf") +
  228. glob("/usr/share/fonts/truetype/*/*.ttf") +
  229. glob("/usr/share/fonts/truetype/*/*/*.ttf") +
  230. glob("C:\\Windows\\fonts\\*.ttf") +
  231. glob("C:\\WinNT\\fonts\\*.ttf") +
  232. glob("/mnt/c_drive/WINDOWS/Fonts/");
  233. return self::install_fonts($files);
  234. }
  235. /**
  236. * Returns the current font lookup table
  237. *
  238. * @return array
  239. */
  240. static function get_font_families() {
  241. return self::$_font_lookup;
  242. }
  243. static function set_font_family($fontname, $entry) {
  244. self::$_font_lookup[mb_strtolower($fontname)] = $entry;
  245. }
  246. static function register_font($style, $remote_file) {
  247. $fontname = mb_strtolower($style["family"]);
  248. $families = Font_Metrics::get_font_families();
  249. $entry = array();
  250. if ( isset($families[$fontname]) ) {
  251. $entry = $families[$fontname];
  252. }
  253. $remote_file = $remote_file;
  254. $local_file = DOMPDF_FONT_DIR . md5($remote_file);
  255. $cache_entry = $local_file;
  256. $local_file .= ".ttf";
  257. $style_string = Font_Metrics::get_type("{$style['weight']} {$style['style']}");
  258. if ( !isset($entry[$style_string]) ) {
  259. $entry[$style_string] = $cache_entry;
  260. Font_Metrics::set_font_family($fontname, $entry);
  261. // Download the remote file
  262. if ( !is_file($local_file) ) {
  263. file_put_contents($local_file, file_get_contents($remote_file));
  264. }
  265. $font = Font::load($local_file);
  266. if (!$font) {
  267. return false;
  268. }
  269. $font->parse();
  270. $font->saveAdobeFontMetrics("$cache_entry.ufm");
  271. // Save the changes
  272. Font_Metrics::save_font_families();
  273. }
  274. return true;
  275. }
  276. }
  277. Font_Metrics::load_font_families();