+++ /dev/null
-package Font::TTF::OS_2;
-
-=head1 NAME
-
-Font::TTF::OS_2 - the OS/2 table in a TTF font
-
-=head1 DESCRIPTION
-
-The OS/2 table has two versions and forms, one an extension of the other. This
-module supports both forms and the switching between them.
-
-=head1 INSTANCE VARIABLES
-
-No other variables than those in table and those in the standard:
-
- Version
- xAvgCharWidth
- usWeightClass
- usWidthClass
- fsType
- ySubscriptXSize
- ySubScriptYSize
- ySubscriptXOffset
- ySubscriptYOffset
- ySuperscriptXSize
- ySuperscriptYSize
- ySuperscriptXOffset
- ySuperscriptYOffset
- yStrikeoutSize
- yStrikeoutPosition
- sFamilyClass
- bFamilyType
- bSerifStyle
- bWeight
- bProportion
- bContrast
- bStrokeVariation
- bArmStyle
- bLetterform
- bMidline
- bXheight
- ulUnicodeRange1
- ulUnicodeRange2
- ulUnicodeRange3
- ulUnicodeRange4
- achVendID
- fsSelection
- usFirstCharIndex
- usLastCharIndex
- sTypoAscender
- sTypoDescender
- sTypoLineGap
- usWinAscent
- usWinDescent
- ulCodePageRange1
- ulCodePageRange2
- xHeight
- CapHeight
- defaultChar
- breakChar
- maxLookups
-
-Notice that versions 0, 1, 2 & 3 of the table are supported. Notice also that the
-Panose variable has been broken down into its elements.
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA @fields @lens @field_info @weights);
-use Font::TTF::Table;
-
-@ISA = qw(Font::TTF::Table);
-@field_info = (
- 'xAvgCharWidth' => 's',
- 'usWeightClass' => 'S',
- 'usWidthClass' => 'S',
- 'fsType' => 's',
- 'ySubscriptXSize' => 's',
- 'ySubScriptYSize' => 's',
- 'ySubscriptXOffset' => 's',
- 'ySubscriptYOffset' => 's',
- 'ySuperscriptXSize' => 's',
- 'ySuperscriptYSize' => 's',
- 'ySuperscriptXOffset' => 's',
- 'ySuperscriptYOffset' => 's',
- 'yStrikeoutSize' => 's',
- 'yStrikeoutPosition' => 's',
- 'sFamilyClass' => 's',
- 'bFamilyType' => 'C',
- 'bSerifStyle' => 'C',
- 'bWeight' => 'C',
- 'bProportion' => 'C',
- 'bContrast' => 'C',
- 'bStrokeVariation' => 'C',
- 'bArmStyle' => 'C',
- 'bLetterform' => 'C',
- 'bMidline' => 'C',
- 'bXheight' => 'C',
- 'ulUnicodeRange1' => 'L',
- 'ulUnicodeRange2' => 'L',
- 'ulUnicodeRange3' => 'L',
- 'ulUnicodeRange4' => 'L',
- 'achVendID' => 'L',
- 'fsSelection' => 'S',
- 'usFirstCharIndex' => 'S',
- 'usLastCharIndex' => 'S',
- 'sTypoAscender' => 'S',
- 'sTypoDescender' => 's',
- 'sTypoLineGap' => 'S',
- 'usWinAscent' => 'S',
- 'usWinDescent' => 'S',
- '' => '',
- 'ulCodePageRange1' => 'L',
- 'ulCodePageRange2' => 'L',
- '' => '',
- 'xHeight' => 's',
- 'CapHeight' => 's',
- 'defaultChar' => 'S',
- 'breakChar' => 'S',
- 'maxLookups' => 's',
- '' => '', # i.e. v3 is basically same as v2
- );
-
-@weights = qw(64 14 27 35 100 20 14 42 63 3 6 35 20 56 56 17 4 49 56 71 31 10 18 3 18 2 166);
-
-use Font::TTF::Utils;
-
-sub init
-{
- my ($k, $v, $c, $n, $i, $t, $j);
-
- $n = 0;
- @lens = (76, 84, 94, 94);
- for ($j = 0; $j < $#field_info; $j += 2)
- {
- if ($field_info[$j] eq '')
- {
- $n++;
- next;
- }
- ($k, $v, $c) = TTF_Init_Fields($field_info[$j], $c, $field_info[$j+1]);
- next unless defined $k && $k ne "";
- for ($i = $n; $i < 4; $i++)
- { $fields[$i]{$k} = $v; }
- }
-}
-
-
-=head2 $t->read
-
-Reads in the various values from disk (see details of OS/2 table)
-
-=cut
-
-sub read
-{
- my ($self) = @_;
- my ($dat, $ver);
-
- $self->SUPER::read or return $self;
-
- init unless defined $fields[2]{'xAvgCharWidth'};
- $self->{' INFILE'}->read($dat, 2);
- $ver = unpack("n", $dat);
- $self->{'Version'} = $ver;
- if ($ver < 4)
- {
- $self->{' INFILE'}->read($dat, $lens[$ver]);
- TTF_Read_Fields($self, $dat, $fields[$ver]);
- }
- $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
- my ($self, $fh) = @_;
- my ($ver);
-
- return $self->SUPER::out($fh) unless $self->{' read'};
-
- $ver = $self->{'Version'};
- $fh->print(pack("n", $ver));
- $fh->print(TTF_Out_Fields($self, $fields[$ver], $lens[$ver]));
- $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $key, $value)
-
-Tidies up the hex values to output them in hex
-
-=cut
-
-sub XML_element
-{
- my ($self) = shift;
- my ($context, $depth, $key, $value) = @_;
- my ($fh) = $context->{'fh'};
-
- if ($key =~ m/^ul(?:Unicode|CodePage)Range\d$/o)
- { $fh->printf("%s<%s>%08X</%s>\n", $depth, $key, $value, $key); }
- elsif ($key eq 'achVendID')
- { $fh->printf("%s<%s name='%s'/>\n", $depth, $key, pack('N', $value)); }
- else
- { return $self->SUPER::XML_element(@_); }
- $self;
-}
-
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Now handle them on the way back in
-
-=cut
-
-sub XML_end
-{
- my ($self) = shift;
- my ($context, $tag, %attrs) = @_;
-
- if ($tag =~ m/^ul(?:Unicode|CodePage)Range\d$/o)
- { return hex($context->{'text'}); }
- elsif ($tag eq 'achVendID')
- { return unpack('N', $attrs{'name'}); }
- else
- { return $self->SUPER::XML_end(@_); }
-}
-
-=head2 $t->update
-
-Updates the OS/2 table by getting information from other sources:
-
-Updates the C<firstChar> and C<lastChar> values based on the MS table in the
-cmap.
-
-Updates the sTypoAscender, sTypoDescender & sTypoLineGap to be the same values
-as Ascender, Descender and Linegap from the hhea table (assuming it is dirty)
-and also sets usWinAscent to be the sum of Ascender+Linegap and usWinDescent to
-be the negative of Descender.
-
-=cut
-
-sub update
-{
- my ($self) = @_;
- my ($map, @keys, $table, $i, $avg, $hmtx);
-
- return undef unless ($self->SUPER::update);
-
- $self->{' PARENT'}{'cmap'}->update;
- $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef;
- $hmtx = $self->{' PARENT'}{'hmtx'}->read;
-
- @keys = sort {$a <=> $b} grep {$_ < 0x10000} keys %{$map->{'val'}};
-
- $self->{'usFirstCharIndex'} = $keys[0];
- $self->{'usLastCharIndex'} = $keys[-1];
-
- $table = $self->{' PARENT'}{'hhea'}->read;
-
- # try any way we can to get some real numbers passed around!
- if (($self->{'fsSelection'} & 128) != 0)
- {
- # assume the user knows what they are doing and has sensible values already
- }
- elsif ($table->{'Ascender'} != 0 || $table->{'Descender'} != 0)
- {
- $self->{'sTypoAscender'} = $table->{'Ascender'};
- $self->{'sTypoDescender'} = $table->{'Descender'};
- $self->{'sTypoLineGap'} = $table->{'LineGap'};
- $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'};
- $self->{'usWinDescent'} = -$self->{'sTypoDescender'};
- }
- elsif ($self->{'sTypoAscender'} != 0 || $self->{'sTypoDescender'} != 0)
- {
- $table->{'Ascender'} = $self->{'sTypoAscender'};
- $table->{'Descender'} = $self->{'sTypoDescender'};
- $table->{'LineGap'} = $self->{'sTypoLineGap'};
- $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'};
- $self->{'usWinDescent'} = -$self->{'sTypoDescender'};
- }
- elsif ($self->{'usWinAscent'} != 0 || $self->{'usWinDescent'} != 0)
- {
- $self->{'sTypoAscender'} = $table->{'Ascender'} = $self->{'usWinAscent'};
- $self->{'sTypoDescender'} = $table->{'Descender'} = -$self->{'usWinDescent'};
- $self->{'sTypoLineGap'} = $table->{'LineGap'} = 0;
- }
-
- if ($self->{'Version'} < 3)
- {
- for ($i = 0; $i < 26; $i++)
- { $avg += $hmtx->{'advance'}[$map->{'val'}{$i + 0x0061}] * $weights[$i]; }
- $avg += $hmtx->{'advance'}[$map->{'val'}{0x0020}] * $weights[-1];
- $self->{'xAvgCharWidth'} = $avg / 1000;
- }
- elsif ($self->{'Version'} > 2)
- {
- $i = 0; $avg = 0;
- foreach (@{$hmtx->{'advance'}})
- {
- next unless ($_);
- $i++;
- $avg += $_;
- }
- $avg /= $i if ($i);
- $self->{'xAvgCharWidth'} = $avg;
- }
-
- foreach $i (keys %{$map->{'val'}})
- {
- if ($i >= 0x10000)
- {
- $self->{'ulUnicodeRange2'} |= 0x2000000;
- last;
- }
- }
-
- $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1);
- $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2);
-
- if ((exists $self->{' PARENT'}{'GPOS'} && $self->{' PARENT'}{'GPOS'}{' read'}) ||
- (exists $self->{' PARENT'}{'GSUB'} && $self->{' PARENT'}{'GSUB'}{' read'}))
- {
- # one or both of GPOS & GSUB exist and have been read or modified; so update usMaxContexts
- my ($lp, $ls);
- $lp = $self->{' PARENT'}{'GPOS'}->maxContext if exists $self->{' PARENT'}{'GPOS'};
- $ls = $self->{' PARENT'}{'GSUB'}->maxContext if exists $self->{' PARENT'}{'GSUB'};
- $self->{'maxLookups'} = $lp > $ls ? $lp : $ls;
- }
-
- $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken@sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut