1 package Font::TTF::Font;
5 Font::TTF::Font - Memory representation of a font
9 Here is the regression test (you provide your own font). Run it once and then
10 again on the output of the first run. There should be no differences between
11 the outputs of the two runs.
13 $f = Font::TTF::Font->open($ARGV[0]);
15 # force a read of all the tables
16 $f->tables_do(sub { $_[0]->read; });
18 # force read of all glyphs (use read_dat to use lots of memory!)
19 # $f->{'loca'}->glyphs_do(sub { $_[0]->read; });
20 $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; });
21 # NB. no need to $g->update since $f->{'glyf'}->out will do it for us
24 $f->release; # clear up memory forcefully!
28 A Truetype font consists of a header containing a directory of tables which
29 constitute the rest of the file. This class holds that header and directory and
30 also creates objects of the appropriate type for each table within the font.
31 Note that it does not read each table into memory, but creates a short reference
32 which can be read using the form:
34 $f->{$tablename}->read;
36 Classes are included that support many of the different TrueType tables. For
37 those for which no special code exists, the table type C<table> is used, which
38 defaults to L<Font::TTF::Table>. The current tables which are supported are:
40 table Font::TTF::Table - for unknown tables
43 Feat Font::TTF::GrFeat
52 cmap Font::TTF::Cmap - see also Font::TTF::OldCmap
58 glyf Font::TTF::Glyf - see also Font::TTF::Glyph
63 kern Font::TTF::Kern - see alternative Font::TTF::AATKern
66 mort Font::TTF::Mort - see also Font::TTF::OldMort
77 L<Font::TTF::EBDT> L<Font::TTF::EBLC> L<Font::TTF::GrFeat>
78 L<Font::TTF::GDEF> L<Font::TTF::GPOS> L<Font::TTF::GSUB> L<Font::TTF::LTSH>
79 L<Font::TTF::OS_2> L<Font::TTF::PCLT> L<Font::TTF::Sill> L<Font::TTF::Bsln> L<Font::TTF::Cmap> L<Font::TTF::Cvt_>
80 L<Font::TTF::Fdsc> L<Font::TTF::Feat> L<Font::TTF::Fmtx> L<Font::TTF::Fpgm> L<Font::TTF::Glyf>
81 L<Font::TTF::Hdmx> L<Font::TTF::Head> L<Font::TTF::Hhea> L<Font::TTF::Hmtx> L<Font::TTF::Kern>
82 L<Font::TTF::Loca> L<Font::TTF::Maxp> L<Font::TTF::Mort> L<Font::TTF::Name> L<Font::TTF::Post>
83 L<Font::TTF::Prep> L<Font::TTF::Prop> L<Font::TTF::Vhea> L<Font::TTF::Vmtx> L<Font::TTF::OldCmap>
84 L<Font::TTF::Glyph> L<Font::TTF::AATKern> L<Font::TTF::OldMort>
87 =head1 INSTANCE VARIABLES
89 Instance variables begin with a space (and have lengths greater than the 4
90 characters which make up table names).
96 This is used during output to disable the creation of the file checksum in the
97 head table. For example, during DSIG table creation, this flag will be set to
98 ensure that the file checksum is left at zero.
102 If set, do not harmonize the script and lang trees of GPOS and GSUB tables. See L<Font::TTF::Ttopen> for more info.
106 Contains the filename of the font which this object was read from.
110 The file handle which reflects the source file for this font.
114 Contains the offset from the beginning of the read file of this particular
115 font directory, thus providing support for TrueType Collections.
126 use vars qw(%tables $VERSION $dumper);
131 $VERSION = 0.38; # MJPH 2-FEB-2008 Add Sill table
132 # $VERSION = 0.37; # MJPH 7-OCT-2005 Force hhea update if dirty, give more OS/2 stuff in update
133 # $VERSION = 0.36; # MJPH 19-AUG-2005 Change cmap::reverse api to be opts based
134 # $VERSION = 0.35; # MJPH 4-MAY-2004 Various fixes to OpenType stuff, separate off scripts
135 # $VERSION = 0.34; # MJPH 22-MAY-2003 Update PSNames to latest AGL
136 # $VERSION = 0.33; # MJPH 9-OCT-2002 Support CFF OpenType (just by version=='OTTO'?!)
137 # $VERSION = 0.32; # MJPH 2-OCT-2002 Bug fixes to TTFBuilder, new methods and some
138 # extension table support in Ttopen and Coverage
139 # $VERSION = 0.31; # MJPH 1-JUL-2002 fix read format 12 cmap (bart@cs.pdx.edu)
140 # improve surrogate support in ttfremap
141 # fix return warn to return warn,undef
142 # ensure correct indexToLocFormat
143 # $VERSION = 0.30; # MJPH 28-MAY-2002 add updated release
144 # $VERSION = 0.29; # MJPH 9-APR-2002 update ttfbuilder, sort out surrogates
145 # $VERSION = 0.28; # MJPH 13-MAR-2002 update ttfbuilder, add Font::TTF::Cmap::ms_enc()
146 # $VERSION = 0.27; # MJPH 6-FEB-2002 update ttfbuilder, support no fpgm, no more __DATA__
147 # $VERSION = 0.26; # MJPH 19-SEP-2001 Update ttfbuilder
148 # $VERSION = 0.25; # MJPH 18-SEP-2001 problems in update of head
149 # $VERSION = 0.24; # MJPH 1-AUG-2001 Sort out update
150 # $VERSION = 0.23; # GST 30-MAY-2001 Memory leak fixed
151 # $VERSION = 0.22; # MJPH 09-APR-2001 Ensure all of AAT stuff included
152 # $VERSION = 0.21; # MJPH 23-MAR-2001 Improve Opentype support
153 # $VERSION = 0.20; # MJPH 13-JAN-2001 Add XML output and some of XML input, AAT & OT tables
154 # $VERSION = 0.19; # MJPH 29-SEP-2000 Add cmap::is_unicode, debug makefile.pl
155 # $VERSION = 0.18; # MJPH 21-JUL-2000 Debug Utils::TTF_bininfo
156 # $VERSION = 0.17; # MJPH 16-JUN-2000 Add utf8 support to names
157 # $VERSION = 0.16; # MJPH 26-APR-2000 Mark read tables as read, tidy up POD
158 # $VERSION = 0.15; # MJPH 5-FEB-2000 Ensure right versions released
159 # $VERSION = 0.14; # MJPH 11-SEP-1999 Sort out Unixisms, agian!
160 # $VERSION = 0.13; # MJPH 9-SEP-1999 Add empty, debug update_bbox
161 # $VERSION = 0.12; # MJPH 22-JUL-1999 Add update_bbox
162 # $VERSION = 0.11; # MJPH 7-JUL-1999 Don't store empties in cmaps
163 # $VERSION = 0.10; # MJPH 21-JUN-1999 Use IO::File
164 # $VERSION = 0.09; # MJPH 9-JUN-1999 Add 5.004 require, minor tweeks in cmap
165 # $VERSION = 0.08; # MJPH 19-MAY-1999 Sort out line endings for Unix
166 # $VERSION = 0.07; # MJPH 28-APR-1999 Get the regression tests to work
167 # $VERSION = 0.06; # MJPH 26-APR-1999 Start to add to CVS, correct MANIFEST.SKIP
168 # $VERSION = 0.05; # MJPH 13-APR-1999 See changes for 0.05
169 # $VERSION = 0.04; # MJPH 13-MAR-1999 Tidy up Tarball
170 # $VERSION = 0.03; # MJPH 9-MAR-1999 Move to Font::TTF for CPAN
171 # $VERSION = 0.02; # MJPH 12-FEB-1999 Add support for ' nocsum' for DSIGS
175 'table' => 'Font::TTF::Table',
176 'EBDT' => 'Font::TTF::EBDT',
177 'EBLC' => 'Font::TTF::EBLC',
178 'Feat' => 'Font::TTF::GrFeat',
179 'GDEF' => 'Font::TTF::GDEF',
180 'GPOS' => 'Font::TTF::GPOS',
181 'GSUB' => 'Font::TTF::GSUB',
182 'LTSH' => 'Font::TTF::LTSH',
183 'OS/2' => 'Font::TTF::OS_2',
184 'PCLT' => 'Font::TTF::PCLT',
185 'Sill' => 'Font::TTF::Sill',
186 'bsln' => 'Font::TTF::Bsln',
187 'cmap' => 'Font::TTF::Cmap',
188 'cvt ' => 'Font::TTF::Cvt_',
189 'fdsc' => 'Font::TTF::Fdsc',
190 'feat' => 'Font::TTF::Feat',
191 'fmtx' => 'Font::TTF::Fmtx',
192 'fpgm' => 'Font::TTF::Fpgm',
193 'glyf' => 'Font::TTF::Glyf',
194 'hdmx' => 'Font::TTF::Hdmx',
195 'head' => 'Font::TTF::Head',
196 'hhea' => 'Font::TTF::Hhea',
197 'hmtx' => 'Font::TTF::Hmtx',
198 'kern' => 'Font::TTF::Kern',
199 'loca' => 'Font::TTF::Loca',
200 'maxp' => 'Font::TTF::Maxp',
201 'mort' => 'Font::TTF::Mort',
202 'name' => 'Font::TTF::Name',
203 'post' => 'Font::TTF::Post',
204 'prep' => 'Font::TTF::Prep',
205 'prop' => 'Font::TTF::Prop',
206 'vhea' => 'Font::TTF::Vhea',
207 'vmtx' => 'Font::TTF::Vmtx',
210 # This is special code because I am fed up of every time I x a table in the debugger
211 # I get the whole font printed. Thus substitutes my 3 line change to dumpvar into
212 # the debugger. Clunky, but nice. You are welcome to a copy if you want one.
219 if (-f "$p/mydumpvar.pl")
221 $dumper = 'mydumpvar.pl';
225 $dumper ||= 'dumpvar.pl';
229 { do $dumper; &main::dumpValue; }
232 =head2 Font::TTF::Font->AddTable($tablename, $class)
234 Adds the given class to be used when representing the given table name. It also
235 'requires' the class for you.
241 my ($class, $table, $useclass) = @_;
243 $tables{$table} = $useclass;
244 # $useclass =~ s|::|/|oig;
245 # require "$useclass.pm";
249 =head2 Font::TTF::Font->Init
251 For those people who like making fonts without reading them. This subroutine
252 will require all the table code for the various table types for you. Not
253 needed if using Font::TTF::Font::read before using a table.
262 foreach $t (values %tables)
269 =head2 Font::TTF::Font->new(%props)
271 Creates a new font object and initialises with the given properties. This is
272 primarily for use when a TTF is embedded somewhere. Notice that the properties
273 are automatically preceded by a space when inserted into the object. This is in
274 order that fields do not clash with tables.
280 my ($class, %props) = @_;
285 foreach (keys %props)
286 { $self->{" $_"} = $props{$_}; }
291 =head2 Font::TTF::Font->open($fname)
293 Reads the header and directory for the given font file and creates appropriate
294 objects for each table in the font.
300 my ($class, $fname) = @_;
306 $fh = IO::File->new($fname) or return undef;
311 $self->{' INFILE'} = $fh;
312 $self->{' fname'} = $fname;
313 $self->{' OFFSET'} = 0;
321 Reads a Truetype font directory starting from the current location in the file.
322 This has been separated from the C<open> function to allow support for embedded
323 TTFs for example in TTCs. Also reads the C<head> and C<maxp> tables immediately.
330 my ($fh) = $self->{' INFILE'};
331 my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t);
333 $fh->seek($self->{' OFFSET'}, 0);
335 ($ver, $dir_num) = unpack("Nn", $dat);
336 $ver == 1 << 16 || $ver == unpack('N', 'OTTO') || $ver == 0x74727565 or return undef; # support Mac sfnts
338 for ($i = 0; $i < $dir_num; $i++)
340 $fh->read($dat, 16) || die "Reading table entry";
341 ($name, $check, $off, $len) = unpack("a4NNN", $dat);
342 $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) && next
343 if (defined $self->{' PARENT'});
344 $type = $tables{$name} || 'Font::TTF::Table';
347 { $t =~ s/^|::/:/oig; }
349 { $t =~ s|::|/|oig; }
351 $self->{$name} = $type->new(PARENT => $self,
359 foreach $t ('head', 'maxp')
360 { $self->{$t}->read if defined $self->{$t}; }
366 =head2 $f->out($fname [, @tablelist])
368 Writes a TTF file consisting of the tables in tablelist. The list is checked to
369 ensure that only tables that exist are output. (This means that you can't have
370 non table information stored in the font object with key length of exactly 4)
372 In many cases the user simply wants to output all the tables in alphabetical order.
373 This can be done by not including a @tablelist, in which case the subroutine will
374 output all the defined tables in the font in alphabetical order.
376 Returns $f on success and undef on failure, including warnings.
378 All output files must include the C<head> table.
384 my ($self, $fname, @tlist) = @_;
386 my ($dat, $numTables, $sRange, $eSel);
387 my (%dir, $k, $mloc, $count);
388 my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift);
392 $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef;
397 $self->{' oname'} = $fname;
398 $self->{' outfile'} = $fh;
400 if ($self->{' wantsig'})
402 $self->{' nocsum'} = 1;
403 # $self->{'head'}{'checkSumAdjustment'} = 0;
404 $self->{' tempDSIG'} = $self->{'DSIG'};
405 $self->{' tempcsum'} = $self->{'head'}{' CSUM'};
406 delete $self->{'DSIG'};
407 @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}}
408 grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0);
411 { @tlist = sort keys %$self; }
413 @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
414 $numTables = $#tlist + 1;
415 $numTables++ if ($self->{' wantsig'});
417 ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16);
418 $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift);
420 $msum = unpack("%32N*", $dat);
422 # reserve place holders for each directory entry
425 $dir{$k} = pack("A4NNN", $k, 0, 0, 0);
426 $fh->print($dir{$k});
429 $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
434 $fh->print(substr("\000" x 4, $loc & 3));
435 $loc += 4 - ($loc & 3);
441 $self->{$k}->out($fh);
443 $len = $loc - $oldloc;
446 $fh->print(substr("\000" x 4, $loc & 3));
447 $loc += 4 - ($loc & 3);
449 $fh->seek($oldloc, 0);
450 $csum = 0; $mloc = $loc;
451 while ($mloc > $oldloc)
453 $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc;
454 $fh->read($dat, $count);
455 $csum += unpack("%32N*", $dat);
456 # this line ensures $csum stays within 32 bit bounds, clipping as necessary
457 if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
460 $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len);
461 $msum += $csum + unpack("%32N*", $dir{$k});
462 while ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; }
466 unless ($self->{' nocsum'}) # assuming we want a file checksum
468 # Now we need to sort out the head table's checksum
469 if (!defined $dir{'head'})
470 { # you have to have a head table
472 return warn("No 'head' table to output in $fname"), undef;
474 ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
475 $fh->seek($loc + 8, 0);
477 $lsum = unpack("N", $dat);
481 if ($csum < 0) { $csum += 0xffffffff; $csum++; }
482 $msum -= $lsum * 2; # twice (in head and in csum)
483 while ($msum < 0) { $msum += 0xffffffff; $msum++; }
485 $lsum = 0xB1B0AFBA - $msum;
486 $fh->seek($loc + 8, 0);
487 $fh->print(pack("N", $lsum));
488 $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len);
489 } elsif ($self->{' wantsig'})
491 if (!defined $dir{'head'})
492 { # you have to have a head table
494 return warn("No 'head' table to output in $fname"), undef;
496 ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
497 $fh->seek($loc + 8, 0);
498 $fh->print(pack("N", 0));
499 # $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len);
502 # Now we can output the directory again
503 if ($self->{' wantsig'})
504 { @tlist = sort @tlist; }
507 { $fh->print($dir{$k}); }
508 $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
514 =head2 $f->out_xml($filename [, @tables])
516 Outputs the font in XML format
522 my ($self, $fname, @tlist) = @_;
523 my ($fh, $context, $numTables, $k);
525 $context->{'indent'} = ' ' x 4;
529 $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef;
534 unless (scalar @tlist > 0)
536 @tlist = sort keys %$self;
537 @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
539 $numTables = $#tlist + 1;
541 $context->{'fh'} = $fh;
542 $fh->print("<?xml version='1.0' encoding='UTF-8'?>\n");
543 $fh->print("<font tables='$numTables'>\n\n");
547 $fh->print("<table name='$k'>\n");
548 $self->{$k}->out_xml($context, $context->{'indent'});
549 $fh->print("</table>\n");
552 $fh->print("</font>\n");
558 =head2 $f->XML_start($context, $tag, %attrs)
560 Handles start messages from the XML parser. Of particular interest to us are <font> and
567 my ($self, $context, $tag, %attrs) = @_;
568 my ($name, $type, $t);
571 { $context->{'tree'}[-1] = $self; }
572 elsif ($tag eq 'table')
574 $name = $attrs{'name'};
575 unless (defined $self->{$name})
577 $type = $tables{$name} || 'Font::TTF::Table';
580 { $t =~ s/^|::/:/oig; }
582 { $t =~ s|::|/|oig; }
584 $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1);
586 $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name});
595 my ($context, $tag, %attrs) = @_;
598 return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca');
599 if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'})
601 for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++)
602 { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; }
603 $context->{'glyphs'} = $self->{'loca'}{'glyphs'};
610 Sends update to all the tables in the font and then resets all the isDirty
611 flags on each table. The data structure in now consistent as a font (we hope).
619 $self->tables_do(sub { $_[0]->update; });
626 Dirties all the tables in the font
631 { $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; }
633 =head2 $f->tables_do(&func [, tables])
635 Calls &func for each table in the font. Calls the table in alphabetical sort
636 order as per the order in the directory:
638 &func($table, $name);
640 May optionally take a list of table names in which case func is called
641 for each of them in the given order.
646 my ($self, $func, @tables) = @_;
649 foreach $t (@tables ? @tables : sort grep {length($_) == 4} keys %$self)
650 { &$func($self->{$t}, $t); }
657 Releases ALL of the memory used by the TTF font and all of its component
658 objects. After calling this method, do B<NOT> expect to have anything left in
659 the C<Font::TTF::Font> object.
661 B<NOTE>, that it is important that you call this method on any
662 C<Font::TTF::Font> object when you wish to destruct it and free up its memory.
663 Internally, we track things in a structure that can result in circular
664 references, and without calling 'C<release()>' these will not properly get
665 cleaned up by Perl. Once you've called this method, though, don't expect to be
666 able to do anything else with the C<Font::TTF::Font> object; it'll have B<no>
667 internal state whatsoever.
669 B<Developer note:> As part of the brute-force cleanup done here, this method
670 will throw a warning message whenever unexpected key values are found within
671 the C<Font::TTF::Font> object. This is done to help ensure that any unexpected
672 and unfreed values are brought to your attention so that you can bug us to keep
673 the module updated properly; otherwise the potential for memory leaks due to
674 dangling circular references will exist.
682 # delete stuff that we know we can, here
684 my @tofree = map { delete $self->{$_} } keys %{$self};
686 while (my $item = shift @tofree)
688 my $ref = ref($item);
689 if (UNIVERSAL::can($item, 'release'))
690 { $item->release(); }
691 elsif ($ref eq 'ARRAY')
692 { push( @tofree, @{$item} ); }
693 elsif (UNIVERSAL::isa($ref, 'HASH'))
697 # check that everything has gone - it better had!
698 foreach my $key (keys %{$self})
699 { warn ref($self) . " still has '$key' key left after release.\n"; }
706 Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope.
707 The parts of the code which haven't been implemented yet are:
713 Version 4 format types are not supported yet.
717 Format type 2 (MBCS) has not been implemented yet and therefore may cause
718 somewhat spurious results for this table type.
722 Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come).
726 The current Font::TTF::Font::out method does not support the writing of TrueType
731 In addition there are weaknesses or features of this module library
737 There is very little (or no) error reporting. This means that if you have
738 garbled data or garbled data structures, then you are liable to generate duff
743 The exposing of the internal data structures everywhere means that doing
744 radical re-structuring is almost impossible. But it stop the code from becoming
749 Apart from these, I try to keep the code in a state of "no known bugs", which
750 given the amount of testing this code has had, is not a guarantee of high
753 For more details see the appropriate class files.
757 Martin Hosken Martin_Hosken@sil.org
759 Copyright Martin Hosken 1998.
761 No warranty or expression of effectiveness, least of all regarding anyone's
762 safety, is implied in this software or documentation.
766 The Perl TTF module is licensed under the Perl Artistic License.