📄 opentype.php
字号:
* the glyph's advance width and its left side bearing. We don't use the * left side bearing. */ $glyphWidths = array(); for ($i = 0; $i < $this->numberHMetrics; $i++) { $glyphWidths[$i] = $this->readUInt(2); $this->skipBytes(2); }
/* Populate last value for the rest of array
*/ while (count($glyphWidths) < $this->numGlyphs) {
$glyphWidths[] = end($glyphWidths);
}
$this->glyphWidths = $glyphWidths; /* There is an optional table of left side bearings which is sometimes * used for monospaced fonts. We don't use the left side bearing, so * we can safely ignore it. */ } /** * Parses the OpenType cmap (Character to Glyph Mapping) table. * * The cmap table provides the maps from character codes to font glyphs. * There are usually at least two character maps in a font: Microsoft Unicode * and Macintosh Roman. For very complex fonts, there may also be mappings * for the characters in the Unicode Surrogates Area, which are UCS-4 * characters. * * @todo Need to rework the selection logic for picking a subtable. We should * have an explicit list of preferences, followed by a list of those that * are tolerable. Most specifically, since everything above this layer deals * in Unicode, we need to be sure to only accept format 0 MacRoman tables. * * @throws Zend_Pdf_Exception */ protected function _parseCmapTable() { $this->_jumpToTable('cmap'); $baseOffset = $this->_tableDirectory['cmap']['offset']; /* We only understand version 0 tables. */ $tableVersion = $this->readUInt(2); if ($tableVersion != 0) { throw new Zend_Pdf_Exception("Unable to read version $tableVersion table", Zend_Pdf_Exception::DONT_UNDERSTAND_TABLE_VERSION); } $this->_debugLog('Version %d table', $tableVersion); $subtableCount = $this->readUInt(2); $this->_debugLog('%d subtables', $subtableCount); /* Like the name table, there may be many different encoding subtables * present. Ideally, we are looking for an acceptable Unicode table. */ $subtables = array(); for ($subtableIndex = 0; $subtableIndex < $subtableCount; $subtableIndex++) { $platformID = $this->readUInt(2); $encodingID = $this->readUInt(2); if (! ( (($platformID == 0) && ($encodingID == 3)) || // Unicode 2.0 or later (($platformID == 0) && ($encodingID == 0)) || // Unicode (($platformID == 3) && ($encodingID == 1)) || // Microsoft Unicode (($platformID == 1) && ($encodingID == 0)) // Mac Roman ) ) { $this->_debugLog('Unsupported encoding: platformID: %d; encodingID: %d; skipping', $platformID, $encodingID); $this->skipBytes(4); continue; } $subtableOffset = $this->readUInt(4); if ($subtableOffset < 0) { // Sanity check for 4-byte unsigned on 32-bit platform $this->_debugLog('Offset 0x%x out of range for platformID: %d; skipping', $subtableOffset, $platformID); continue; } $this->_debugLog('Found subtable; platformID: %d; encodingID: %d; offset: 0x%x (0x%x)', $platformID, $encodingID, $baseOffset + $subtableOffset, $subtableOffset); $subtables[$platformID][$encodingID][] = $subtableOffset; } /* In preferred order, find a subtable to use. */ $offsets = array(); /* Unicode 2.0 or later semantics */ if (isset($subtables[0][3])) { foreach ($subtables[0][3] as $offset) { $offsets[] = $offset; } } /* Unicode default semantics */ if (isset($subtables[0][0])) { foreach ($subtables[0][0] as $offset) { $offsets[] = $offset; } } /* Microsoft Unicode */ if (isset($subtables[3][1])) { foreach ($subtables[3][1] as $offset) { $offsets[] = $offset; } } /* Mac Roman. */ if (isset($subtables[1][0])) { foreach ($subtables[1][0] as $offset) { $offsets[] = $offset; } } $cmapType = -1; foreach ($offsets as $offset) { $cmapOffset = $baseOffset + $offset; $this->moveToOffset($cmapOffset); $format = $this->readUInt(2); $language = -1; switch ($format) { case 0x0: $cmapLength = $this->readUInt(2); $language = $this->readUInt(2); if ($language != 0) { $this->_debugLog('Type 0 cmap tables must be language-independent;' . ' language: %d; skipping', $language); continue; } break; case 0x4: // break intentionally omitted case 0x6: $cmapLength = $this->readUInt(2); $language = $this->readUInt(2); if ($language != 0) { $this->_debugLog('Warning: cmap tables must be language-independent - this font' . ' may not work properly; language: %d', $language); } break; case 0x2: // break intentionally omitted case 0x8: // break intentionally omitted case 0xa: // break intentionally omitted case 0xc: $this->_debugLog('Format: 0x%x currently unsupported; skipping', $format); continue; //$this->skipBytes(2); //$cmapLength = $this->readUInt(4); //$language = $this->readUInt(4); //if ($language != 0) { // $this->_debugLog('Warning: cmap tables must be language-independent - this font' // . ' may not work properly; language: %d', $language); //} //break; default: $this->_debugLog('Unknown subtable format: 0x%x; skipping', $format); continue; } $cmapType = $format; break; } if ($cmapType == -1) { throw new Zend_Pdf_Exception('Unable to find usable cmap table', Zend_Pdf_Exception::CANT_FIND_GOOD_CMAP); } /* Now extract the subtable data and create a Zend_Pdf_FontCmap object. */ $this->_debugLog('Using cmap type %d; offset: 0x%x; length: %d', $cmapType, $cmapOffset, $cmapLength); $this->moveToOffset($cmapOffset); $cmapData = $this->readBytes($cmapLength); $this->cmap = Zend_Pdf_Cmap::cmapWithTypeData($cmapType, $cmapData); } /** * Reads the scaler type from the header of the OpenType font file and * returns it as an unsigned long integer. * * The scaler type defines the type of font: OpenType font files may contain * TrueType or PostScript outlines. Throws an exception if the scaler type * is not recognized. * * @return integer * @throws Zend_Pdf_Exception */ protected function _readScalerType() { if ($this->_scalerType != 0) { return $this->_scalerType; } $this->moveToOffset(0); $this->_scalerType = $this->readUInt(4); switch ($this->_scalerType) { case 0x00010000: // version 1.0 - Windows TrueType signature $this->_debugLog('Windows TrueType signature'); break; case 0x74727565: // 'true' - Macintosh TrueType signature $this->_debugLog('Macintosh TrueType signature'); break; case 0x4f54544f: // 'OTTO' - the CFF signature $this->_debugLog('PostScript CFF signature'); break; case 0x74797031: // 'typ1' throw new Zend_Pdf_Exception('Unsupported font type: PostScript in sfnt wrapper', Zend_Pdf_Exception::WRONG_FONT_TYPE); default: throw new Zend_Pdf_Exception('Not an OpenType font file', Zend_Pdf_Exception::WRONG_FONT_TYPE); } return $this->_scalerType; } /** * Validates a given table's existence, then sets the file pointer to the * start of that table. * * @param string $tableName * @throws Zend_Pdf_Exception */ protected function _jumpToTable($tableName) { if (empty($this->_tableDirectory[$tableName])) { // do not allow NULL or zero throw new Zend_Pdf_Exception("Required table '$tableName' not found!", Zend_Pdf_Exception::REQUIRED_TABLE_NOT_FOUND); } $this->_debugLog("Parsing $tableName table..."); $this->moveToOffset($this->_tableDirectory[$tableName]['offset']); } /** * Reads the fixed 16.16 table version number and checks for compatibility. * If the version is incompatible, throws an exception. If it is compatible, * returns the version number. * * @param float $minVersion Minimum compatible version number. * @param float $maxVertion Maximum compatible version number. * @return float Table version number. * @throws Zend_Pdf_Exception */ protected function _readTableVersion($minVersion, $maxVersion) { $tableVersion = $this->readFixed(16, 16); if (($tableVersion < $minVersion) || ($tableVersion > $maxVersion)) { throw new Zend_Pdf_Exception("Unable to read version $tableVersion table", Zend_Pdf_Exception::DONT_UNDERSTAND_TABLE_VERSION); } $this->_debugLog('Version %.2f table', $tableVersion); return $tableVersion; } /** * Utility method that returns ISO 639 two-letter language codes from the * TrueType platform and language ID. Returns NULL for languages that are * not supported. * * @param integer $platformID * @param integer $encodingID * @return string | null */ protected function _languageCodeForPlatform($platformID, $languageID) { if ($platformID == 3) { // Microsoft encoding. /* The low-order bytes specify the language, the high-order bytes * specify the dialect. We just care about the language. For the * complete list, see: * http://www.microsoft.com/globaldev/reference/lcid-all.mspx */ $languageID &= 0xff; switch ($languageID) { case 0x09: return 'en'; case 0x0c: return 'fr'; case 0x07: return 'de'; case 0x10: return 'it'; case 0x13: return 'nl'; case 0x1d: return 'sv'; case 0x0a: return 'es'; case 0x06: return 'da'; case 0x16: return 'pt'; case 0x14: return 'no'; case 0x0d: return 'he'; case 0x11: return 'ja'; case 0x01: return 'ar'; case 0x0b: return 'fi'; case 0x08: return 'el'; default: return null; } } else if ($platformID == 1) { // Macintosh encoding. switch ($languageID) { case 0: return 'en'; case 1: return 'fr'; case 2: return 'de'; case 3: return 'it'; case 4: return 'nl'; case 5: return 'sv'; case 6: return 'es'; case 7: return 'da'; case 8: return 'pt'; case 9: return 'no'; case 10: return 'he'; case 11: return 'ja'; case 12: return 'ar'; case 13: return 'fi'; case 14: return 'el'; default: return null; } } else { // Unknown encoding. return null; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -