Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php$GLOBALS['g_last_assigned_font_id'] = 0;class Font {var $underline_position;var $underline_thickness;var $ascender;var $descender;var $char_widths;var $bbox;function ascender() {return $this->ascender;}function descender() {return $this->descender;}function error_message() {return $this->error_message;}function Font() {}function linethrough_position() {return $this->bbox[3]*0.25;}function name() {return $this->name;}function overline_position() {return $this->bbox[3]*0.8;}function points($fontsize, $dimension) {return $dimension * $fontsize / 1000;}function stringwidth($string) {$width = 0;$length = strlen($string);for ($i=0; $i<$length; $i++) {$width += $this->char_widths[$string{$i}];};return $width;}function underline_position() {return $this->underline_position;}function underline_thickness() {return $this->underline_thickness;}}class FontTrueType extends Font {function create($fontfile, $encoding) {$font = new FontTrueType();$font->_read(TTF_FONTS_REPOSITORY.$fontfile, $encoding);return $font;}/*** TODO: cache results; replace makefont with this utility*/function _read($file, $encoding) {error_log(sprintf("Parsing font file file %s for encoding %s", $file, $encoding));$font = new OpenTypeFile();$font->open($file);$hhea = $font->getTable('hhea');$head = $font->getTable('head');$hmtx = $font->getTable('hmtx');$post = $font->getTable('post');$cmap = $font->getTable('cmap');$subtable = $cmap->findSubtable(OT_CMAP_PLATFORM_WINDOWS,OT_CMAP_PLATFORM_WINDOWS_UNICODE);/*** Read character widths for selected encoding*/$widths = array();$manager = ManagerEncoding::get();$map = $manager->get_encoding_vector($encoding);foreach ($map as $code => $ucs2) {$glyphIndex = $subtable->lookup($ucs2);if (!is_null($glyphIndex)) {$widths[$code] = floor($hmtx->_hMetrics[$glyphIndex]['advanceWidth']*1000/$head->_unitsPerEm);} else {$widths[$code] = DEFAULT_CHAR_WIDTH;};};// Fill unknown characters with the default char widthfor ($i=0; $i<256; $i++) {if (!isset($widths[chr($i)])) {$widths[chr($i)] = DEFAULT_CHAR_WIDTH;};};$this->ascender = floor($hhea->_ascender*1000/$head->_unitsPerEm);$this->descender = floor($hhea->_descender*1000/$head->_unitsPerEm);$this->bbox = array($head->_xMin*1000/$head->_unitsPerEm,$head->_yMin*1000/$head->_unitsPerEm,$head->_xMax*1000/$head->_unitsPerEm,$head->_yMax*1000/$head->_unitsPerEm);$this->underline_position = floor($post->_underlinePosition*1000/$head->_unitsPerEm);$this->underline_thickness = floor($post->_underlineThickness*1000/$head->_unitsPerEm);$this->char_widths = $widths;$font->close();}}// Note that ALL font dimensions are measured in 1/1000 of font size units;//class FontType1 extends Font {function &create($typeface, $encoding, $font_resolver, &$error_message) {$font = new FontType1();$font->underline_position = 0;$font->underline_thickness = 0;$font->ascender;$font->descender;$font->char_widths = array();$font->bbox = array();global $g_last_assigned_font_id;$g_last_assigned_font_id++;$font->name = "font".$g_last_assigned_font_id;// Get and load the metrics file$afm = $font_resolver->get_afm_mapping($typeface);if (!$font->_parse_afm($afm, $typeface, $encoding)) {$error_message = $font->error_message();$dummy = null;return $dummy;};return $font;}// Parse the AFM metric file; keep only sized of glyphs present in the chosen encodingfunction _parse_afm($afm, $typeface, $encoding) {global $g_manager_encodings;$encoding_data = $g_manager_encodings->get_glyph_to_code_mapping($encoding);$filename = TYPE1_FONTS_REPOSITORY.$afm.".afm";$file = @fopen($filename, 'r');if (!$file) {$_filename = $filename;$_typeface = $typeface;ob_start();include(HTML2PS_DIR.'templates/error._missing_afm.tpl');$this->error_message = ob_get_contents();ob_end_clean();error_log(sprintf("Missing font metrics file: %s",$filename));return false;};while ($line = fgets($file)) {if (preg_match("/C\s-?\d+\s;\sWX\s(\d+)\s;\sN\s(\S+)\s;/",$line,$matches)) {$glyph_width = $matches[1];$glyph_name = $matches[2];// This line is a character width definitionif (isset($encoding_data[$glyph_name])) {foreach ($encoding_data[$glyph_name] as $c) {$this->char_widths[$c] = $glyph_width;};};} elseif (preg_match("/UnderlinePosition ([\d-]+)/",$line,$matches)) {// This line is an underline position line$this->underline_position = $matches[1];} elseif (preg_match("/UnderlineThickness ([\d-]+)/",$line,$matches)) {// This line is an underline thickness line$this->underline_thickness = $matches[1];} elseif (preg_match("/Ascender ([\d-]+)/",$line,$matches)) {// This line is an ascender line$this->ascender = $matches[1];} elseif (preg_match("/Descender ([\d-]+)/",$line,$matches)) {// This line is an descender line$this->descender = $matches[1];} elseif (preg_match("/FontBBox ([\d-]+) ([\d-]+) ([\d-]+) ([\d-]+)/",$line,$matches)) {// This line is an font BBox line$this->bbox = array($matches[1], $matches[2], $matches[3], $matches[4]);};};fclose($file);// Fill unknown characters with the default char widthfor ($i=0; $i<256; $i++) {if (!isset($this->char_widths[chr($i)])) {$this->char_widths[chr($i)] = DEFAULT_CHAR_WIDTH;};};return true;}}?>