Blame lib/Font/TTF/Post.pm

Packit 5d935b
package Font::TTF::Post;
Packit 5d935b
Packit 5d935b
=head1 NAME
Packit 5d935b
Packit 5d935b
Font::TTF::Post - Holds the Postscript names for each glyph
Packit 5d935b
Packit 5d935b
=head1 DESCRIPTION
Packit 5d935b
Packit 5d935b
Holds the postscript names for glyphs. Note that they are not held as an
Packit 5d935b
array, but as indexes into two lists. The first list is the standard Postscript
Packit 5d935b
name list defined by the TrueType standard. The second comes from the font
Packit 5d935b
directly.
Packit 5d935b
Packit 5d935b
Looking up a glyph from a Postscript name or a name from a glyph number is
Packit 5d935b
achieved through methods rather than variable lookup.
Packit 5d935b
Packit 5d935b
This class handles PostScript table types of 1, 2, 2.5 & 3, but not version 4.
Packit 5d935b
Support for version 2.5 is as per Apple spec rather than MS.
Packit 5d935b
Packit 5d935b
The way to look up Postscript names or glyphs is:
Packit 5d935b
Packit 5d935b
    $pname = $f->{'post'}{'VAL'}[$gnum];
Packit 5d935b
    $gnum = $f->{'post'}{'STRINGS'}{$pname};
Packit 5d935b
Packit 5d935b
=head1 INSTANCE VARIABLES
Packit 5d935b
Packit 5d935b
Due to different systems having different limitations, there are various class
Packit 5d935b
variables available to control what post table types can be written.
Packit 5d935b
Packit 5d935b
=over 4
Packit 5d935b
Packit 5d935b
=item $Font::TTF::Post::no25
Packit 5d935b
Packit 5d935b
If set tells Font::TTF::Post::out to use table type 2 instead of 2.5 in case apps
Packit 5d935b
cannot handle version 2.5.
Packit 5d935b
Packit 5d935b
=item VAL
Packit 5d935b
Packit 5d935b
Contains an array indexed by glyph number of Postscript names. This is used when
Packit 5d935b
writing out a font.
Packit 5d935b
Packit 5d935b
=item STRINGS
Packit 5d935b
Packit 5d935b
An associative array of Postscript names mapping to the highest glyph with that
Packit 5d935b
name. These may not be in sync with VAL.
Packit 5d935b
Packit 5d935b
=back
Packit 5d935b
Packit 5d935b
In addition there are the standard introductory variables defined in the
Packit 5d935b
standard:
Packit 5d935b
Packit 5d935b
    FormatType
Packit 5d935b
    italicAngle
Packit 5d935b
    underlinePosition
Packit 5d935b
    underlineThickness
Packit 5d935b
    isFixedPitch
Packit 5d935b
    minMemType42
Packit 5d935b
    maxMemType42
Packit 5d935b
    minMemType1
Packit 5d935b
    maxMemType1
Packit 5d935b
Packit 5d935b
=head1 METHODS
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b
use strict;
Packit 5d935b
use vars qw(@ISA @base_set %base_set %fields $VERSION $no25 @field_info @base_set);
Packit 5d935b
require Font::TTF::Table;
Packit 5d935b
use Font::TTF::Utils;
Packit 5d935b
Packit 5d935b
$no25 = 1;                  # officially deprecated format 2.5 tables in MS spec 1.3
Packit 5d935b
Packit 5d935b
@ISA = qw(Font::TTF::Table);
Packit 5d935b
@field_info = (
Packit 5d935b
    'FormatType' => 'f',
Packit 5d935b
    'italicAngle' => 'f',
Packit 5d935b
    'underlinePosition' => 's',
Packit 5d935b
    'underlineThickness' => 's',
Packit 5d935b
    'isFixedPitch' => 'L',
Packit 5d935b
    'minMemType42' => 'L',
Packit 5d935b
    'maxMemType42' => 'L',
Packit 5d935b
    'minMemType1' => 'L',
Packit 5d935b
    'maxMemType1' => 'L');
Packit 5d935b
@base_set = qw(.notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar percent ampersand quotesingle
Packit 5d935b
    parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six
Packit 5d935b
    seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q
Packit 5d935b
    R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore grave a b c d e f g h
Packit 5d935b
    i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla
Packit 5d935b
    Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis atilde aring ccedilla eacute
Packit 5d935b
    egrave ecircumflex edieresis iacute igrave icircumflex idieresis ntilde oacute ograve ocircumflex
Packit 5d935b
    odieresis otilde uacute ugrave ucircumflex udieresis dagger degree cent sterling section bullet
Packit 5d935b
    paragraph germandbls registered copyright trademark acute dieresis notequal AE Oslash infinity
Packit 5d935b
    plusminus lessequal greaterequal yen mu partialdiff summation product pi integral ordfeminine
Packit 5d935b
    ordmasculine Omega ae oslash questiondown exclamdown logicalnot radical florin approxequal
Packit 5d935b
    Delta guillemotleft guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe endash emdash
Packit 5d935b
    quotedblleft quotedblright quoteleft quoteright divide lozenge ydieresis Ydieresis fraction currency
Packit 5d935b
    guilsinglleft guilsinglright fi fl daggerdbl periodcentered quotesinglbase quotedblbase perthousand
Packit 5d935b
    Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex
Packit 5d935b
    apple Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve dotaccent
Packit 5d935b
    ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron scaron Zcaron zcaron brokenbar Eth eth
Packit 5d935b
    Yacute yacute Thorn thorn minus multiply onesuperior twosuperior threesuperior onehalf onequarter
Packit 5d935b
    threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron ccaron dcroat);
Packit 5d935b
Packit 5d935b
$VERSION = 0.01;        # MJPH   5-AUG-1998     Re-organise data structures
Packit 5d935b
Packit 5d935b
sub init
Packit 5d935b
{
Packit 5d935b
    my ($k, $v, $c, $i);
Packit 5d935b
    for ($i = 0; $i < $#field_info; $i += 2)
Packit 5d935b
    {
Packit 5d935b
        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
Packit 5d935b
        next unless defined $k && $k ne "";
Packit 5d935b
        $fields{$k} = $v;
Packit 5d935b
    }
Packit 5d935b
    $i = 0;
Packit 5d935b
    %base_set = map {$_ => $i++} @base_set;
Packit 5d935b
}
Packit 5d935b
Packit 5d935b
Packit 5d935b
=head2 $t->read
Packit 5d935b
Packit 5d935b
Reads the Postscript table into memory from disk
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b
sub read
Packit 5d935b
{
Packit 5d935b
    my ($self) = @_;
Packit 5d935b
    $self->SUPER::read or return $self;
Packit 5d935b
Packit 5d935b
    my ($dat, $dat1, $i, $off, $c, $maxoff, $form, $angle, $numGlyphs);
Packit 5d935b
    my ($fh) = $self->{' INFILE'};
Packit 5d935b
Packit 5d935b
    $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
Packit 5d935b
    init unless ($fields{'FormatType'});
Packit 5d935b
    $fh->read($dat, 32);
Packit 5d935b
    TTF_Read_Fields($self, $dat, \%fields);
Packit 5d935b
Packit 5d935b
    if (int($self->{'FormatType'} + .5) == 1)
Packit 5d935b
    {
Packit 5d935b
        for ($i = 0; $i < 258; $i++)
Packit 5d935b
        {
Packit 5d935b
            $self->{'VAL'}[$i] = $base_set[$i];
Packit 5d935b
            $self->{'STRINGS'}{$base_set[$i]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i]});
Packit 5d935b
        }
Packit 5d935b
    } elsif (int($self->{'FormatType'} * 2 + .1) == 5)
Packit 5d935b
    {
Packit 5d935b
        $fh->read($dat, 2);
Packit 5d935b
        $numGlyphs = unpack("n", $dat);
Packit 5d935b
        $fh->read($dat, $numGlyphs);
Packit 5d935b
        for ($i = 0; $i < $numGlyphs; $i++)
Packit 5d935b
        {
Packit 5d935b
            $off = unpack("c", substr($dat, $i, 1));
Packit 5d935b
            $self->{'VAL'}[$i] = $base_set[$i + $off];
Packit 5d935b
            $self->{'STRINGS'}{$base_set[$i + $off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i + $off]});
Packit 5d935b
        }
Packit 5d935b
    } elsif (int($self->{'FormatType'} + .5) == 2)
Packit 5d935b
    {
Packit 5d935b
        my (@strings);
Packit 5d935b
        
Packit 5d935b
        $fh->read($dat, ($numGlyphs + 1) << 1);
Packit 5d935b
        for ($i = 0; $i < $numGlyphs; $i++)
Packit 5d935b
        {
Packit 5d935b
            $off = unpack("n", substr($dat, ($i + 1) << 1, 2));
Packit 5d935b
            $maxoff = $off if (!defined $maxoff || $off > $maxoff);
Packit 5d935b
        }
Packit 5d935b
        for ($i = 0; $i < $maxoff - 257; $i++)
Packit 5d935b
        {
Packit 5d935b
            $fh->read($dat1, 1);
Packit 5d935b
            $off = unpack("C", $dat1);
Packit 5d935b
            $fh->read($dat1, $off);
Packit 5d935b
            $strings[$i] = $dat1;
Packit 5d935b
        }
Packit 5d935b
        for ($i = 0; $i < $numGlyphs; $i++)
Packit 5d935b
        {
Packit 5d935b
            $off = unpack("n", substr($dat, ($i + 1) << 1, 2));
Packit 5d935b
            if ($off > 257)
Packit 5d935b
            {
Packit 5d935b
                $self->{'VAL'}[$i] = $strings[$off - 258];
Packit 5d935b
                $self->{'STRINGS'}{$strings[$off - 258]} = $i;
Packit 5d935b
            }
Packit 5d935b
            else
Packit 5d935b
            {
Packit 5d935b
                $self->{'VAL'}[$i] = $base_set[$off];
Packit 5d935b
                $self->{'STRINGS'}{$base_set[$off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$off]});
Packit 5d935b
            }
Packit 5d935b
        }
Packit 5d935b
    }
Packit 5d935b
    $self;
Packit 5d935b
}
Packit 5d935b
Packit 5d935b
Packit 5d935b
=head2 $t->out($fh)
Packit 5d935b
Packit 5d935b
Writes out a new Postscript name table from memory or copies from disk
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b
sub out
Packit 5d935b
{
Packit 5d935b
    my ($self, $fh) = @_;
Packit 5d935b
    my ($i, $num);
Packit 5d935b
Packit 5d935b
    return $self->SUPER::out($fh) unless $self->{' read'};
Packit 5d935b
Packit 5d935b
    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
Packit 5d935b
Packit 5d935b
    init unless ($fields{'FormatType'});
Packit 5d935b
Packit 5d935b
    for ($i = $#{$self->{'VAL'}}; !defined $self->{'VAL'}[$i] && $i > 0; $i--)
Packit 5d935b
    { pop(@{$self->{'VAL'}}); }
Packit 5d935b
    if ($#{$self->{'VAL'}} < 0)
Packit 5d935b
    { $self->{'FormatType'} = 3; }
Packit 5d935b
    else
Packit 5d935b
    {
Packit 5d935b
        $self->{'FormatType'} = 1;
Packit 5d935b
        for ($i = 0; $i < $num; $i++)
Packit 5d935b
        {
Packit 5d935b
            if (!defined $base_set{$self->{'VAL'}[$i]})
Packit 5d935b
            {
Packit 5d935b
                $self->{'FormatType'} = 2;
Packit 5d935b
                last;
Packit 5d935b
            }
Packit 5d935b
            elsif ($base_set{$self->{'VAL'}[$i]} != $i)
Packit 5d935b
            { $self->{'FormatType'} = ($no25 ? 2 : 2.5); }
Packit 5d935b
        }
Packit 5d935b
    }
Packit 5d935b
Packit 5d935b
    $fh->print(TTF_Out_Fields($self, \%fields, 32));
Packit 5d935b
Packit 5d935b
    return $self if (int($self->{'FormatType'} + .4) == 3);
Packit 5d935b
Packit 5d935b
    if (int($self->{'FormatType'} + .5) == 2)
Packit 5d935b
    {
Packit 5d935b
        my (@ind);
Packit 5d935b
        my ($count) = 0;
Packit 5d935b
        
Packit 5d935b
        $fh->print(pack("n", $num));
Packit 5d935b
        for ($i = 0; $i < $num; $i++)
Packit 5d935b
        {
Packit 5d935b
            if (defined $base_set{$self->{'VAL'}[$i]})
Packit 5d935b
            { $fh->print(pack("n", $base_set{$self->{'VAL'}[$i]})); }
Packit 5d935b
            else
Packit 5d935b
            {
Packit 5d935b
                $fh->print(pack("n", $count + 258));
Packit 5d935b
                $ind[$count++] = $i;
Packit 5d935b
            }
Packit 5d935b
        }
Packit 5d935b
        for ($i = 0; $i < $count; $i++)
Packit 5d935b
        {
Packit 5d935b
            $fh->print(pack("C", length($self->{'VAL'}[$ind[$i]])));
Packit 5d935b
            $fh->print($self->{'VAL'}[$ind[$i]]);
Packit 5d935b
        }
Packit 5d935b
    } elsif (int($self->{'FormatType'} * 2 + .5) == 5)
Packit 5d935b
    {
Packit 5d935b
        $fh->print(pack("n", $num));
Packit 5d935b
        for ($i = 0; $i < $num; $i++)
Packit 5d935b
        { $fh->print(pack("c", defined $base_set{$self->{'VAL'}[$i]} ?
Packit 5d935b
                    $base_set{$self->{'VAL'}[$i]} - $i : -$i)); }
Packit 5d935b
    }
Packit 5d935b
        
Packit 5d935b
    $self;
Packit 5d935b
}
Packit 5d935b
Packit 5d935b
Packit 5d935b
=head2 $t->XML_element($context, $depth, $key, $val)
Packit 5d935b
Packit 5d935b
Outputs the names as one block of XML
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b
sub XML_element
Packit 5d935b
{
Packit 5d935b
    my ($self) = shift;
Packit 5d935b
    my ($context, $depth, $key, $val) = @_;
Packit 5d935b
    my ($fh) = $context->{'fh'};
Packit 5d935b
    my ($i);
Packit 5d935b
Packit 5d935b
    return $self->SUPER::XML_element(@_) unless ($key eq 'STRINGS' || $key eq 'VAL');
Packit 5d935b
    return unless ($key eq 'VAL');
Packit 5d935b
Packit 5d935b
    $fh->print("$depth<names>\n");
Packit 5d935b
    for ($i = 0; $i <= $#{$self->{'VAL'}}; $i++)
Packit 5d935b
    { $fh->print("$depth$context->{'indent'}<name post='$self->{'VAL'}[$i]' gid='$i'/>\n"); }
Packit 5d935b
    $fh->print("$depth</names>\n");
Packit 5d935b
    $self;
Packit 5d935b
}
Packit 5d935b
Packit 5d935b
=head2 $t->minsize()
Packit 5d935b
Packit 5d935b
Returns the minimum size this table can be. If it is smaller than this, then the table
Packit 5d935b
must be bad and should be deleted or whatever.
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b
sub minsize
Packit 5d935b
{
Packit 5d935b
    return 32;
Packit 5d935b
}
Packit 5d935b
Packit 5d935b
1;
Packit 5d935b
Packit 5d935b
=head1 BUGS
Packit 5d935b
Packit 5d935b
=over 4
Packit 5d935b
Packit 5d935b
=item *
Packit 5d935b
Packit 5d935b
No support for type 4 tables
Packit 5d935b
Packit 5d935b
=back
Packit 5d935b
Packit 5d935b
=head1 AUTHOR
Packit 5d935b
Packit 5d935b
Martin Hosken L<http://scripts.sil.org/FontUtils>. 
Packit 5d935b
Packit 5d935b
Packit 5d935b
=head1 LICENSING
Packit 5d935b
Packit 5d935b
Copyright (c) 1998-2016, SIL International (http://www.sil.org) 
Packit 5d935b
Packit 5d935b
This module is released under the terms of the Artistic License 2.0. 
Packit 5d935b
For details, see the full text of the license in the file LICENSE.
Packit 5d935b
Packit 5d935b
Packit 5d935b
Packit 5d935b
=cut
Packit 5d935b
Packit 5d935b