independent-analytics
/
vendor
/
phenx
/
php-font-lib
/
src
/
FontLib
/
Glyph
/
OutlineComposite.php
Outline.php
3 years ago
OutlineComponent.php
3 years ago
OutlineComposite.php
3 years ago
OutlineSimple.php
3 years ago
OutlineComposite.php
196 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * @package php-font-lib |
| 5 | * @link https://github.com/PhenX/php-font-lib |
| 6 | * @author Fabien Ménager <fabien.menager@gmail.com> |
| 7 | * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License |
| 8 | * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $ |
| 9 | */ |
| 10 | namespace IAWP\FontLib\Glyph; |
| 11 | |
| 12 | /** |
| 13 | * Composite glyph outline |
| 14 | * |
| 15 | * @package php-font-lib |
| 16 | */ |
| 17 | class OutlineComposite extends Outline |
| 18 | { |
| 19 | const ARG_1_AND_2_ARE_WORDS = 0x1; |
| 20 | const ARGS_ARE_XY_VALUES = 0x2; |
| 21 | const ROUND_XY_TO_GRID = 0x4; |
| 22 | const WE_HAVE_A_SCALE = 0x8; |
| 23 | const MORE_COMPONENTS = 0x20; |
| 24 | const WE_HAVE_AN_X_AND_Y_SCALE = 0x40; |
| 25 | const WE_HAVE_A_TWO_BY_TWO = 0x80; |
| 26 | const WE_HAVE_INSTRUCTIONS = 0x100; |
| 27 | const USE_MY_METRICS = 0x200; |
| 28 | const OVERLAP_COMPOUND = 0x400; |
| 29 | /** |
| 30 | * @var OutlineComponent[] |
| 31 | */ |
| 32 | public $components = array(); |
| 33 | function getGlyphIDs() |
| 34 | { |
| 35 | if (empty($this->components)) { |
| 36 | $this->parseData(); |
| 37 | } |
| 38 | $glyphIDs = array(); |
| 39 | foreach ($this->components as $_component) { |
| 40 | $glyphIDs[] = $_component->glyphIndex; |
| 41 | $_glyph = $this->table->data[$_component->glyphIndex]; |
| 42 | if ($_glyph !== $this) { |
| 43 | $glyphIDs = \array_merge($glyphIDs, $_glyph->getGlyphIDs()); |
| 44 | } |
| 45 | } |
| 46 | return $glyphIDs; |
| 47 | } |
| 48 | /*function parse() { |
| 49 | //$this->parseData(); |
| 50 | }*/ |
| 51 | function parseData() |
| 52 | { |
| 53 | parent::parseData(); |
| 54 | $font = $this->getFont(); |
| 55 | do { |
| 56 | $flags = $font->readUInt16(); |
| 57 | $glyphIndex = $font->readUInt16(); |
| 58 | $a = 1.0; |
| 59 | $b = 0.0; |
| 60 | $c = 0.0; |
| 61 | $d = 1.0; |
| 62 | $e = 0.0; |
| 63 | $f = 0.0; |
| 64 | $point_compound = null; |
| 65 | $point_component = null; |
| 66 | $instructions = null; |
| 67 | if ($flags & self::ARG_1_AND_2_ARE_WORDS) { |
| 68 | if ($flags & self::ARGS_ARE_XY_VALUES) { |
| 69 | $e = $font->readInt16(); |
| 70 | $f = $font->readInt16(); |
| 71 | } else { |
| 72 | $point_compound = $font->readUInt16(); |
| 73 | $point_component = $font->readUInt16(); |
| 74 | } |
| 75 | } else { |
| 76 | if ($flags & self::ARGS_ARE_XY_VALUES) { |
| 77 | $e = $font->readInt8(); |
| 78 | $f = $font->readInt8(); |
| 79 | } else { |
| 80 | $point_compound = $font->readUInt8(); |
| 81 | $point_component = $font->readUInt8(); |
| 82 | } |
| 83 | } |
| 84 | if ($flags & self::WE_HAVE_A_SCALE) { |
| 85 | $a = $d = $font->readInt16(); |
| 86 | } elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) { |
| 87 | $a = $font->readInt16(); |
| 88 | $d = $font->readInt16(); |
| 89 | } elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) { |
| 90 | $a = $font->readInt16(); |
| 91 | $b = $font->readInt16(); |
| 92 | $c = $font->readInt16(); |
| 93 | $d = $font->readInt16(); |
| 94 | } |
| 95 | //if ($flags & self::WE_HAVE_INSTRUCTIONS) { |
| 96 | // |
| 97 | //} |
| 98 | $component = new OutlineComponent(); |
| 99 | $component->flags = $flags; |
| 100 | $component->glyphIndex = $glyphIndex; |
| 101 | $component->a = $a; |
| 102 | $component->b = $b; |
| 103 | $component->c = $c; |
| 104 | $component->d = $d; |
| 105 | $component->e = $e; |
| 106 | $component->f = $f; |
| 107 | $component->point_compound = $point_compound; |
| 108 | $component->point_component = $point_component; |
| 109 | $component->instructions = $instructions; |
| 110 | $this->components[] = $component; |
| 111 | } while ($flags & self::MORE_COMPONENTS); |
| 112 | } |
| 113 | function encode() |
| 114 | { |
| 115 | $font = $this->getFont(); |
| 116 | $gids = $font->getSubset(); |
| 117 | $size = $font->writeInt16(-1); |
| 118 | $size += $font->writeFWord($this->xMin); |
| 119 | $size += $font->writeFWord($this->yMin); |
| 120 | $size += $font->writeFWord($this->xMax); |
| 121 | $size += $font->writeFWord($this->yMax); |
| 122 | foreach ($this->components as $_i => $_component) { |
| 123 | $flags = 0; |
| 124 | if ($_component->point_component === null && $_component->point_compound === null) { |
| 125 | $flags |= self::ARGS_ARE_XY_VALUES; |
| 126 | if (\abs($_component->e) > 0x7f || \abs($_component->f) > 0x7f) { |
| 127 | $flags |= self::ARG_1_AND_2_ARE_WORDS; |
| 128 | } |
| 129 | } elseif ($_component->point_component > 0xff || $_component->point_compound > 0xff) { |
| 130 | $flags |= self::ARG_1_AND_2_ARE_WORDS; |
| 131 | } |
| 132 | if ($_component->b == 0 && $_component->c == 0) { |
| 133 | if ($_component->a == $_component->d) { |
| 134 | if ($_component->a != 1.0) { |
| 135 | $flags |= self::WE_HAVE_A_SCALE; |
| 136 | } |
| 137 | } else { |
| 138 | $flags |= self::WE_HAVE_AN_X_AND_Y_SCALE; |
| 139 | } |
| 140 | } else { |
| 141 | $flags |= self::WE_HAVE_A_TWO_BY_TWO; |
| 142 | } |
| 143 | if ($_i < \count($this->components) - 1) { |
| 144 | $flags |= self::MORE_COMPONENTS; |
| 145 | } |
| 146 | $size += $font->writeUInt16($flags); |
| 147 | $new_gid = \array_search($_component->glyphIndex, $gids); |
| 148 | $size += $font->writeUInt16($new_gid); |
| 149 | if ($flags & self::ARG_1_AND_2_ARE_WORDS) { |
| 150 | if ($flags & self::ARGS_ARE_XY_VALUES) { |
| 151 | $size += $font->writeInt16($_component->e); |
| 152 | $size += $font->writeInt16($_component->f); |
| 153 | } else { |
| 154 | $size += $font->writeUInt16($_component->point_compound); |
| 155 | $size += $font->writeUInt16($_component->point_component); |
| 156 | } |
| 157 | } else { |
| 158 | if ($flags & self::ARGS_ARE_XY_VALUES) { |
| 159 | $size += $font->writeInt8($_component->e); |
| 160 | $size += $font->writeInt8($_component->f); |
| 161 | } else { |
| 162 | $size += $font->writeUInt8($_component->point_compound); |
| 163 | $size += $font->writeUInt8($_component->point_component); |
| 164 | } |
| 165 | } |
| 166 | if ($flags & self::WE_HAVE_A_SCALE) { |
| 167 | $size += $font->writeInt16($_component->a); |
| 168 | } elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) { |
| 169 | $size += $font->writeInt16($_component->a); |
| 170 | $size += $font->writeInt16($_component->d); |
| 171 | } elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) { |
| 172 | $size += $font->writeInt16($_component->a); |
| 173 | $size += $font->writeInt16($_component->b); |
| 174 | $size += $font->writeInt16($_component->c); |
| 175 | $size += $font->writeInt16($_component->d); |
| 176 | } |
| 177 | } |
| 178 | return $size; |
| 179 | } |
| 180 | public function getSVGContours() |
| 181 | { |
| 182 | $contours = array(); |
| 183 | /** @var \FontLib\Table\Type\glyf $glyph_data */ |
| 184 | $glyph_data = $this->getFont()->getTableObject("glyf"); |
| 185 | /** @var Outline[] $glyphs */ |
| 186 | $glyphs = $glyph_data->data; |
| 187 | foreach ($this->components as $component) { |
| 188 | $_glyph = $glyphs[$component->glyphIndex]; |
| 189 | if ($_glyph !== $this) { |
| 190 | $contours[] = array("contours" => $_glyph->getSVGContours(), "transform" => $component->getMatrix()); |
| 191 | } |
| 192 | } |
| 193 | return $contours; |
| 194 | } |
| 195 | } |
| 196 |