function _findfont($name, $encoding) { $font =& $this->font_factory->get_type1($name, $encoding); if ($font == null) { $this->error_message .= $this->font_factory->error_message(); $dummy = null; return $dummy; } if (!isset($this->used_encodings[$encoding])) { $this->used_encodings[$encoding] = true; $this->_write_document_prolog(ManagerEncoding::get_ps_encoding_vector($encoding)); $this->_write_document_prolog("\n"); } $fontname = $font->name(); if (!isset($this->found_fonts[$fontname])) { $this->found_fonts[$fontname] = true; $this->_write_document_prolog("/{$fontname} /{$name} {$encoding} findfont-enc def\n"); } 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->getEncodingVector($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 width for ($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(); }
function generate_cpg($encoding, $force = false) { if (!$force) { $filename = CACHE_DIR . $encoding . '.cpg'; } else { $filename = CACHE_DIR . uniqid('', false) . '.cpg'; } if (file_exists($filename)) { return $filename; } $output = fopen($filename, 'w'); $manager_encoding =& ManagerEncoding::get(); $vector = $manager_encoding->get_encoding_vector($encoding); foreach ($vector as $code => $utf) { fwrite($output, sprintf("0x%04X 0x%02X\n", $utf, ord($code))); } fclose($output); return $filename; }
function get_content_callback($word, $encoding) { $manager_encoding =& ManagerEncoding::get(); return $manager_encoding->to_utf8($word, $encoding); }
function break_into_words($content) { $content = trim($content); if ($content == '') { return array(); } // Extract Unicode characters from the raw content data $ptr = 0; $utf8_chars = array(); $ucs2_chars = array(); $size = strlen($content); while ($ptr < $size) { $utf8_char = ManagerEncoding::get_next_utf8_char($content, $ptr); $utf8_chars[] = $utf8_char; $ucs2_chars[] = utf8_to_code($utf8_char); } // Get unicode line breaking classes $classes = array_map(array($this, 'get_line_break_class'), $ucs2_chars); $this->find_line_break($classes, $breaks, count($classes)); // Make words array $words = array(); $word = ''; for ($i = 0, $size = count($breaks); $i < $size; $i++) { $word .= $utf8_chars[$i]; $break = $breaks[$i]; if ($break == LB_INDIRECT || $break == LB_INDIRECT_CM || $break == LB_DIRECT || $break == LB_EXPLICIT) { $words[] = trim($word); $word = ''; } } return $words; }
function process_word($raw_content, &$pipeline) { if ($raw_content === '') { return false; } $ptr = 0; $word = ''; $hyphens = array(); $encoding = 'iso-8859-1'; $manager_encoding =& ManagerEncoding::get(); $text_box =& TextBox::create_empty($pipeline); $len = strlen($raw_content); while ($ptr < $len) { $char = $manager_encoding->getNextUTF8Char($raw_content, $ptr); // Check if current char is a soft hyphen character. It it is, // remove it from the word (as it should not be drawn normally) // and store its location if ($char == SYMBOL_SHY) { $hyphens[] = strlen($word); } else { $mapping = $manager_encoding->getMapping($char); /** * If this character is not found in predefined encoding vectors, * we'll use "Custom" encoding and add single-character TextBox * * @TODO: handle characters without known glyph names */ if (is_null($mapping)) { /** * No mapping to default encoding vectors found for this character */ /** * Add last word */ if ($word !== '') { $text_box->add_subword($word, $encoding, $hyphens); } /** * Add current symbol */ $custom_char = $manager_encoding->addCustomChar(utf8_to_code($char)); $text_box->add_subword($custom_char, $manager_encoding->getCustomEncodingName(), $hyphens); $word = ''; } else { if (isset($mapping[$encoding])) { $word .= $mapping[$encoding]; } else { // This condition prevents empty text boxes from appearing; say, if word starts with a national // character, an () - text box with no letters will be generated, in rare case causing a random line // wraps, if container is narrow if ($word !== '') { $text_box->add_subword($word, $encoding, $hyphens); } reset($mapping); list($encoding, $add) = each($mapping); $word = $mapping[$encoding]; $hyphens = array(); } } } } if ($word !== '') { $text_box->add_subword($word, $encoding, $hyphens); } $this->add_child($text_box); return true; }
function MakeFont($fontfile, $afmfile, $destdir, $destfile, $enc) { // Generate a font definition file set_magic_quotes_runtime(0); ini_set('auto_detect_line_endings', '1'); $manager = ManagerEncoding::get(); $map = $manager->get_encoding_glyphs($enc); $fm = ReadAFM($afmfile, $map); if (is_null($fm)) { error_log(sprintf("Notice: Missing AFM file '%s'; attempting to parse font file '%s' directly", $afmfile, $fontfile)); $fm = ReadTTF($fontfile, $manager->getEncodingVector($enc)); if (is_null($fm)) { die(sprintf("Cannot get font metrics for '%s'", $fontfile)); } } $diff = MakeFontEncoding($map); $cmap = MakeFontCMap($enc); $fd = MakeFontDescriptor($fm, empty($map)); //Find font type if ($fontfile) { $ext = strtolower(substr($fontfile, -3)); if ($ext == 'ttf') { $type = 'TrueType'; } elseif ($ext == 'pfb') { $type = 'Type1'; } else { die('<B>Error:</B> unrecognized font file extension: ' . $ext); } } else { if ($type != 'TrueType' and $type != 'Type1') { die('<B>Error:</B> incorrect font type: ' . $type); } } //Start generation $s = '<?php' . "\n"; $s .= '$type=\'' . $type . "';\n"; $s .= '$name=\'' . $fm['FontName'] . "';\n"; $s .= '$desc=' . $fd . ";\n"; if (!isset($fm['UnderlinePosition'])) { $fm['UnderlinePosition'] = -100; } if (!isset($fm['UnderlineThickness'])) { $fm['UnderlineThickness'] = 50; } $s .= '$up=' . $fm['UnderlinePosition'] . ";\n"; $s .= '$ut=' . $fm['UnderlineThickness'] . ";\n"; $w = MakeWidthArray($fm); $s .= '$cw=' . $w . ";\n"; $s .= '$enc=\'' . $enc . "';\n"; $s .= '$diff=\'' . $diff . "';\n"; $s .= '$cmap=' . $cmap . ";\n"; $basename = substr(basename($afmfile), 0, -4); if ($fontfile) { //Embedded font if (!file_exists($fontfile)) { die('<B>Error:</B> font file not found: ' . $fontfile); } if ($type == 'TrueType') { CheckTTF($fontfile); } $f = fopen($fontfile, 'rb'); if (!$f) { die('<B>Error:</B> Can\'t open ' . $fontfile); } $file = fread($f, filesize($fontfile)); fclose($f); if ($type == 'Type1') { //Find first two sections and discard third one $header = ord($file[0]) == 128; if ($header) { //Strip first binary header $file = substr($file, 6); } $pos = strpos($file, 'eexec'); if (!$pos) { die('<B>Error:</B> font file does not seem to be valid Type1'); } $size1 = $pos + 6; if ($header and ord($file[$size1]) == 128) { //Strip second binary header $file = substr($file, 0, $size1) . substr($file, $size1 + 6); } $pos = strpos($file, '00000000'); if (!$pos) { die('<B>Error:</B> font file does not seem to be valid Type1'); } $size2 = $pos - $size1; $file = substr($file, 0, $size1 + $size2); } $gzcompress_exists = function_exists('gzcompress'); if ($gzcompress_exists) { $cmp = $basename . '.z'; SaveToFile($destdir . $cmp, gzcompress($file), 'b'); $s .= '$file=\'' . $cmp . "';\n"; } else { $cmp = $basename . '.ttf'; SaveToFile($destdir . $cmp, $file, 'b'); $s .= '$file=\'' . basename($fontfile) . "';\n"; error_log('Notice: font file could not be compressed (zlib extension not available)'); } if ($type == 'Type1') { $s .= '$size1=' . $size1 . ";\n"; $s .= '$size2=' . $size2 . ";\n"; } else { $s .= '$originalsize=' . filesize($fontfile) . ";\n"; } } else { //Not embedded font $s .= '$file=' . "'';\n"; } $s .= "?>\n"; SaveToFile($destdir . $destfile, $s); }
function _LoadFont($fontkey, $family, $encoding) { if (!isset($this->fonts[$fontkey])) { global $g_font_resolver_pdf; $file = $g_font_resolver_pdf->ttf_mappings[$family]; $embed = $g_font_resolver_pdf->embed[$family]; // Remove the '.ttf' suffix $file = substr($file, 0, strlen($file) - 4); // Generate (if required) PHP font description files if (!file_exists($this->_getfontpath() . $fontkey . '.php') || ManagerEncoding::is_custom_encoding($encoding)) { // As MakeFont squeaks a lot, we'll need to capture and discard its output MakeFont(TTF_FONTS_REPOSITORY . $file . '.ttf', TTF_FONTS_REPOSITORY . $file . '.afm', $this->_getfontpath(), $fontkey . '.php', $encoding); } $this->AddFont($fontkey, $family, $encoding, $fontkey . '.php', $embed); } }