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)); }