235 lines
6.5 KiB
PHP
235 lines
6.5 KiB
PHP
<?php
|
|
/**
|
|
* @package php-font-lib
|
|
* @link https://github.com/PhenX/php-font-lib
|
|
* @author Fabien Ménager <fabien.menager@gmail.com>
|
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
|
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
|
|
*/
|
|
|
|
namespace FontLib\Glyph;
|
|
|
|
/**
|
|
* Composite glyph outline
|
|
*
|
|
* @package php-font-lib
|
|
*/
|
|
class OutlineComposite extends Outline {
|
|
const ARG_1_AND_2_ARE_WORDS = 0x0001;
|
|
const ARGS_ARE_XY_VALUES = 0x0002;
|
|
const ROUND_XY_TO_GRID = 0x0004;
|
|
const WE_HAVE_A_SCALE = 0x0008;
|
|
const MORE_COMPONENTS = 0x0020;
|
|
const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
|
|
const WE_HAVE_A_TWO_BY_TWO = 0x0080;
|
|
const WE_HAVE_INSTRUCTIONS = 0x0100;
|
|
const USE_MY_METRICS = 0x0200;
|
|
const OVERLAP_COMPOUND = 0x0400;
|
|
|
|
/**
|
|
* @var OutlineComponent[]
|
|
*/
|
|
public $components = array();
|
|
|
|
function getGlyphIDs() {
|
|
if (empty($this->components)) {
|
|
$this->parseData();
|
|
}
|
|
|
|
$glyphIDs = array();
|
|
foreach ($this->components as $_component) {
|
|
$glyphIDs[] = $_component->glyphIndex;
|
|
|
|
$_glyph = $this->table->data[$_component->glyphIndex];
|
|
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
|
|
}
|
|
|
|
return $glyphIDs;
|
|
}
|
|
|
|
/*function parse() {
|
|
//$this->parseData();
|
|
}*/
|
|
|
|
function parseData() {
|
|
parent::parseData();
|
|
|
|
$font = $this->getFont();
|
|
|
|
do {
|
|
$flags = $font->readUInt16();
|
|
$glyphIndex = $font->readUInt16();
|
|
|
|
$a = 1.0;
|
|
$b = 0.0;
|
|
$c = 0.0;
|
|
$d = 1.0;
|
|
$e = 0.0;
|
|
$f = 0.0;
|
|
|
|
$point_compound = null;
|
|
$point_component = null;
|
|
|
|
$instructions = null;
|
|
|
|
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
|
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
|
$e = $font->readInt16();
|
|
$f = $font->readInt16();
|
|
}
|
|
else {
|
|
$point_compound = $font->readUInt16();
|
|
$point_component = $font->readUInt16();
|
|
}
|
|
}
|
|
else {
|
|
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
|
$e = $font->readInt8();
|
|
$f = $font->readInt8();
|
|
}
|
|
else {
|
|
$point_compound = $font->readUInt8();
|
|
$point_component = $font->readUInt8();
|
|
}
|
|
}
|
|
|
|
if ($flags & self::WE_HAVE_A_SCALE) {
|
|
$a = $d = $font->readInt16();
|
|
}
|
|
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
|
$a = $font->readInt16();
|
|
$d = $font->readInt16();
|
|
}
|
|
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
|
$a = $font->readInt16();
|
|
$b = $font->readInt16();
|
|
$c = $font->readInt16();
|
|
$d = $font->readInt16();
|
|
}
|
|
|
|
//if ($flags & self::WE_HAVE_INSTRUCTIONS) {
|
|
//
|
|
//}
|
|
|
|
$component = new OutlineComponent();
|
|
$component->flags = $flags;
|
|
$component->glyphIndex = $glyphIndex;
|
|
$component->a = $a;
|
|
$component->b = $b;
|
|
$component->c = $c;
|
|
$component->d = $d;
|
|
$component->e = $e;
|
|
$component->f = $f;
|
|
$component->point_compound = $point_compound;
|
|
$component->point_component = $point_component;
|
|
$component->instructions = $instructions;
|
|
|
|
$this->components[] = $component;
|
|
} while ($flags & self::MORE_COMPONENTS);
|
|
}
|
|
|
|
function encode() {
|
|
$font = $this->getFont();
|
|
|
|
$gids = $font->getSubset();
|
|
|
|
$size = $font->writeInt16(-1);
|
|
$size += $font->writeFWord($this->xMin);
|
|
$size += $font->writeFWord($this->yMin);
|
|
$size += $font->writeFWord($this->xMax);
|
|
$size += $font->writeFWord($this->yMax);
|
|
|
|
foreach ($this->components as $_i => $_component) {
|
|
$flags = 0;
|
|
if ($_component->point_component === null && $_component->point_compound === null) {
|
|
$flags |= self::ARGS_ARE_XY_VALUES;
|
|
|
|
if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
|
|
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
|
}
|
|
}
|
|
elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
|
|
$flags |= self::ARG_1_AND_2_ARE_WORDS;
|
|
}
|
|
|
|
if ($_component->b == 0 && $_component->c == 0) {
|
|
if ($_component->a == $_component->d) {
|
|
if ($_component->a != 1.0) {
|
|
$flags |= self::WE_HAVE_A_SCALE;
|
|
}
|
|
}
|
|
else {
|
|
$flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
|
|
}
|
|
}
|
|
else {
|
|
$flags |= self::WE_HAVE_A_TWO_BY_TWO;
|
|
}
|
|
|
|
if ($_i < count($this->components) - 1) {
|
|
$flags |= self::MORE_COMPONENTS;
|
|
}
|
|
|
|
$size += $font->writeUInt16($flags);
|
|
|
|
$new_gid = array_search($_component->glyphIndex, $gids);
|
|
$size += $font->writeUInt16($new_gid);
|
|
|
|
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
|
|
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
|
$size += $font->writeInt16($_component->e);
|
|
$size += $font->writeInt16($_component->f);
|
|
}
|
|
else {
|
|
$size += $font->writeUInt16($_component->point_compound);
|
|
$size += $font->writeUInt16($_component->point_component);
|
|
}
|
|
}
|
|
else {
|
|
if ($flags & self::ARGS_ARE_XY_VALUES) {
|
|
$size += $font->writeInt8($_component->e);
|
|
$size += $font->writeInt8($_component->f);
|
|
}
|
|
else {
|
|
$size += $font->writeUInt8($_component->point_compound);
|
|
$size += $font->writeUInt8($_component->point_component);
|
|
}
|
|
}
|
|
|
|
if ($flags & self::WE_HAVE_A_SCALE) {
|
|
$size += $font->writeInt16($_component->a);
|
|
}
|
|
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
|
|
$size += $font->writeInt16($_component->a);
|
|
$size += $font->writeInt16($_component->d);
|
|
}
|
|
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
|
|
$size += $font->writeInt16($_component->a);
|
|
$size += $font->writeInt16($_component->b);
|
|
$size += $font->writeInt16($_component->c);
|
|
$size += $font->writeInt16($_component->d);
|
|
}
|
|
}
|
|
|
|
return $size;
|
|
}
|
|
|
|
public function getSVGContours() {
|
|
$contours = array();
|
|
|
|
/** @var \FontLib\Table\Type\glyf $glyph_data */
|
|
$glyph_data = $this->getFont()->getTableObject("glyf");
|
|
|
|
/** @var Outline[] $glyphs */
|
|
$glyphs = $glyph_data->data;
|
|
|
|
foreach ($this->components as $component) {
|
|
$contours[] = array(
|
|
"contours" => $glyphs[$component->glyphIndex]->getSVGContours(),
|
|
"transform" => $component->getMatrix(),
|
|
);
|
|
}
|
|
|
|
return $contours;
|
|
}
|
|
} |