3 * @package php-font-lib
4 * @link https://github.com/PhenX/php-font-lib
5 * @author Fabien Ménager <fabien.menager@gmail.com>
6 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
7 * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
10 namespace FontLib\Glyph
;
13 * Composite glyph outline
15 * @package php-font-lib
17 class OutlineComposite
extends Outline
{
18 const ARG_1_AND_2_ARE_WORDS
= 0x0001;
19 const ARGS_ARE_XY_VALUES
= 0x0002;
20 const ROUND_XY_TO_GRID
= 0x0004;
21 const WE_HAVE_A_SCALE
= 0x0008;
22 const MORE_COMPONENTS
= 0x0020;
23 const WE_HAVE_AN_X_AND_Y_SCALE
= 0x0040;
24 const WE_HAVE_A_TWO_BY_TWO
= 0x0080;
25 const WE_HAVE_INSTRUCTIONS
= 0x0100;
26 const USE_MY_METRICS
= 0x0200;
27 const OVERLAP_COMPOUND
= 0x0400;
30 * @var OutlineComponent[]
32 public $components = array();
34 function getGlyphIDs() {
35 if (empty($this->components
)) {
40 foreach ($this->components
as $_component) {
41 $glyphIDs[] = $_component->glyphIndex
;
43 $_glyph = $this->table
->data
[$_component->glyphIndex
];
44 $glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
54 function parseData() {
57 $font = $this->getFont();
60 $flags = $font->readUInt16();
61 $glyphIndex = $font->readUInt16();
70 $point_compound = null;
71 $point_component = null;
75 if ($flags & self
::ARG_1_AND_2_ARE_WORDS
) {
76 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
77 $e = $font->readInt16();
78 $f = $font->readInt16();
81 $point_compound = $font->readUInt16();
82 $point_component = $font->readUInt16();
86 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
87 $e = $font->readInt8();
88 $f = $font->readInt8();
91 $point_compound = $font->readUInt8();
92 $point_component = $font->readUInt8();
96 if ($flags & self
::WE_HAVE_A_SCALE
) {
97 $a = $d = $font->readInt16();
99 elseif ($flags & self
::WE_HAVE_AN_X_AND_Y_SCALE
) {
100 $a = $font->readInt16();
101 $d = $font->readInt16();
103 elseif ($flags & self
::WE_HAVE_A_TWO_BY_TWO
) {
104 $a = $font->readInt16();
105 $b = $font->readInt16();
106 $c = $font->readInt16();
107 $d = $font->readInt16();
110 //if ($flags & self::WE_HAVE_INSTRUCTIONS) {
114 $component = new OutlineComponent();
115 $component->flags
= $flags;
116 $component->glyphIndex
= $glyphIndex;
123 $component->point_compound
= $point_compound;
124 $component->point_component
= $point_component;
125 $component->instructions
= $instructions;
127 $this->components
[] = $component;
128 } while ($flags & self
::MORE_COMPONENTS
);
132 $font = $this->getFont();
134 $gids = $font->getSubset();
136 $size = $font->writeInt16(-1);
137 $size +
= $font->writeFWord($this->xMin
);
138 $size +
= $font->writeFWord($this->yMin
);
139 $size +
= $font->writeFWord($this->xMax
);
140 $size +
= $font->writeFWord($this->yMax
);
142 foreach ($this->components
as $_i => $_component) {
144 if ($_component->point_component
=== null && $_component->point_compound
=== null) {
145 $flags |
= self
::ARGS_ARE_XY_VALUES
;
147 if (abs($_component->e
) > 0x7F ||
abs($_component->f
) > 0x7F) {
148 $flags |
= self
::ARG_1_AND_2_ARE_WORDS
;
151 elseif ($_component->point_component
> 0xFF ||
$_component->point_compound
> 0xFF) {
152 $flags |
= self
::ARG_1_AND_2_ARE_WORDS
;
155 if ($_component->b
== 0 && $_component->c
== 0) {
156 if ($_component->a
== $_component->d
) {
157 if ($_component->a
!= 1.0) {
158 $flags |
= self
::WE_HAVE_A_SCALE
;
162 $flags |
= self
::WE_HAVE_AN_X_AND_Y_SCALE
;
166 $flags |
= self
::WE_HAVE_A_TWO_BY_TWO
;
169 if ($_i < count($this->components
) - 1) {
170 $flags |
= self
::MORE_COMPONENTS
;
173 $size +
= $font->writeUInt16($flags);
175 $new_gid = array_search($_component->glyphIndex
, $gids);
176 $size +
= $font->writeUInt16($new_gid);
178 if ($flags & self
::ARG_1_AND_2_ARE_WORDS
) {
179 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
180 $size +
= $font->writeInt16($_component->e
);
181 $size +
= $font->writeInt16($_component->f
);
184 $size +
= $font->writeUInt16($_component->point_compound
);
185 $size +
= $font->writeUInt16($_component->point_component
);
189 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
190 $size +
= $font->writeInt8($_component->e
);
191 $size +
= $font->writeInt8($_component->f
);
194 $size +
= $font->writeUInt8($_component->point_compound
);
195 $size +
= $font->writeUInt8($_component->point_component
);
199 if ($flags & self
::WE_HAVE_A_SCALE
) {
200 $size +
= $font->writeInt16($_component->a
);
202 elseif ($flags & self
::WE_HAVE_AN_X_AND_Y_SCALE
) {
203 $size +
= $font->writeInt16($_component->a
);
204 $size +
= $font->writeInt16($_component->d
);
206 elseif ($flags & self
::WE_HAVE_A_TWO_BY_TWO
) {
207 $size +
= $font->writeInt16($_component->a
);
208 $size +
= $font->writeInt16($_component->b
);
209 $size +
= $font->writeInt16($_component->c
);
210 $size +
= $font->writeInt16($_component->d
);
217 public function getSVGContours() {
220 /** @var \FontLib\Table\Type\glyf $glyph_data */
221 $glyph_data = $this->getFont()->getTableObject("glyf");
223 /** @var Outline[] $glyphs */
224 $glyphs = $glyph_data->data
;
226 foreach ($this->components
as $component) {
228 "contours" => $glyphs[$component->glyphIndex
]->getSVGContours(),
229 "transform" => $component->getMatrix(),