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
];
45 if ($_glyph !== $this) {
46 $glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
57 function parseData() {
60 $font = $this->getFont();
63 $flags = $font->readUInt16();
64 $glyphIndex = $font->readUInt16();
73 $point_compound = null;
74 $point_component = null;
78 if ($flags & self
::ARG_1_AND_2_ARE_WORDS
) {
79 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
80 $e = $font->readInt16();
81 $f = $font->readInt16();
84 $point_compound = $font->readUInt16();
85 $point_component = $font->readUInt16();
89 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
90 $e = $font->readInt8();
91 $f = $font->readInt8();
94 $point_compound = $font->readUInt8();
95 $point_component = $font->readUInt8();
99 if ($flags & self
::WE_HAVE_A_SCALE
) {
100 $a = $d = $font->readInt16();
102 elseif ($flags & self
::WE_HAVE_AN_X_AND_Y_SCALE
) {
103 $a = $font->readInt16();
104 $d = $font->readInt16();
106 elseif ($flags & self
::WE_HAVE_A_TWO_BY_TWO
) {
107 $a = $font->readInt16();
108 $b = $font->readInt16();
109 $c = $font->readInt16();
110 $d = $font->readInt16();
113 //if ($flags & self::WE_HAVE_INSTRUCTIONS) {
117 $component = new OutlineComponent();
118 $component->flags
= $flags;
119 $component->glyphIndex
= $glyphIndex;
126 $component->point_compound
= $point_compound;
127 $component->point_component
= $point_component;
128 $component->instructions
= $instructions;
130 $this->components
[] = $component;
131 } while ($flags & self
::MORE_COMPONENTS
);
135 $font = $this->getFont();
137 $gids = $font->getSubset();
139 $size = $font->writeInt16(-1);
140 $size +
= $font->writeFWord($this->xMin
);
141 $size +
= $font->writeFWord($this->yMin
);
142 $size +
= $font->writeFWord($this->xMax
);
143 $size +
= $font->writeFWord($this->yMax
);
145 foreach ($this->components
as $_i => $_component) {
147 if ($_component->point_component
=== null && $_component->point_compound
=== null) {
148 $flags |
= self
::ARGS_ARE_XY_VALUES
;
150 if (abs($_component->e
) > 0x7F ||
abs($_component->f
) > 0x7F) {
151 $flags |
= self
::ARG_1_AND_2_ARE_WORDS
;
154 elseif ($_component->point_component
> 0xFF ||
$_component->point_compound
> 0xFF) {
155 $flags |
= self
::ARG_1_AND_2_ARE_WORDS
;
158 if ($_component->b
== 0 && $_component->c
== 0) {
159 if ($_component->a
== $_component->d
) {
160 if ($_component->a
!= 1.0) {
161 $flags |
= self
::WE_HAVE_A_SCALE
;
165 $flags |
= self
::WE_HAVE_AN_X_AND_Y_SCALE
;
169 $flags |
= self
::WE_HAVE_A_TWO_BY_TWO
;
172 if ($_i < count($this->components
) - 1) {
173 $flags |
= self
::MORE_COMPONENTS
;
176 $size +
= $font->writeUInt16($flags);
178 $new_gid = array_search($_component->glyphIndex
, $gids);
179 $size +
= $font->writeUInt16($new_gid);
181 if ($flags & self
::ARG_1_AND_2_ARE_WORDS
) {
182 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
183 $size +
= $font->writeInt16($_component->e
);
184 $size +
= $font->writeInt16($_component->f
);
187 $size +
= $font->writeUInt16($_component->point_compound
);
188 $size +
= $font->writeUInt16($_component->point_component
);
192 if ($flags & self
::ARGS_ARE_XY_VALUES
) {
193 $size +
= $font->writeInt8($_component->e
);
194 $size +
= $font->writeInt8($_component->f
);
197 $size +
= $font->writeUInt8($_component->point_compound
);
198 $size +
= $font->writeUInt8($_component->point_component
);
202 if ($flags & self
::WE_HAVE_A_SCALE
) {
203 $size +
= $font->writeInt16($_component->a
);
205 elseif ($flags & self
::WE_HAVE_AN_X_AND_Y_SCALE
) {
206 $size +
= $font->writeInt16($_component->a
);
207 $size +
= $font->writeInt16($_component->d
);
209 elseif ($flags & self
::WE_HAVE_A_TWO_BY_TWO
) {
210 $size +
= $font->writeInt16($_component->a
);
211 $size +
= $font->writeInt16($_component->b
);
212 $size +
= $font->writeInt16($_component->c
);
213 $size +
= $font->writeInt16($_component->d
);
220 public function getSVGContours() {
223 /** @var \FontLib\Table\Type\glyf $glyph_data */
224 $glyph_data = $this->getFont()->getTableObject("glyf");
226 /** @var Outline[] $glyphs */
227 $glyphs = $glyph_data->data
;
229 foreach ($this->components
as $component) {
230 $_glyph = $glyphs[$component->glyphIndex
];
232 if ($_glyph !== $this) {
234 "contours" => $_glyph->getSVGContours(),
235 "transform" => $component->getMatrix(),