1 package Font::TTF::Kern;
5 Font::TTF::Kern - Kerning tables
9 Kerning tables are held as an ordered collection of subtables each giving
10 incremental information regarding the kerning of various pairs of glyphs.
12 The basic structure of the kerning data structure is:
14 $kern = $f->{'kern'}{'tables'}[$tnum]{'kerns'}{$leftnum}{$rightnum};
16 Due to the possible complexity of some kerning tables the above information
17 is insufficient. Reference also needs to be made to the type of the table and
20 =head1 INSTANCE VARIABLES
22 The instance variables for a kerning table are relatively straightforward.
28 Version number of the kerning table
32 Number of subtables in the kerning table
36 Array of subtables in the kerning table
40 Each subtable has a number of instance variables.
44 A two level hash array containing kerning values. The indexing is left
45 value and then right value. In the case of type 2 tables, the indexing
46 is via left class and right class. It may seem using hashes is strange,
47 but most tables are not type 2 and this method saves empty array values.
51 Stores the table type. Only type 0 and type 2 tables are specified for
56 A bit field of coverage information regarding the kerning value. See the
57 TrueType specification for details.
61 Contains the version number of the table.
65 Number of kerning pairs in this type 0 table.
69 An array indexed by glyph - left_first which returns a class number for
70 the glyph in type 2 tables.
74 An array indexed by glyph - right_first which returns a class number for
75 the glyph in type 2 tables.
79 the glyph number of the first element in the left array for type 2 tables.
83 the glyph number of the first element in the right array for type 2 tables.
87 Number of left classes
91 Number of right classes
103 use Font::TTF::Utils;
104 use Font::TTF::Table;
106 @ISA = qw(Font::TTF::Table);
110 Reads the whole kerning table into structures
117 my ($fh) = $self->{' INFILE'};
118 my ($dat, $i, $numt, $len, $cov, $t);
120 $self->SUPER::read or return $self;
123 ($self->{'Version'}, $numt) = unpack("n2", $dat);
124 $self->{'Num'} = $numt;
126 for ($i = 0; $i < $numt; $i++)
130 ($t->{'Version'}, $len, $cov) = unpack("n3", $dat);
131 $t->{'coverage'} = $cov & 255;
132 $t->{'type'} = $cov >> 8;
133 $fh->read($dat, $len - 6);
134 if ($t->{'Version'} == 0)
136 $t->{'Num'} = unpack("n", $dat);
137 my (@vals) = unpack("n*", substr($dat, 8, $t->{'Num'} * 6));
138 for (0 .. ($t->{'Num'} - 1))
144 $v -= 65536 if ($v > 32767);
145 $t->{'kern'}{$f}{$l} = $v;
147 } elsif ($t->{'Version'} == 2)
149 my ($wid, $off, $numg, $maxl, $maxr, $j);
151 $wid = unpack("n", $dat);
152 $off = unpack("n", substr($dat, 2));
153 ($t->{'left_first'}, $numg) = unpack("n2", substr($dat, $off));
154 $t->{'left'} = [unpack("C$numg", substr($dat, $off + 4))];
155 foreach (@{$t->{'left'}})
158 $maxl = $_ if ($_ > $maxl);
160 $t->{'left_max'} = $maxl;
162 $off = unpack("n", substr($dat, 4));
163 ($t->{'right_first'}, $numg) = unpack("n2", substr($dat, $off));
164 $t->{'right'} = [unpack("C$numg", substr($dat, $off + 4))];
165 foreach (@{$t->{'right'}})
168 $maxr = $_ if ($_ > $maxr);
170 $t->{'right_max'} = $maxr;
172 $off = unpack("n", substr($dat, 6));
173 for ($j = 0; $j <= $maxl; $j++)
177 map { $t->{'kern'}{$j}{$k} = $_ if $_; $k++; }
178 unpack("n$maxr", substr($dat, $off + $wid * $j));
181 push (@{$self->{'tables'}}, $t);
189 Outputs the kerning tables to the given file
195 my ($self, $fh) = @_;
196 my ($i, $l, $r, $loc, $loc1, $t);
198 return $self->SUPER::out($fh) unless ($self->{' read'});
200 $fh->print(pack("n2", $self->{'Version'}, $self->{'Num'}));
201 for ($i = 0; $i < $self->{'Num'}; $i++)
203 $t = $self->{'tables'}[$i];
206 $fh->print(pack("nnn", $t->{'Version'}, 0, $t->{'coverage'}));
207 if ($t->{'Version'} == 0)
210 foreach $l (sort {$a <=> $b} keys %{$t->{'kern'}})
212 foreach $r (sort {$a <=> $b} keys %{$t->{'kern'}{$l}})
213 { $dat .= TTF_Pack("SSs", $l, $r, $t->{'kern'}{$l}{$r}); }
215 $fh->print(TTF_Pack("SSSS", Font::TTF::Utils::TTF_bininfo(length($dat) / 6, 6)));
217 } elsif ($t->{'Version'} == 2)
221 $fh->print(pack("nnnn", $t->{'right_max'} << 1, 8, ($#{$t->{'left'}} + 7) << 1,
222 ($#{$t->{'left'}} + $#{$t->{'right'}} + 10) << 1));
224 $fh->print(pack("nn", $t->{'left_first'}, $#{$t->{'left'}} + 1));
225 foreach (@{$t->{'left'}})
226 { $fh->print(pack("C", $_ * (($t->{'left_max'} + 1) << 1))); }
228 $fh->print(pack("nn", $t->{'right_first'}, $#{$t->{'right'}} + 1));
229 foreach (@{$t->{'right'}})
230 { $fh->print(pack("C", $_ << 1)); }
232 $arr = "\000\000" x (($t->{'left_max'} + 1) * ($t->{'right_max'} + 1));
233 foreach $l (keys %{$t->{'kern'}})
235 foreach $r (keys %{$t->{'kern'}{$l}})
236 { substr($arr, ($l * ($t->{'left_max'} + 1) + $r) << 1, 2)
237 = pack("n", $t->{'kern'}{$l}{$r}); }
242 $fh->seek($loc + 2, 0);
243 $fh->print(pack("n", $loc1 - $loc));
250 =head2 $t->XML_element($context, $depth, $key, $value)
252 Handles outputting the kern hash into XML a little more tidily
259 my ($context, $depth, $key, $value) = @_;
260 my ($fh) = $context->{'fh'};
263 return $self->SUPER::XML_element(@_) unless ($key eq 'kern');
264 $fh->print("$depth<kern-table>\n");
265 foreach $f (sort {$a <=> $b} keys %{$value})
267 foreach $l (sort {$a <=> $b} keys %{$value->{$f}})
268 { $fh->print("$depth$context->{'indent'}<adjust first='$f' last='$l' dist='$value->{$f}{$l}'/>\n"); }
270 $fh->print("$depth</kern-table>\n");
282 Only supports kerning table types 0 & 2.
286 No real support functions to I<do> anything with the kerning tables yet.
292 Martin Hosken Martin_Hosken@sil.org. See L<Font::TTF::Font> for copyright and