--- /dev/null
+package Font::TTF::GSUB;
+
+=head1 NAME
+
+Font::TTF::GSUB - Module support for the GSUB table in conjunction with TTOpen
+
+=head1 DESCRIPTION
+
+Handles the GSUB subtables in relation to Ttopen tables. Due to the variety of
+different lookup types, the data structures are not all that straightforward,
+although I have tried to make life easy for myself when using this!
+
+=head1 INSTANCE VARIABLES
+
+The structure of a GSUB table is the same as that given in L<Font::TTF::Ttopen>.
+Here we give some of the semantics specific to GSUB lookups.
+
+=over 4
+
+=item ACTION_TYPE
+
+This is a string taking one of 4 values indicating the nature of the information
+in the ACTION array of the rule:
+
+=over 8
+
+=item g
+
+The action contains a string of glyphs to replace the match string by
+
+=item l
+
+The action array contains a list of lookups and offsets to run, in order, on
+the matched string
+
+=item a
+
+The action array is an unordered set of optional replacements for the matched
+glyph. The application should make the selection somehow.
+
+=item o
+
+The action array is empty (in fact there is no rule array for this type of
+rule) and the ADJUST value should be added to the glyph id to find the replacement
+glyph id value
+
+=back
+
+=item MATCH_TYPE
+
+This indicates which type of information the various MATCH arrays (MATCH, PRE,
+POST) hold in the rule:
+
+=over 8
+
+=item g
+
+The array holds a string of glyph ids which should match exactly
+
+=item c
+
+The array holds a sequence of class definitions which each glyph should
+correspondingly match to
+
+=item o
+
+The array holds offsets to coverage tables
+
+=back
+
+=back
+
+=head1 CORRESPONDANCE TO LAYOUT TYPES
+
+The following table gives the values for ACTION_TYPE and MATCH_TYPE for each
+of the 11 different lookup types found in the GSUB table definition I have:
+
+ 1.1 1.2 2 3 4 5.1 5.2 5.3 6.1 6.2 6.3
+ ACTION_TYPE o g g a g l l l l l l
+ MATCH_TYPE g g c o g c o
+
+Hopefully, the rest of the uses of the variables should make sense from this
+table.
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::Ttopen;
+
+@ISA = qw(Font::TTF::Ttopen);
+
+=head2 $t->read_sub($fh, $lookup, $index)
+
+Asked by the superclass to read in from the given file the indexth subtable from
+lookup number lookup. The file is positioned ready for the read.
+
+=cut
+
+sub read_sub
+{
+ my ($self, $fh, $main_lookup, $sindex) = @_;
+ my ($type) = $main_lookup->{'TYPE'};
+ my ($loc) = $fh->tell();
+ my ($lookup) = $main_lookup->{'SUB'}[$sindex];
+ my ($dat, $s, @subst, $t, $fmt, $cover, $count, $mcount, $scount, $i, $gid);
+ my (@srec);
+
+ if ($type == 6)
+ {
+ $fh->read($dat, 4);
+ ($fmt, $cover) = TTF_Unpack('S2', $dat);
+ if ($fmt < 3)
+ {
+ $fh->read($dat, 2);
+ $count = TTF_Unpack('S', $dat);
+ }
+ } else
+ {
+ $fh->read($dat, 6);
+ ($fmt, $cover, $count) = TTF_Unpack("S3", $dat);
+ }
+ unless ($fmt == 3 && ($type == 5 || $type == 6))
+ { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); }
+
+ $lookup->{'FORMAT'} = $fmt;
+ if ($type == 1 && $fmt == 1)
+ {
+ $count -= 65536 if ($count > 32767);
+ $lookup->{'ADJUST'} = $count;
+ $lookup->{'ACTION_TYPE'} = 'o';
+ } elsif ($type == 1 && $fmt == 2)
+ {
+ $fh->read($dat, $count << 1);
+ @subst = TTF_Unpack('S*', $dat);
+ foreach $s (@subst)
+ { push(@{$lookup->{'RULES'}}, [{'ACTION' => [$s]}]); }
+ $lookup->{'ACTION_TYPE'} = 'g';
+ } elsif ($type == 2 || $type == 3)
+ {
+ $fh->read($dat, $count << 1); # number of offsets
+ foreach $s (TTF_Unpack('S*', $dat))
+ {
+ $fh->seek($loc + $s, 0);
+ $fh->read($dat, 2);
+ $t = TTF_Unpack('S', $dat);
+ $fh->read($dat, $t << 1);
+ push(@{$lookup->{'RULES'}}, [{'ACTION' => [TTF_Unpack('S*', $dat)]}]);
+ }
+ $lookup->{'ACTION_TYPE'} = ($type == 2 ? 'g' : 'a');
+ } elsif ($type == 4)
+ {
+ $fh->read($dat, $count << 1);
+ foreach $s (TTF_Unpack('S*', $dat))
+ {
+ @subst = ();
+ $fh->seek($loc + $s, 0);
+ $fh->read($dat, 2);
+ $t = TTF_Unpack('S', $dat);
+ $fh->read($dat, $t << 1);
+ foreach $t (TTF_Unpack('S*', $dat))
+ {
+ $fh->seek($loc + $s + $t, 0);
+ $fh->read($dat, 4);
+ ($gid, $mcount) = TTF_Unpack('S2', $dat);
+ $fh->read($dat, ($mcount - 1) << 1);
+ push(@subst, {'ACTION' => [$gid], 'MATCH' => [TTF_Unpack('S*', $dat)]});
+ }
+ push(@{$lookup->{'RULES'}}, [@subst]);
+ }
+ $lookup->{'ACTION_TYPE'} = 'g';
+ $lookup->{'MATCH_TYPE'} = 'g';
+ } elsif ($type == 5 || $type == 6)
+ { $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc); }
+ $lookup;
+}
+
+
+=head2 $t->extension
+
+Returns the table type number for the extension table
+
+=cut
+
+sub extension
+{ return 7; }
+
+
+=head2 $t->out_sub($fh, $lookup, $index)
+
+Passed the filehandle to output to, suitably positioned, the lookup and subtable
+index, this function outputs the subtable to $fh at that point.
+
+=cut
+
+sub out_sub
+{
+ my ($self, $fh, $main_lookup, $index, $ctables, $base) = @_;
+ my ($type) = $main_lookup->{'TYPE'};
+ my ($lookup) = $main_lookup->{'SUB'}[$index];
+ my ($fmt) = $lookup->{'FORMAT'};
+ my ($out, $r, $t, $i, $j, $offc, $offd, $numd);
+ my ($num) = $#{$lookup->{'RULES'}} + 1;
+
+ if ($type == 1)
+ {
+ $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base));
+ if ($fmt == 1)
+ { $out .= pack("n", $lookup->{'ADJUST'}); }
+ else
+ {
+ $out .= pack("n", $num);
+ foreach $r (@{$lookup->{'RULES'}})
+ { $out .= pack("n", $r->[0]{'ACTION'}[0]); }
+ }
+ } elsif ($type == 2 || $type == 3)
+ {
+ $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base),
+ $num);
+ $out .= pack('n*', (0) x $num);
+ $offc = length($out);
+ for ($i = 0; $i < $num; $i++)
+ {
+ $out .= pack("n*", $#{$lookup->{'RULES'}[$i][0]{'ACTION'}} + 1,
+ @{$lookup->{'RULES'}[$i][0]{'ACTION'}});
+ substr($out, ($i << 1) + 6, 2) = pack('n', $offc);
+ $offc = length($out);
+ }
+ } elsif ($type == 4 || $type == 5 || $type == 6)
+ { $out = $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num, $base); }
+# Font::TTF::Ttopen::out_final($fh, $out, [[$ctables, 0]]);
+ $out;
+}
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken@sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+