/** * Constructor * * Instantiate a TTF 'post' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Post */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['post']->offset + 4; $italicBytes = $font->read($bytePos, 4); $this->italicAngle = $font->readFixed(16, 16, $italicBytes); $bytePos += 8; $ary = unpack('nfixed/', $font->read($bytePos, 2)); $ary = $font->shiftToSigned($ary); $this->fixed = $ary['fixed']; }
/** * Constructor * * Instantiate a TTF 'hhea' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Hhea */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['hhea']->offset + 4; $ary = unpack('nascent/' . 'ndescent', $font->read($bytePos, 4)); $ary = $font->shiftToSigned($ary); $this->ascent = $font->toEmSpace($ary['ascent']); $this->descent = $font->toEmSpace($ary['descent']); $bytePos = $font->tableInfo['hhea']->offset + 34; $ary = unpack('nnumberOfHMetrics/', $font->read($bytePos, 2)); $this->numberOfHMetrics = $ary['numberOfHMetrics']; }
/** * Constructor * * Instantiate a TTF 'name' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Name */ public function __construct(\Pop\Font\AbstractFont $font) { $font->tableInfo['name']->header = new \ArrayObject(unpack('nformatSelector/' . 'nnameRecordsCount/' . 'nstorageOffset', $font->read($font->tableInfo['name']->offset, 6)), \ArrayObject::ARRAY_AS_PROPS); $bytePos = $font->tableInfo['name']->offset + 6; for ($j = 0; $j < $font->tableInfo['name']->header->nameRecordsCount; $j++) { $ttfRecord = unpack('nplatformId/' . 'nencodingId/' . 'nlanguageId/' . 'nnameId/' . 'nlength/' . 'noffset', $font->read($bytePos, 12)); $ttfRecordOffset = $bytePos + 12; $nextBytePos = $font->tableInfo['name']->offset + $font->tableInfo['name']->header->storageOffset + $ttfRecord['offset']; $ttfValue = $font->read($nextBytePos, $ttfRecord['length']); if ($ttfRecord['platformId'] != 1) { $ttfValue = @iconv('UTF-16be', 'UTF-8//TRANSLIT', $ttfValue); } if ($ttfValue != '' && isset($ttfRecord['nameId']) && isset($this->names[$ttfRecord['nameId']])) { $this->fontInfo[$this->names[$ttfRecord['nameId']]] = $ttfValue; } $bytePos = $ttfRecordOffset; } }
/** * Constructor * * Instantiate a TTF 'head' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Head */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['head']->offset; $tableVersionNumberBytes = $font->read($bytePos, 4); $tableVersionNumber = $font->readFixed(16, 16, $tableVersionNumberBytes); $bytePos += 4; $fontRevisionBytes = $font->read($bytePos, 4); $fontRevision = $font->readFixed(16, 16, $fontRevisionBytes); $versionArray = array('tableVersionNumber' => $tableVersionNumber, 'fontRevision' => $fontRevision); $bytePos += 4; $headerArray = unpack('NcheckSumAdjustment/' . 'NmagicNumber/' . 'nflags/' . 'nunitsPerEm', $font->read($bytePos, 12)); $bytePos += 28; $bBox = unpack('nxMin/' . 'nyMin/' . 'nxMax/' . 'nyMax', $font->read($bytePos, 8)); $bBox = $font->shiftToSigned($bBox); $bytePos += 14; $indexToLocFormat = unpack('nindexToLocFormat', $font->read($bytePos, 2)); $headerArray['indexToLocFormat'] = $font->shiftToSigned($indexToLocFormat['indexToLocFormat']); $this->headerInfo = array_merge($versionArray, $headerArray, $bBox); }
/** * Constructor * * Instantiate a TTF 'hmtx' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Hmtx */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['hmtx']->offset; for ($i = 0; $i < $font->numberOfHMetrics; $i++) { $ary = unpack('nglyphWidth/', $font->read($bytePos, 2)); $this->glyphWidths[$i] = $font->shiftToSigned($ary['glyphWidth']); $bytePos += 4; } while (count($this->glyphWidths) < $font->numberOfGlyphs) { $this->glyphWidths[] = end($this->glyphWidths); } }
/** * Constructor * * Instantiate a TTF 'loca' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Loca */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['loca']->offset; $format = $font->header->indexToLocFormat == 1 ? 'N' : 'n'; $byteLength = $font->header->indexToLocFormat == 1 ? 4 : 2; $multiplier = $font->header->indexToLocFormat == 1 ? 1 : 2; for ($i = 0; $i < $font->numberOfGlyphs + 1; $i++) { $ary = unpack($format . 'offset', $font->read($bytePos, $byteLength)); $this->offsets[$i] = $ary['offset'] * $multiplier; $bytePos += $byteLength; } }
/** * Constructor * * Instantiate a OTF 'OS/2' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Os2 */ public function __construct(\Pop\Font\AbstractFont $font) { $this->flags = new \ArrayObject(array('isFixedPitch' => false, 'isSerif' => false, 'isSymbolic' => false, 'isScript' => false, 'isNonSymbolic' => false, 'isItalic' => false, 'isAllCap' => false, 'isSmallCap' => false, 'isForceBold' => false), \ArrayObject::ARRAY_AS_PROPS); $bytePos = $font->tableInfo['OS/2']->offset + 8; $ary = unpack("nfsType", $font->read($bytePos, 2)); $this->embeddable = $ary['fsType'] != 2 && ($ary['fsType'] & 0x200) == 0; $bytePos = $font->tableInfo['OS/2']->offset + 30; $ary = unpack("nfamily_class", $font->read($bytePos, 2)); $familyClass = $font->shiftToSigned($ary['family_class']) >> 8; if ($familyClass >= 1 && $familyClass <= 5 || $familyClass == 7) { $this->flags->isSerif = true; } else { if ($familyClass == 8) { $this->flags->isSerif = false; } } if ($familyClass == 10) { $this->flags->isScript = true; } if ($familyClass == 12) { $this->flags->isSymbolic = true; $this->flags->isNonSymbolic = false; } else { $this->flags->isSymbolic = false; $this->flags->isNonSymbolic = true; } // Unicode bit-sniffing may not be necessary. $bytePos += 3; $ary = unpack('NunicodeRange1/' . 'NunicodeRange2/' . 'NunicodeRange3/' . 'NunicodeRange4', $font->read($bytePos, 16)); if ($ary['unicodeRange1'] == 1 && $ary['unicodeRange2'] == 0 && $ary['unicodeRange3'] == 0 && $ary['unicodeRange4'] == 0) { $this->flags->isSymbolic = false; $this->flags->isNonSymbolic = true; } $bytePos = $font->tableInfo['OS/2']->offset + 76; $ary = unpack("ncap/", $font->read($bytePos, 2)); $this->capHeight = $font->toEmSpace($font->shiftToSigned($ary['cap'])); }
/** * Method to parse the CMAP subtables. * * @param \Pop\Font\AbstractFont $font * @return void */ protected function parseSubTables($font) { $bytePos = $font->tableInfo['cmap']->offset + 4; // Get each of the subtable's data. for ($i = 0; $i < $this->header->numberOfTables; $i++) { $ary = unpack('nplatformId/' . 'nencodingId/' . 'Noffset', $font->read($bytePos, 8)); if ($ary['platformId'] == 0 && $ary['encodingId'] == 0) { $ary['encoding'] = 'Unicode 2.0'; } else { if ($ary['platformId'] == 0 && $ary['encodingId'] == 3) { $ary['encoding'] = 'Unicode'; } else { if ($ary['platformId'] == 3 && $ary['encodingId'] == 1) { $ary['encoding'] = 'Microsoft Unicode'; } else { if ($ary['platformId'] == 1 && $ary['encodingId'] == 0) { $ary['encoding'] = 'Mac Roman'; } else { $ary['encoding'] = 'Unknown'; } } } } $this->subTables[] = new \ArrayObject($ary, \ArrayObject::ARRAY_AS_PROPS); $bytePos += 8; } // Parse each of the subtable's data. foreach ($this->subTables as $key => $subTable) { $bytePos = $font->tableInfo['cmap']->offset + $subTable->offset; $ary = unpack('nformat/' . 'nlength/' . 'nlanguage', $font->read($bytePos, 6)); $this->subTables[$key]->format = $ary['format']; $this->subTables[$key]->length = $ary['length']; $this->subTables[$key]->language = $ary['language']; $bytePos += 6; $this->subTables[$key]->data = $font->read($bytePos, $ary['length'] - 6); switch ($this->subTables[$key]->format) { case 0: $this->subTables[$key]->parsed = Cmap\ByteEncoding::parseData($this->subTables[$key]->data); break; case 4: $this->subTables[$key]->parsed = Cmap\SegmentToDelta::parseData($this->subTables[$key]->data); break; case 6: $this->subTables[$key]->parsed = Cmap\TrimmedTable::parseData($this->subTables[$key]->data); break; } } }
/** * Constructor * * Instantiate a TTF 'glyf' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Glyf */ public function __construct(\Pop\Font\AbstractFont $font) { $locaLength = count($font->tables['loca']->offsets); $j = 0; foreach ($font->tables['loca']->offsets as $offset) { $bytePos = $font->tableInfo['glyf']->offset + $offset; $ary = unpack('nnumberOfContours/' . 'nxMin/' . 'nyMin/' . 'nxMax/' . 'nyMax', $font->read($bytePos, 10)); $ary = $font->shiftToSigned($ary); $ary['xMin'] = $font->toEmSpace($ary['xMin']); $ary['yMin'] = $font->toEmSpace($ary['yMin']); $ary['xMax'] = $font->toEmSpace($ary['xMax']); $ary['yMax'] = $font->toEmSpace($ary['yMax']); $ary['width'] = $ary['xMin'] + $ary['xMax']; $this->glyphWidths[] = $ary['width']; $bytePos += 10; $ary['endPtsOfContours'] = array(); $ary['instructionLength'] = null; $ary['instructions'] = null; $ary['flags'] = null; // The simple and composite glyph descriptions may not be necessary. // If simple glyph. if ($ary['numberOfContours'] > 0) { for ($i = 0; $i < $ary['numberOfContours']; $i++) { $ar = unpack('nendPt', $font->read($bytePos, 2)); $ary['endPtsOfContours'][$i] = $ar['endPt']; $bytePos += 2; } $ar = unpack('ninstructionLength', $font->read($bytePos, 2)); $ary['instructionLength'] = $ar['instructionLength']; $bytePos += 2; if ($ary['instructionLength'] > 0) { for ($i = 0; $i < $ary['instructionLength']; $i++) { $byte = $font->read($bytePos, 1); if (strlen($byte) != 0) { $ar = unpack('Cinstruction', $byte); $ary['instructions'][$i] = $ar['instruction']; $bytePos++; } else { $ary['instructions'][$i] = null; } } } $bytePos++; $byte = $font->read($bytePos, 1); if (strlen($byte) != 0) { $ar = unpack('Cflags', $byte); $ary['flags'] = $ar['flags']; } else { $ary['flags'] = 0; } if ($j < $locaLength - 1) { $this->glyphs[] = $ary; } // Stopped here. Still need to get the x & y coordinates of the simple glyph. // Else, if composite glyph. } else { if ($j < $locaLength - 1) { // Composite glyph goes here. } } $j++; } }
/** * Constructor * * Instantiate a TTF 'maxp' table object. * * @param \Pop\Font\AbstractFont $font * @return \Pop\Font\TrueType\Table\Maxp */ public function __construct(\Pop\Font\AbstractFont $font) { $bytePos = $font->tableInfo['maxp']->offset + 4; $ary = unpack('nnumberOfGlyphs/', $font->read($bytePos, 2)); $this->numberOfGlyphs = $ary['numberOfGlyphs']; }