1 package Font::TTF::GDEF;
5 Font::TTF::GDEF - Opentype GDEF table support
9 The GDEF table contains various global lists of information which are apparantly
10 used in other places in an OpenType renderer. But precisely where is open to
13 =head1 INSTANCE VARIABLES
15 There are 4 tables in the GDEF table, each with their own structure:
21 This is an L<Font::TTF::Coverage> Class Definition table containing information
22 as to what type each glyph is.
26 The attach table consists of a coverage table and then attachment points for
27 each glyph in the coverage table:
33 This is a coverage table
37 This is an array of point elements. Each element is an array of curve points
38 corresponding to the attachment points on that glyph. The order of the curve points
39 in the array corresponds to the attachment point number specified in the MARKS
40 coverage table (see below).
46 This contains the ligature caret positioning information for ligature glyphs
52 A coverage table to say which glyphs are ligatures
56 An array of elements for each ligature. Each element is an array of information
57 for each caret position in the ligature (there being number of components - 1 of
64 This is the format of the information and is important to provide the semantics
65 for the value. This value must be set correctly before output
69 The value which has meaning according to FMT
73 For FMT = 3, a device table is also referenced which is stored here
81 Due to confusion in the GDEF specification, this field is currently withdrawn until
82 the confusion is resolved. That way, perhaps this stuff will work!
84 This class definition table stores the mark attachment point numbers for each
85 attachment mark, to indicate which attachment point the mark attaches to on its
98 use Font::TTF::Ttopen;
99 use vars qw(@ISA $new_gdef);
101 @ISA = qw(Font::TTF::Table);
106 Reads the table into the data structure
113 my ($fh) = $self->{' INFILE'};
114 my ($boff) = $self->{' OFFSET'};
115 my ($dat, $goff, $loff, $aoff, $moff, $r, $s, $bloc);
117 $self->SUPER::read or return $self;
122 ($self->{'Version'}, $goff, $aoff, $loff, $moff) = TTF_Unpack('fS4', $dat);
127 ($self->{'Version'}, $goff, $aoff, $loff) = TTF_Unpack('fS3', $dat);
132 $fh->seek($goff + $boff, 0);
133 $self->{'GLYPH'} = Font::TTF::Coverage->new(0)->read($fh);
136 if ($new_gdef && $moff > 0 && $moff < $self->{' LENGTH'})
138 $fh->seek($moff + $boff, 0);
139 $self->{'MARKS'} = Font::TTF::Coverage->new(0)->read($fh);
144 my ($off, $gcount, $pcount);
146 $fh->seek($aoff + $boff, 0);
148 ($off, $gcount) = TTF_Unpack('SS', $dat);
149 $fh->read($dat, $gcount << 1);
151 $fh->seek($aoff + $boff + $off, 0);
152 $self->{'ATTACH'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
154 foreach $r (TTF_Unpack('S*', $dat))
158 push (@{$self->{'ATTACH'}{'POINTS'}}, []);
161 $fh->seek($aoff + $boff + $r, 0);
163 $pcount = TTF_Unpack('S', $dat);
164 $fh->read($dat, $pcount << 1);
165 push (@{$self->{'ATTACH'}{'POINTS'}}, [TTF_Unpack('S*', $dat)]);
171 my ($lcount, $off, $ccount, $srec, $comp);
173 $fh->seek($loff + $boff, 0);
175 ($off, $lcount) = TTF_Unpack('SS', $dat);
176 $fh->read($dat, $lcount << 1);
178 $fh->seek($off + $loff + $boff, 0);
179 $self->{'LIG'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
181 foreach $r (TTF_Unpack('S*', $dat))
183 $fh->seek($r + $loff + $boff, 0);
185 $ccount = TTF_Unpack('S', $dat);
186 $fh->read($dat, $ccount << 1);
189 foreach $s (TTF_Unpack('S*', $dat))
192 $fh->seek($s + $r + $loff + $boff, 0);
194 ($comp->{'FMT'}, $comp->{'VAL'}) = TTF_Unpack('S*', $dat);
195 if ($comp->{'FMT'} == 3)
198 $off = TTF_Unpack('S', $dat);
199 if (defined $self->{' CACHE'}{$off + $s + $r})
200 { $comp->{'DEVICE'} = $self->{' CACHE'}{$off + $s + $r}; }
203 $fh->seek($off + $s + $r + $loff + $boff, 0);
204 $comp->{'DEVICE'} = Font::TTF::Delta->new->read($fh);
205 $self->{' CACHE'}{$off + $s + $r} = $comp->{'DEVICE'};
208 push (@$srec, $comp);
210 push (@{$self->{'LIG'}{'LIGS'}}, $srec);
220 Writes out this table.
226 my ($self, $fh) = @_;
227 my ($goff, $aoff, $loff, $moff, @offs, $loc1, $coff, $loc);
229 return $self->SUPER::out($fh) unless $self->{' read'};
233 { $fh->print(TTF_Pack('fSSSS', $self->{'Version'}, 0, 0, 0, 0)); }
235 { $fh->print(TTF_Pack('fSSS', $self->{'Version'}, 0, 0, 0)); }
237 if (defined $self->{'GLYPH'})
239 $goff = $fh->tell() - $loc;
240 $self->{'GLYPH'}->out($fh);
243 if (defined $self->{'ATTACH'})
247 $aoff = $fh->tell() - $loc;
248 $fh->print(pack('n*', (0) x ($#{$self->{'ATTACH'}{'POINTS'}} + 3)));
249 foreach $r (@{$self->{'ATTACH'}{'POINTS'}})
251 push (@offs, $fh->tell() - $loc - $aoff);
252 $fh->print(pack('n*', $#{$r} + 1, @$r));
254 $coff = $fh->tell() - $loc - $aoff;
255 $self->{'ATTACH'}{'COVERAGE'}->out($fh);
257 $fh->seek($aoff + $loc, 0);
258 $fh->print(pack('n*', $coff, $#offs + 1, @offs));
262 if (defined $self->{'LIG'})
264 my (@reftables, $ltables, $i, $j, $out, $r, $s);
267 $loff = $fh->tell() - $loc;
269 Font::TTF::Ttopen::ref_cache($self->{'LIG'}{'COVERAGE'}, $ltables, 0),
270 $#{$self->{'LIG'}{'LIGS'}} + 1,
271 (0) x ($#{$self->{'LIG'}{'LIGS'}} + 1));
272 push (@reftables, [$ltables, 0]);
274 foreach $r (@{$self->{'LIG'}{'LIGS'}})
277 $loc1 = length($out);
278 substr($out, ($i << 1) + 4, 2) = TTF_Pack('S', $loc1);
279 $out .= pack('n*', $#{$r} + 1, (0) x ($#{$r} + 1));
283 substr($out, ($j << 1) + 2 + $loc1, 2) =
284 TTF_Pack('S', length($out) - $loc1);
285 $out .= TTF_Pack('SS', $s->{'FMT'}, $s->{'VAL'});
286 $out .= pack('n', Font::TTF::Ttopen::ref_cache($s->{'DEVICE'},
287 $ltables, length($out))) if ($s->{'FMT'} == 3);
290 push (@reftables, [$ltables, $loc1]);
293 Font::TTF::Ttopen::out_final($fh, $out, \@reftables);
296 if ($new_gdef && defined $self->{'MARKS'})
298 $moff = $fh->tell() - $loc;
299 $self->{'MARKS'}->out($fh);
303 $fh->seek($loc + 4, 0);
305 { $fh->print(TTF_Pack('S4', $goff, $aoff, $loff, $moff)); }
307 { $fh->print(TTF_Pack('S3', $goff, $aoff, $loff)); }