r1050 - in packages/libfont-ttf-perl/trunk: . debian lib lib/Font/TTF lib/Font/TTF/Kern lib/Font/TTF/Mort

Gunnar Wolf gwolf at costa.debian.org
Sun Jul 17 08:09:14 UTC 2005


Author: gwolf
Date: 2005-05-25 15:22:16 +0000 (Wed, 25 May 2005)
New Revision: 1050

Added:
   packages/libfont-ttf-perl/trunk/META.yml
Removed:
   packages/libfont-ttf-perl/trunk/Examples/
   packages/libfont-ttf-perl/trunk/Make.PM
   packages/libfont-ttf-perl/trunk/Setup.bat
   packages/libfont-ttf-perl/trunk/pmake.bat
   packages/libfont-ttf-perl/trunk/scripts/
Modified:
   packages/libfont-ttf-perl/trunk/MANIFEST
   packages/libfont-ttf-perl/trunk/MANIFEST.SKIP
   packages/libfont-ttf-perl/trunk/Makefile
   packages/libfont-ttf-perl/trunk/Makefile.PL
   packages/libfont-ttf-perl/trunk/README.TXT
   packages/libfont-ttf-perl/trunk/debian/changelog
   packages/libfont-ttf-perl/trunk/debian/control
   packages/libfont-ttf-perl/trunk/debian/watch
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATKern.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATutils.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Anchor.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Bsln.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Changes
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cmap.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Coverage.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cvt_.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Delta.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fdsc.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Feat.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fmtx.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Font.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fpgm.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/GDEF.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/GPOS.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/GSUB.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyf.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyph.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hdmx.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Head.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hhea.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hmtx.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/ClassArray.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/CompactClassArray.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/OrderedList.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/StateTable.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/Subtable.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/LTSH.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Loca.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Manual.pod
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Maxp.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Chain.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Contextual.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Insertion.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Ligature.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Noncontextual.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Rearrangement.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Subtable.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Name.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/OS_2.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldCmap.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldMort.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/PCLT.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/PSNames.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Post.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prep.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prop.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Segarr.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Table.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttc.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttopen.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Useall.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Utils.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vhea.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vmtx.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/Win32.pm
   packages/libfont-ttf-perl/trunk/lib/Font/TTF/XMLparse.pm
   packages/libfont-ttf-perl/trunk/lib/ttfmod.pl
Log:
New upstream version


Modified: packages/libfont-ttf-perl/trunk/MANIFEST
===================================================================
--- packages/libfont-ttf-perl/trunk/MANIFEST	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/MANIFEST	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,21 +1,3 @@
-Examples/StripCmap.plx
-Examples/addpclt.plx
-Examples/makemono.plx
-Examples/symbol.rmp
-Examples/ttfaddname.plx
-Examples/ttfdeltable.plx
-Examples/ttfenc.plx
-Examples/ttfwidth.plx
-Examples/ttunadopter.plx
-Examples/xmldump.plx
-Examples/zerohyph.plx
-MANIFEST
-MANIFEST.SKIP
-Make.PM
-Makefile
-Makefile.PL
-README.TXT
-Setup.bat
 lib/Font/TTF/AATKern.pm
 lib/Font/TTF/AATutils.pm
 lib/Font/TTF/Anchor.pm
@@ -31,10 +13,10 @@
 lib/Font/TTF/Font.pm
 lib/Font/TTF/Fpgm.pm
 lib/Font/TTF/GDEF.pm
-lib/Font/TTF/GPOS.pm
-lib/Font/TTF/GSUB.pm
 lib/Font/TTF/Glyf.pm
 lib/Font/TTF/Glyph.pm
+lib/Font/TTF/GPOS.pm
+lib/Font/TTF/GSUB.pm
 lib/Font/TTF/Hdmx.pm
 lib/Font/TTF/Head.pm
 lib/Font/TTF/Hhea.pm
@@ -45,8 +27,8 @@
 lib/Font/TTF/Kern/OrderedList.pm
 lib/Font/TTF/Kern/StateTable.pm
 lib/Font/TTF/Kern/Subtable.pm
-lib/Font/TTF/LTSH.pm
 lib/Font/TTF/Loca.pm
+lib/Font/TTF/LTSH.pm
 lib/Font/TTF/Manual.pod
 lib/Font/TTF/Maxp.pm
 lib/Font/TTF/Mort.pm
@@ -58,14 +40,14 @@
 lib/Font/TTF/Mort/Rearrangement.pm
 lib/Font/TTF/Mort/Subtable.pm
 lib/Font/TTF/Name.pm
-lib/Font/TTF/OS_2.pm
 lib/Font/TTF/OldCmap.pm
 lib/Font/TTF/OldMort.pm
+lib/Font/TTF/OS_2.pm
 lib/Font/TTF/PCLT.pm
-lib/Font/TTF/PSNames.pm
 lib/Font/TTF/Post.pm
 lib/Font/TTF/Prep.pm
 lib/Font/TTF/Prop.pm
+lib/Font/TTF/PSNames.pm
 lib/Font/TTF/Segarr.pm
 lib/Font/TTF/Table.pm
 lib/Font/TTF/Ttc.pm
@@ -77,11 +59,9 @@
 lib/Font/TTF/Win32.pm
 lib/Font/TTF/XMLparse.pm
 lib/ttfmod.pl
-pmake.bat
-scripts/check_attach.plx
-scripts/eurofix.plx
-scripts/hackos2.plx
-scripts/psfix.plx
-scripts/ttfbuilder.plx
-scripts/ttfname.plx
-scripts/ttfremap.plx
+Makefile
+Makefile.PL
+MANIFEST			This list of files
+MANIFEST.SKIP
+README.TXT
+META.yml                                 Module meta-data (added by MakeMaker)

Modified: packages/libfont-ttf-perl/trunk/MANIFEST.SKIP
===================================================================
--- packages/libfont-ttf-perl/trunk/MANIFEST.SKIP	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/MANIFEST.SKIP	2005-05-25 15:22:16 UTC (rev 1050)
@@ -9,3 +9,4 @@
 exes/
 \.cvsignore
 ^#
+\.svn/

Copied: packages/libfont-ttf-perl/trunk/META.yml (from rev 1049, packages/libfont-ttf-perl/branches/upstream/current/META.yml)

Deleted: packages/libfont-ttf-perl/trunk/Make.PM
===================================================================
--- packages/libfont-ttf-perl/trunk/Make.PM	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/Make.PM	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,1321 +0,0 @@
-package Make::Rule::Vars;
-use Carp;
-use strict;
-my $generation = 0; # lexical cross-package scope used!
-
-# Package to handle 'magic' variables pertaining to rules e.g. $@ $* $^ $?
-# by using tie to this package 'subsvars' can work with array of 
-# hash references to possible sources of variable definitions.
-
-sub TIEHASH
-{
- my ($class,$rule) = @_;
- return bless \$rule,$class;
-}
-
-sub FETCH
-{
- my $self = shift;
- local $_ = shift;
- my $rule = $$self;
- return undef unless (/^[\@^<?*]$/);
- # print STDERR "FETCH $_ for ",$rule->Name,"\n";
- return $rule->Name if ($_ eq '@');
- return $rule->Base if ($_ eq '*');
- return join(' ',$rule->exp_depend)  if ($_ eq '^');
- return join(' ',$rule->out_of_date) if ($_ eq '?');
- # Next one is dubious - I think $< is really more subtle ...
- return ($rule->exp_depend)[0] if ($_ eq '<');
- return undef;
-}
-
-package Make::Rule;
-use Carp;
-use strict;
-
-# Bottom level 'rule' package 
-# An instance exists for each ':' or '::' rule in the makefile.
-# The commands and dependancies are kept here.
-
-sub target
-{
- return shift->{TARGET};
-}
-
-sub Name
-{
- return shift->target->Name;
-}
-
-sub Base
-{
- my $name = shift->target->Name;
- $name =~ s/\.[^.]+$//;
- return $name;
-}
-
-sub Info
-{
- return shift->target->Info;
-}       
-
-sub depend
-{
- my $self = shift;
- if (@_)
-  {            
-   my $name = $self->Name;
-   my $dep = shift;
-   confess "dependants $dep are not an array reference" unless ('ARRAY' eq ref $dep); 
-   my $file;
-   foreach $file (@$dep)
-    {
-     unless (exists $self->{DEPHASH}{$file})
-      {    
-       $self->{DEPHASH}{$file} = 1;
-       push(@{$self->{DEPEND}},$file);
-      }
-    }
-  }
- return (wantarray) ? @{$self->{DEPEND}} : $self->{DEPEND};
-}
-
-sub command
-{
- my $self = shift;
- if (@_)
-  {
-   my $cmd = shift;
-   confess "commands $cmd are not an array reference" unless ('ARRAY' eq ref $cmd); 
-   if (@$cmd)
-    {
-     if (@{$self->{COMMAND}})
-      {
-       warn "Command for ".$self->Name," redefined";
-       print STDERR "Was:",join("\n",@{$self->{COMMAND}}),"\n";
-       print STDERR "Now:",join("\n",@$cmd),"\n";
-      }
-     $self->{COMMAND} = $cmd;
-    }
-   else
-    {
-     if (@{$self->{COMMAND}})
-      { 
-       # warn "Command for ".$self->Name," retained";
-       # print STDERR "Was:",join("\n",@{$self->{COMMAND}}),"\n";
-      }
-    } 
-  }
- return (wantarray) ? @{$self->{COMMAND}} : $self->{COMMAND};
-}
-
-#
-# The key make test - is target out-of-date as far as this rule is concerned
-# In scalar context - boolean value of 'do we need to apply the rule'
-# In list context the things we are out-of-date with e.g. magic $? variable
-#
-sub out_of_date
-{
- my $array = wantarray;
- my $self  = shift;
- my $info  = $self->Info;
- my @dep = ();
- my $tdate  = $self->target->date;
- my $dep;
- my $count = 0;
- foreach $dep ($self->exp_depend)
-  {
-   my $date = $info->date($dep);
-   $count++;
-   if (!defined($date) || !defined($tdate) || $date < $tdate)
-    {       
-     # warn $self->Name." ood wrt ".$dep."\n";
-     return 1 unless $array;
-     push(@dep,$dep);
-    }
-  }
- return @dep if $array;
- # Note special case of no dependencies means it is always  out-of-date!
- return !$count;
-}
-
-#
-# Return list of things rule depends on with variables expanded
-# - May need pathname and vpath processing as well
-#
-sub exp_depend
-{
- my $self = shift;
- my $info = $self->Info;
- my @dep = map(split(/\s+/,$info->subsvars($_)),$self->depend);
- return (wantarray) ? @dep : \@dep;
-}
-
-#
-# Return commands to apply rule with variables expanded
-# - No pathname processing needed, commands should always chdir()
-#   to logical place (at least till we get very clever at bourne shell parsing).
-# - May need vpath processing
-#
-sub exp_command
-{
- my $self   = shift;
- my $info   = $self->Info;
- my $base   = $self->Name;
- my %var;
- tie %var,'Make::Rule::Vars',$self;
- my @cmd  = map($info->subsvars($_,\%var),$self->command);
- return (wantarray) ? @cmd : \@cmd;
-}
-
-#
-# clone creates a new rule derived from an existing rule, but 
-# with a different target. Used when left hand side was a variable.
-# perhaps should be used for dot/pattern rule processing too.
-#
-sub clone
-{
- my ($self,$target) = @_;
- my %hash = %$self;
- $hash{TARGET} = $target;
- $hash{DEPEND} = [@{$self->{DEPEND}}];
- $hash{DEPHASH} = {%{$self->{DEPHASH}}};
- my $obj = bless \%hash,ref $self;
- return $obj;
-}
-
-sub new
-{
- my $class = shift;
- my $target = shift;
- my $kind   = shift;
- my $self = bless { TARGET => $target,             # parent target (left hand side)
-                    KIND => $kind,                 # : or ::
-                    DEPEND => [], DEPHASH => {},   # right hand args
-                    COMMAND => []                  # command(s)  
-                  },$class;        
- $self->depend(shift) if (@_);
- $self->command(shift) if (@_);
- return $self;
-}
-
-#
-# This code has to go somewhere but no good home obvious yet.
-#  - only applies to ':' rules, but needs top level database
-#  - perhaps in ->commands of derived ':' class?
-#
-sub find_commands
-{
- my ($self) = @_;
- if (!@{$self->{COMMAND}} && @{$self->{DEPEND}})
-  {
-   my $info = $self->Info;
-   my $name = $self->Name;
-   my @dep  = $self->depend;
-   my @rule = $info->patrule($self->Name);
-   if (@rule)
-    {
-     $self->depend($rule[0]);
-     $self->command($rule[1]);
-    }
-  }
-}
-
-#
-# Spew a shell script to perfom the 'make' e.g. make -n 
-#
-sub Script
-{
- my $self = shift;
- return unless $self->out_of_date;
- my @cmd = $self->exp_command;
- if (@cmd)
-  {
-   my $file;
-  my $com = ($^O eq 'MSWin32') ? 'rem ': '# ';
-   print  $com,$self->Name,"\n";
-   foreach $file ($self->exp_command)
-    {
-     $file =~ s/^[\@\s-]*//;
-     print "$file\n";
-    }
-  }
-}
-
-#
-# Normal 'make' method
-#
-sub Make
-{
- my $self = shift;
- my $file;
- return unless ($self->out_of_date);
- my @cmd = $self->exp_command;
- my $info = $self->Info;
- if (@cmd)
-  {
-   foreach my $file ($self->exp_command)
-    {
-     $file =~ s/^([\@\s-]*)//;
-     my $prefix = $1;
-     print  "$file\n" unless ($prefix =~ /\@/);
-     my $code = $info->exec($file);
-     if ($code && $prefix !~ /-/)
-      {
-       die "Code $code from $file";
-      }
-    }
-  }
-}
-
-#
-# Print rule out in makefile syntax 
-# - currently has variables expanded as debugging aid.
-# - will eventually become make -p 
-# - may be useful for writing makefiles from MakeMaker too...
-#
-sub Print
-{
- my $self = shift;
- my $file;
- print $self->Name,' ',$self->{KIND},' ';
- foreach $file ($self->depend)
-  {
-   print " \\\n   $file";
-  }
- print "\n";
- my @cmd = $self->exp_command;
- if (@cmd)
-  {
-   foreach $file ($self->exp_command)
-    {
-     print "\t",$file,"\n";
-    }
-  }
- else
-  {
-   print STDERR "No commands for ",$self->Name,"\n" unless ($self->target->phony); 
-  }
- print "\n";
-}
-
-package Make::Target;
-use Carp;
-use strict;
-use Cwd;
-
-#
-# Intermediate 'target' package
-# There is an instance of this for each 'target' that apears on 
-# the left hand side of a rule i.e. for each thing that can be made.
-# 
-sub new
-{
- my ($class,$info,$target) = @_;
- return bless { NAME => $target,     # name of thing
-                MAKEFILE => $info,   # Makefile context 
-                Pass => 0            # Used to determine if 'done' this sweep
-              },$class;
-}
-
-sub date
-{
- my $self = shift;
- my $info = $self->Info;
- return $info->date($self->Name);
-}
-
-sub phony
-{
- my $self = shift;
- return $self->Info->phony($self->Name);
-}   
-
-
-sub colon
-{
- my $self = shift;
- if (@_)
-  {
-   if (exists $self->{COLON})
-    {
-     my $dep = $self->{COLON};
-     if (@_ == 1)
-      {            
-       # merging an existing rule
-       my $other = shift;
-       $dep->depend(scalar $other->depend);
-       $dep->command(scalar $other->command);
-      }
-     else
-      {
-       $dep->depend(shift);
-       $dep->command(shift);
-      }
-    }
-   else
-    {
-     $self->{COLON} = (@_ == 1) ? shift->clone($self) : Make::Rule->new($self,':', at _);
-    }
-  }
- if (exists $self->{COLON})
-  {
-   return (wantarray) ? ($self->{COLON}) : $self->{COLON};
-  }
- else
-  {
-   return (wantarray) ? () : undef;
-  }
-}
-
-sub dcolon
-{
- my $self = shift;
- if (@_)
-  {
-   my $rule = (@_ == 1) ? shift->clone($self) : Make::Rule->new($self,'::', at _);
-   $self->{DCOLON} = [] unless (exists $self->{DCOLON});
-   push(@{$self->{DCOLON}},$rule);
-  }
- return (exists $self->{DCOLON}) ? @{$self->{DCOLON}} : ();
-}
-
-sub Name
-{
- return shift->{NAME};
-}
-
-sub Info
-{
- return shift->{MAKEFILE};
-}
-
-sub ProcessColon
-{
- my ($self) = @_;
- my $c = $self->colon;
- $c->find_commands if $c;
-}
-
-sub ExpandTarget
-{
- my ($self) = @_;
- my $target = $self->Name;
- my $info   = $self->Info;
- my $colon  = delete $self->{COLON};
- my $dcolon = delete $self->{DCOLON};
- foreach my $expand (split(/\s+/,$info->subsvars($target)))
-  {
-   next unless defined($expand);
-   my $t = $info->Target($expand);
-   if (defined $colon)
-    {
-     $t->colon($colon); 
-    }
-   foreach my $d (@{$dcolon})
-    {
-     $t->dcolon($d);
-    }
-  }
-}
-
-sub done
-{
- my $self = shift;
- my $info = $self->Info;
- my $pass = $info->pass;
- return 1 if ($self->{Pass} == $pass);
- $self->{Pass} = $pass;
- return 0;
-}
-
-sub recurse
-{
- my ($self,$method, at args) = @_;
- my $info = $self->Info;
- my $rule;
- my $i = 0;
- foreach $rule ($self->colon,$self->dcolon)
-  {
-   my $dep;
-   my $j = 0;
-   foreach $dep ($rule->exp_depend)
-    {
-     my $t = $info->{Depend}{$dep};
-     if (defined $t)
-      {
-       $t->$method(@args) 
-      }
-     else
-      {
-       unless ($info->exists($dep))
-        {
-         my $dir = cwd();                                      
-         die "Cannot recurse $method - no target $dep in $dir" 
-        }
-      }
-    }
-  }
-}
-
-sub Script
-{
- my $self = shift;
- my $info = $self->Info;
- my $rule = $self->colon;
- return if ($self->done);
- $self->recurse('Script');
- foreach $rule ($self->colon,$self->dcolon)
-  {
-   $rule->Script;
-  }
-}
-
-sub Make
-{
- my $self = shift;
- my $info = $self->Info;
- my $rule = $self->colon;
- return if ($self->done);
- $self->recurse('Make');
- foreach $rule ($self->colon,$self->dcolon)
-  {
-   $rule->Make;
-  }
-}
-
-sub Print
-{
- my $self = shift;
- my $info = $self->Info;
- return if ($self->done);
- my $rule = $self->colon;
- foreach $rule ($self->colon,$self->dcolon)
-  {
-   $rule->Print;
-  }
- $self->recurse('Print');
-}
-
-package Make;
-use 5.005;  # Need look-behind assertions
-use Carp;
-use strict;
-use Config;
-use Cwd;
-use File::Spec;
-use vars qw($VERSION);
-$VERSION = '1.00';
-
-my %date;
-
-sub phony
-{
- my ($self,$name) = @_;
- return exists $self->{PHONY}{$name};
-}
-
-sub suffixes
-{
- my ($self) = @_;
- return keys %{$self->{'SUFFIXES'}};
-}
-
-#
-# Construct a new 'target' (or find old one)
-# - used by parser to add to data structures
-#
-sub Target
-{
- my ($self,$target) = @_;
- unless (exists $self->{Depend}{$target})
-  {
-   my $t = Make::Target->new($self,$target);
-   $self->{Depend}{$target} = $t;
-  if ($target =~ /%/)
-   {
-    $self->{Pattern}{$target} = $t;
-   }
-  elsif ($target =~ /^\./)
-   {
-    $self->{Dot}{$target} = $t;
-   }
-  else
-   {
-    push(@{$self->{Targets}},$t);
-   }
-  }
- return $self->{Depend}{$target};
-}
-
-#
-# Utility routine for patching %.o type 'patterns'
-#
-sub patmatch
-{
- my $key = shift;
- local $_ = shift;
- my $pat = $key;
- $pat =~ s/\./\\./;
- $pat =~ s/%/(\[^\/\]*)/;
- if (/$pat$/)
-  {
-   return $1;
-  }
- return undef;
-}
-
-#
-# old vpath lookup routine 
-#
-sub locate
-{
- my $self = shift;
- local $_ = shift;
- return $_ if (-r $_);
- my $key;
- foreach $key (keys %{$self->{vpath}})
-  {
-   my $Pat;
-   if (defined($Pat = patmatch($key,$_)))
-    {
-     my $dir;
-     foreach $dir (split(/:/,$self->{vpath}{$key}))
-      {
-       return "$dir/$_"  if (-r "$dir/$_");
-      }
-    }
-  }
- return undef;
-}
-
-#
-# Convert traditional .c.o rules into GNU-like into %o : %c
-#
-sub dotrules
-{
- my ($self) = @_;
- my $t;
- foreach $t (keys %{$self->{Dot}})
-  {
-   my $e = $self->subsvars($t);
-   $self->{Dot}{$e} = delete $self->{Dot}{$t} unless ($t eq $e);
-  }
- my (@suffix) = $self->suffixes;
- foreach $t (@suffix)
-  {
-   my $d;
-   my $r = delete $self->{Dot}{$t};
-   if (defined $r)
-    {
-     my @rule = ($r->colon) ? ($r->colon->depend) : ();
-     if (@rule)
-      {
-       delete $self->{Dot}{$t->Name};
-       print STDERR $t->Name," has dependants\n";
-       push(@{$self->{Targets}},$r);
-      }
-     else
-      {
-       # print STDERR "Build \% : \%$t\n";                   
-       $self->Target('%')->dcolon(['%'.$t],scalar $r->colon->command);
-      }
-    }
-   foreach $d (@suffix)
-    {
-     $r = delete $self->{Dot}{$t.$d};
-     if (defined $r)
-      {
-       # print STDERR "Build \%$d : \%$t\n";
-       $self->Target('%'.$d)->dcolon(['%'.$t],scalar $r->colon->command);
-      }
-    }
-  }
- foreach $t (keys %{$self->{Dot}})
-  {
-   push(@{$self->{Targets}},delete $self->{Dot}{$t});
-  }
-}
-
-#
-# Return 'full' pathname of name given directory info. 
-# - may be the place to do vpath stuff ?
-#               
-
-my %pathname;
-
-sub pathname
-{
- my ($self,$name) = @_;
- my $hash = $self->{'Pathname'}; 
- unless (exists $hash->{$name})
-  {
-   if (File::Spec->file_name_is_absolute($name))
-    {
-     $hash->{$name} = $name;
-    }
-   else
-    {
-     $name =~ s,^\./,,;                             
-     $hash->{$name} = File::Spec->catfile($self->{Dir},$name);
-    }
-  }
- return $hash->{$name};
- 
-}
-
-#
-# Return modified date of name if it exists
-# 
-sub date
-{
- my ($self,$name) = @_;
- my $path = $self->pathname($name);
- unless (exists $date{$path})
-  {
-   $date{$path} = -M $path;
-  }
- return $date{$path};
-}
-
-#
-# Check to see if name is a target we can make or an existing
-# file - used to see if pattern rules are valid
-# - Needs extending to do vpath lookups
-#
-sub exists
-{
- my ($self,$name) = @_;
- return 1 if (exists $self->{Depend}{$name});
- return 1 if defined $self->date($name);
- # print STDERR "$name '$path' does not exist\n";
- return 0;
-}
-
-#
-# See if we can find a %.o : %.c rule for target
-# .c.o rules are already converted to this form 
-#
-sub patrule
-{
- my ($self,$target) = @_;
- my $key;
- # print STDERR "Trying pattern for $target\n";
- foreach $key (keys %{$self->{Pattern}})
-  {
-   my $Pat;
-   if (defined($Pat = patmatch($key,$target)))
-    {
-     my $t = $self->{Pattern}{$key};
-     my $rule;
-     foreach $rule ($t->dcolon)
-      {
-       my @dep = $rule->exp_depend;
-       if (@dep)
-        {
-         my $dep = $dep[0];
-         $dep =~ s/%/$Pat/g;
-         # print STDERR "Try $target : $dep\n";
-         if ($self->exists($dep)) 
-          {
-           foreach (@dep)
-            {
-             s/%/$Pat/g;
-            }
-           return (\@dep,scalar $rule->command);
-          }
-        }
-      }
-    }
-  }
- return ();
-}
-
-#
-# Old code to handle vpath stuff - not used yet
-#
-sub needs
-{my ($self,$target) = @_;
- unless ($self->{Done}{$target})
-  {
-   if (exists $self->{Depend}{$target})
-    {
-     my @depend = split(/\s+/,$self->subsvars($self->{Depend}{$target}));
-     foreach (@depend)
-      {
-       $self->needs($_);
-      }
-    }
-   else
-    {
-     my $vtarget = $self->locate($target);
-     if (defined $vtarget)
-      {
-       $self->{Need}{$vtarget} = $target;
-      }
-     else
-      {
-       $self->{Need}{$target}  = $target;
-      }
-    }
-  }
-}
-
-#
-# Substitute $(xxxx) and $x style variable references
-# - should handle ${xxx} as well
-# - recurses till they all go rather than doing one level,
-#   which may need fixing
-#
-sub subsvars
-{
- my $self = shift;
- local $_ = shift;
- my @var = @_;
- push(@var,$self->{Override},$self->{Vars},\%ENV);
- croak("Trying to subsitute undef value") unless (defined $_); 
- while (/(?<!\$)\$\(([^()]+)\)/ || /(?<!\$)\$([<\@^?*])/)
-  {
-   my ($key,$head,$tail) = ($1,$`,$');
-   my $value;
-   if ($key =~ /^([\w._]+|\S)(?::(.*))?$/)
-    {
-     my ($var,$op) = ($1,$2);
-     foreach my $hash (@var)
-      {
-       $value = $hash->{$var};
-       if (defined $value)
-        {
-         last; 
-        }
-      }
-     unless (defined $value)
-      {
-       die "$var not defined in '$_'" unless (length($var) > 1); 
-       $value = '';
-      }
-     if (defined $op)
-      {
-       if ($op =~ /^s(.).*\1.*\1/)
-        {
-         local $_ = $self->subsvars($value);
-         $op =~ s/\\/\\\\/g;
-         eval $op.'g';
-         $value = $_;
-        }
-       else
-        {
-         die "$var:$op = '$value'\n"; 
-        }   
-      }
-    }
-   elsif ($key =~ /wildcard\s*(.*)$/)
-    {
-     $value = join(' ',glob($self->pathname($1)));
-    }
-   elsif ($key =~ /shell\s*(.*)$/)
-    {
-     $value = join(' ',split('\n',`$1`));
-    }
-   elsif ($key =~ /addprefix\s*([^,]*),(.*)$/)
-    {
-     $value = join(' ',map($1 . $_,split('\s+',$2)));
-    }
-   elsif ($key =~ /notdir\s*(.*)$/)
-    {
-     my @files = split(/\s+/,$1);
-     foreach (@files)
-      {
-       s#^.*/([^/]*)$#$1#;
-      }
-     $value = join(' ', at files);
-    }
-   elsif ($key =~ /dir\s*(.*)$/)
-    {
-     my @files = split(/\s+/,$1);
-     foreach (@files)
-      {
-       s#^(.*)/[^/]*$#$1#;
-      }
-     $value = join(' ', at files);
-    }
-   elsif ($key =~ /^subst\s+([^,]*),([^,]*),(.*)$/)
-    {
-     my ($a,$b) = ($1,$2);
-     $value = $3;
-     $a =~ s/\./\\./;
-     $value =~ s/$a/$b/; 
-    }
-   elsif ($key =~ /^mktmp,(\S+)\s*(.*)$/)
-    {
-     my ($file,$content) = ($1,$2);
-     open(TMP,">$file") || die "Cannot open $file:$!";
-     $content =~ s/\\n//g;
-     print TMP $content;
-     close(TMP);
-     $value = $file;
-    }
-   else
-    {
-     warn "Cannot evaluate '$key' in '$_'\n";
-    }
-   $_ = "$head$value$tail";
-  }
- s/\$\$/\$/g;
- return $_;
-}
-
-#
-# Split a string into tokens - like split(/\s+/,...) but handling
-# $(keyword ...) with embedded \s
-# Perhaps should also understand "..." and '...' ?
-#
-sub tokenize
-{
- local $_ = $_[0];
- my @result = ();
- s/\s+$//;
- while (length($_))
-  {
-   s/^\s+//;
-   last unless (/^\S/);
-   my $token = "";
-   while (/^\S/)
-    {
-     if (s/^\$([\(\{])//)
-      {
-       $token .= $&; 
-       my $paren = $1 eq '(';
-       my $brace = $1 eq '{';
-       my $count = 1;
-       while (length($_) && ($paren || $brace))
-        {
-         s/^.//;
-         $token .= $&; 
-         $paren += ($& eq '(');
-         $paren -= ($& eq ')');
-         $brace += ($& eq '{');
-         $brace -= ($& eq '}');
-        }
-       die "Mismatched {} in $_[0]" if ($brace);
-       die "Mismatched () in $_[0]" if ($paren);
-      }
-     elsif (s/^(\$\S?|[^\s\$]+)//)
-      {
-       $token .= $&;
-      }
-    }
-   push(@result,$token);
-  }
- return (wantarray) ? @result : \@result;
-}
-
-
-#
-# read makefile (or fragment of one) either as a result
-# of a command line, or an 'include' in another makefile.
-# 
-sub makefile
-{
- my ($self,$makefile,$name) = @_;
- local $_;
- print STDERR "Reading $name\n";
-Makefile:
- while (<$makefile>)
-  {
-   last unless (defined $_);
-   chomp($_);
-   if (/\\$/)
-    {
-     chop($_);
-     s/\s*$//;
-     my $more = <$makefile>;
-     $more =~ s/^\s*/ /; 
-     $_ .= $more;
-     redo;
-    }
-   next if (/^\s*#/);
-   next if (/^\s*$/);
-   s/#.*$//;
-   s/^\s+//;
-   if (/^(-?)include\s+(.*)$/)
-    {
-     my $opt = $1;
-     my $file;
-     foreach $file (tokenize($self->subsvars($2)))
-      {
-       local *Makefile;
-       my $path = $self->pathname($file);
-       if (open(Makefile,"<$path"))
-        {
-         $self->makefile(\*Makefile,$path);
-         close(Makefile);
-        }
-       else
-        {
-         warn "Cannot open $path:$!" unless ($opt eq '-') ;
-        }
-      }
-    }
-   elsif (/^\s*([\w._]+)\s*:?=\s*(.*)$/)
-    {
-     $self->{Vars}{$1} = (defined $2) ? $2 : "";
-#    print STDERR "$1 = ",$self->{Vars}{$1},"\n";
-    }
-   elsif (/^vpath\s+(\S+)\s+(.*)$/)
-    {my ($pat,$path) = ($1,$2);
-     $self->{Vpath}{$pat} = $path;
-    }
-   elsif (/^\s*([^:]*)(::?)\s*(.*)$/)
-    {
-     my ($target,$kind,$depend) = ($1,$2,$3);
-     my @cmnds;
-     if ($depend =~ /^([^;]*);(.*)$/)
-      {
-       ($depend,$cmnds[0])  = ($1,$2);
-      }
-     while (<$makefile>)
-      {
-       next if (/^\s*#/);
-       next if (/^\s*$/);
-       last unless (/^\t/);
-       chop($_);         
-       if (/\\$/)        
-        {                
-         chop($_);
-         $_ .= ' ';
-         $_ .= <$makefile>;
-         redo;           
-        }                
-       next if (/^\s*$/);
-       s/^\s+//;
-       push(@cmnds,$_);
-      }
-     $depend =~ s/\s\s+/ /;
-     $target =~ s/\s\s+/ /;
-     my @depend = tokenize($depend);
-     foreach (tokenize($target))
-      {
-       my $t = $self->Target($_);
-       my $index = 0;
-       if ($kind eq '::' || /%/)
-        {
-         $t->dcolon(\@depend,\@cmnds);
-        }
-       else
-        {
-         $t->colon(\@depend,\@cmnds);
-        }
-      }
-     redo Makefile;
-    }
-   else
-    {
-     warn "Ignore '$_'\n";
-    }
-  }
-}
-
-sub pseudos
-{
- my $self = shift;
- my $key;
- foreach $key (qw(SUFFIXES PHONY PRECIOUS PARALLEL))
-  {
-   my $t = delete $self->{Dot}{'.'.$key};
-   if (defined $t)
-    {
-     my $dep;
-     $self->{$key} = {};
-     foreach $dep ($t->colon->exp_depend)
-      {
-       $self->{$key}{$dep} = 1;
-      }
-    }
-  }
-}
-
-
-sub ExpandTarget
-{
- my $self = shift;
- foreach my $t (@{$self->{'Targets'}})
-  {
-   $t->ExpandTarget;
-  }
- foreach my $t (@{$self->{'Targets'}})
-  {
-   $t->ProcessColon;
-  }
-}
-
-sub parse
-{
- my ($self,$file) = @_;
- if (defined $file)
-  {
-   $file = $self->pathname($file);
-  }
- else
-  {
-   my @files = qw(makefile Makefile);
-   unshift(@files,'GNUmakefile') if ($self->{GNU});
-   my $name;
-   foreach $name (@files)
-    {
-     $file = $self->pathname($name);
-     if (-r $file)
-      {
-       $self->{Makefile} = $name;
-       last; 
-      }
-    }
-  }
- local (*Makefile);
- open(Makefile,"<$file") || croak("Cannot open $file:$!");
- $self->makefile(\*Makefile,$file);
- close(Makefile);
-
- # Next bits should really be done 'lazy' on need.
-
- $self->pseudos;         # Pull out .SUFFIXES etc. 
- $self->dotrules;        # Convert .c.o into %.o : %.c
-}
-
-sub PrintVars
-{
- my $self = shift;
- local $_;
- foreach (keys %{$self->{Vars}})
-  {
-   print "$_ = ",$self->{Vars}{$_},"\n";
-  }
- print "\n";
-}
-
-sub exec
-{
- my $self = shift;
- undef %date;
- $generation++;
- if ($^O eq 'MSWin32')
-  {
-   my $cwd = cwd();
-   my $ret;
-   chdir $self->{Dir};
-   $ret = system(@_);
-   chdir $cwd;
-   return $ret;
-  }
- else
-  {
-   my $pid  = fork;
-   if ($pid)
-    {
-     waitpid $pid,0;
-     return $?;
-    }
-   else
-    {
-     my $dir = $self->{Dir}; 
-     chdir($dir) || die "Cannot cd to $dir";
-     # handle leading VAR=value here ?
-     # To handle trivial cases like ': libpTk.a' force using /bin/sh
-     exec("/bin/sh","-c", at _) || confess "Cannot exec ".join(' ', at _);
-    }
-  }
-}
-
-sub NextPass { shift->{Pass}++ }
-sub pass     { shift->{Pass} }
-
-sub apply
-{
- my $self = shift;
- my $method = shift;
- $self->NextPass;
- my @targets = ();
- # print STDERR join(' ',Apply => $method, at _),"\n";
- foreach (@_)
-  {
-   if (/^(\w+)=(.*)$/)
-    {
-     # print STDERR "OVERRIDE: $1 = $2\n";
-     $self->{Override}{$1} = $2;
-    }
-   else
-    {
-     push(@targets,$_);
-    }
-  }
- #
- # This expansion is dubious as it alters the database
- # as a function of current values of Override.
- # 
- $self->ExpandTarget;    # Process $(VAR) : 
- @targets = ($self->{'Targets'}[0])->Name unless (@targets);
- # print STDERR join(' ',Targets => $method,map($_->Name, at targets)),"\n";
- foreach (@targets)
-  {
-   my $t = $self->{Depend}{$_};
-   unless (defined $t)
-    {
-     print STDERR join(' ',$method, at _),"\n";
-     die "Cannot `$method' - no target $_" 
-    }
-   $t->$method();
-  }
-}
-
-sub Script
-{
- shift->apply(Script => @_);
-}
-
-sub Print
-{
- shift->apply(Print => @_);
-}
-
-sub Make
-{
- shift->apply(Make => @_);
-}
-
-sub new
-{
- my ($class,%args) = @_;
- unless (defined $args{Dir})
-  {
-   chomp($args{Dir} = getcwd());
-  }
- my $self = bless { %args, 
-                   Pattern  => {},  # GNU style %.o : %.c 
-                   Dot      => {},  # Trad style .c.o
-                   Vpath    => {},  # vpath %.c info 
-                   Vars     => {},  # Variables defined in makefile
-                   Depend   => {},  # hash of targets
-                   Targets  => [],  # ordered version so we can find 1st one
-                   Pass     => 0,   # incremented each sweep
-                   Pathname => {},  # cache of expanded names
-                   Need     => {},
-                   Done     => {},
-                 },$class;
- $self->{Vars}{CC}     = $Config{cc};
- $self->{Vars}{AR}     = $Config{ar};
- $self->{Vars}{CFLAGS} = $Config{optimize};
- $self->makefile(\*DATA,__FILE__);
- $self->parse($self->{Makefile});
- return $self;
-}
-
-=head1 NAME
-
-Make - module for processing makefiles 
-
-=head1 SYNOPSIS
-
-	require Make;
-	my $make = Make->new(...);
-	$make->parse($file);   
-	$make->Script(@ARGV)
-	$make->Make(@ARGV)
-	$make->Print(@ARGV)
-
-        my $targ = $make->Target($name);
-        $targ->colon([dependancy...],[command...]);
-        $targ->dolon([dependancy...],[command...]);
-        my @depends  = $targ->colon->depend;
-        my @commands = $targ->colon->command;
-
-=head1 DESCRIPTION
-
-Make->new creates an object if C<new(Makefile =E<gt> $file)> is specified
-then it is parsed. If not the usual makefile Makefile sequence is 
-used. (If GNU => 1 is passed to new then GNUmakefile is looked for first.) 
-
-C<$make-E<gt>Make(target...)> 'makes' the target(s) specified
-(or the first 'real' target in the makefile).
-
-C<$make-E<gt>Print> can be used to 'print' to current C<select>'ed stream
-a form of the makefile with all variables expanded. 
-
-C<$make-E<gt>Script(target...)> can be used to 'print' to 
-current C<select>'ed stream the equivalent bourne shell script
-that a make would perform i.e. the output of C<make -n>.
-
-There are other methods (used by parse) which can be used to add and 
-manipulate targets and their dependants. There is a hierarchy of classes
-which is still evolving. These classes and their methods will be documented when
-they are a little more stable.
-
-The syntax of makefile accepted is reasonably generic, but I have not re-read
-any documentation yet, rather I have implemented my own mental model of how
-make works (then fixed it...).
-
-In addition to traditional 
-
-	.c.o : 
-		$(CC) -c ...
-
-GNU make's 'pattern' rules e.g. 
-
-	%.o : %.c 
-		$(CC) -c ...
-
-Likewise a subset of GNU makes $(function arg...) syntax is supported.
-
-Via pmake Make has built perl/Tk from the C<MakeMaker> generated Makefiles...
-
-=head1 BUGS
-
-At present C<new> must always find a makefile, and
-C<$make-E<gt>parse($file)> can only be used to augment that file.
-
-More attention needs to be given to using the package to I<write> makefiles.
-
-The rules for matching 'dot rules' e.g. .c.o   and/or pattern rules e.g. %.o : %.c
-are suspect. For example give a choice of .xs.o vs .xs.c + .c.o behaviour
-seems a little odd.
-
-Variables are probably substituted in different 'phases' of the process
-than in make(1) (or even GNU make), so 'clever' uses will probably not
-work.
-
-UNIXisms abound. 
-
-=head1 SEE ALSO 
-
-L<pmake>
-
-=head1 AUTHOR
-
-Nick Ing-Simmons
-
-=cut 
-
-1;
-#
-# Remainder of file is in makefile syntax and constitutes
-# the built in rules
-#
-__DATA__
-
-.SUFFIXES: .o .c .y .h .sh .cps
-
-.c.o :
-	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 
-
-.c   :
-	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $< $(LDFLAGS) $(LDLIBS)
-
-.y.o:
-	$(YACC) $<
-	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ y.tab.c
-	$(RM) y.tab.c
-
-.y.c:
-	$(YACC) $<
-	mv y.tab.c $@
-
-

Modified: packages/libfont-ttf-perl/trunk/Makefile
===================================================================
--- packages/libfont-ttf-perl/trunk/Makefile	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/Makefile	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,97 +1,141 @@
 # This Makefile is for the Font::TTF extension to perl.
 #
 # It was generated automatically by MakeMaker version
-# 5.45 (Revision: 1.222) from the contents of
+# 6.17 (Revision: 1.133) from the contents of
 # Makefile.PL. Don't edit this file, edit Makefile.PL instead.
 #
-#	ANY CHANGES MADE HERE WILL BE LOST!
+#       ANY CHANGES MADE HERE WILL BE LOST!
 #
 #   MakeMaker ARGV: ()
 #
 #   MakeMaker Parameters:
 
-#	ABSTRACT => q[TTF font support for Perl]
-#	AUTHOR => q[martin_hosken at sil.org]
-#	EXE_FILES => [q[scripts/check_attach.plx], q[scripts/eurofix.plx], q[scripts/hackos2.plx], q[scripts/psfix.plx], q[scripts/ttfbuilder.plx], q[scripts/ttfname.plx], q[scripts/ttfremap.plx]]
-#	NAME => q[Font::TTF]
-#	VERSION_FROM => q[lib/Font/TTF/Font.pm]
-#	dist => { TO_UNIX=>q[perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"] }
+#     ABSTRACT => q[TTF font support for Perl]
+#     AUTHOR => q[martin_hosken at sil.org]
+#     NAME => q[Font::TTF]
+#     VERSION_FROM => q[lib/Font/TTF/Font.pm]
+#     dist => { TO_UNIX=>q[perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"] }
 
 # --- MakeMaker post_initialize section:
 
 
 # --- MakeMaker const_config section:
 
-# These definitions are from config.sh (via D:/Progs/Perl/lib/Config.pm)
+# These definitions are from config.sh (via /usr/lib/perl5/5.8.5/i586-linux-thread-multi/Config.pm)
 
 # They may have been overridden via Makefile.PL or on the command line
-AR = lib
-CC = cl
-CCCDLFLAGS =  
-CCDLFLAGS =  
-DLEXT = dll
-DLSRC = dl_win32.xs
-LD = link
-LDDLFLAGS = -dll -nologo -nodefaultlib -release  -libpath:"D:\Progs\Perl\lib\CORE"  -machine:x86
-LDFLAGS = -nologo -nodefaultlib -release  -libpath:"D:\Progs\Perl\lib\CORE"  -machine:x86
-LIBC = msvcrt.lib
-LIB_EXT = .lib
-OBJ_EXT = .obj
-OSNAME = MSWin32
-OSVERS = 4.0
-RANLIB = rem
-SO = dll
-EXE_EXT = .exe
-FULL_AR = 
+AR = ar
+CC = cc
+CCCDLFLAGS = -fPIC
+CCDLFLAGS = -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE
+DLEXT = so
+DLSRC = dl_dlopen.xs
+LD = cc
+LDDLFLAGS = -shared
+LDFLAGS = 
+LIBC = 
+LIB_EXT = .a
+OBJ_EXT = .o
+OSNAME = linux
+OSVERS = 2.6.8.1
+RANLIB = :
+SITELIBEXP = /usr/lib/perl5/site_perl/5.8.5
+SITEARCHEXP = /usr/lib/perl5/site_perl/5.8.5/i586-linux-thread-multi
+SO = so
+EXE_EXT = 
+FULL_AR = /usr/bin/ar
+VENDORARCHEXP = /usr/lib/perl5/vendor_perl/5.8.5/i586-linux-thread-multi
+VENDORLIBEXP = /usr/lib/perl5/vendor_perl/5.8.5
 
 
 # --- MakeMaker constants section:
 AR_STATIC_ARGS = cr
+DIRFILESEP = /
 NAME = Font::TTF
-DISTNAME = Font-TTF
 NAME_SYM = Font_TTF
-VERSION = 0.34
-VERSION_SYM = 0_34
-XS_VERSION = 0.34
-INST_BIN = blib\bin
-INST_EXE = blib\script
-INST_LIB = blib\lib
-INST_ARCHLIB = blib\arch
-INST_SCRIPT = blib\script
-PREFIX = D:\Progs\Perl
-INSTALLDIRS = site
-INSTALLPRIVLIB = $(PREFIX)\lib
-INSTALLARCHLIB = $(PREFIX)\lib
-INSTALLSITELIB = D:\Progs\Perl\site\lib
-INSTALLSITEARCH = D:\Progs\Perl\site\lib
-INSTALLBIN = $(PREFIX)\bin
-INSTALLSCRIPT = $(PREFIX)\bin
-PERL_LIB = D:\Progs\Perl\lib
-PERL_ARCHLIB = D:\Progs\Perl\lib
-SITELIBEXP = D:\Progs\Perl\site\lib
-SITEARCHEXP = D:\Progs\Perl\site\lib
-LIBPERL_A = libperl.lib
-FIRST_MAKEFILE = Makefile
-MAKE_APERL_FILE = Makefile.aperl
-PERLMAINCC = $(CC)
-PERL_INC = D:\Progs\Perl\lib\CORE
-PERL = D:\Progs\Perl\bin\Perl.exe
-FULLPERL = D:\Progs\Perl\bin\Perl.exe
-
+VERSION = 0.35
 VERSION_MACRO = VERSION
+VERSION_SYM = 0_35
 DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\"
+XS_VERSION = 0.35
 XS_VERSION_MACRO = XS_VERSION
 XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"
+INST_ARCHLIB = blib/arch
+INST_SCRIPT = blib/script
+INST_BIN = blib/bin
+INST_LIB = blib/lib
+INST_MAN1DIR = blib/man1
+INST_MAN3DIR = blib/man3
+MAN1EXT = 1
+MAN3EXT = 3pm
+INSTALLDIRS = site
+DESTDIR = 
+PREFIX = 
+PERLPREFIX = /usr
+SITEPREFIX = /usr
+VENDORPREFIX = /usr
+INSTALLPRIVLIB = $(PERLPREFIX)/lib/perl5/5.8.5
+DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB)
+INSTALLSITELIB = $(SITEPREFIX)/lib/perl5/site_perl/5.8.5
+DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB)
+INSTALLVENDORLIB = $(VENDORPREFIX)/lib/perl5/vendor_perl/5.8.5
+DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB)
+INSTALLARCHLIB = $(PERLPREFIX)/lib/perl5/5.8.5/i586-linux-thread-multi
+DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB)
+INSTALLSITEARCH = $(SITEPREFIX)/lib/perl5/site_perl/5.8.5/i586-linux-thread-multi
+DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH)
+INSTALLVENDORARCH = $(VENDORPREFIX)/lib/perl5/vendor_perl/5.8.5/i586-linux-thread-multi
+DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH)
+INSTALLBIN = $(PERLPREFIX)/bin
+DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN)
+INSTALLSITEBIN = $(SITEPREFIX)/bin
+DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN)
+INSTALLVENDORBIN = $(VENDORPREFIX)/bin
+DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN)
+INSTALLSCRIPT = $(PERLPREFIX)/bin
+DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT)
+INSTALLMAN1DIR = $(PERLPREFIX)/share/man/man1
+DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR)
+INSTALLSITEMAN1DIR = $(SITEPREFIX)/share/man/man1
+DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR)
+INSTALLVENDORMAN1DIR = $(VENDORPREFIX)/share/man/man1
+DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR)
+INSTALLMAN3DIR = $(PERLPREFIX)/share/man/man3
+DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR)
+INSTALLSITEMAN3DIR = $(SITEPREFIX)/share/man/man3
+DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR)
+INSTALLVENDORMAN3DIR = $(VENDORPREFIX)/share/man/man3
+DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR)
+PERL_LIB = /usr/lib/perl5/5.8.5
+PERL_ARCHLIB = /usr/lib/perl5/5.8.5/i586-linux-thread-multi
+LIBPERL_A = libperl.a
+FIRST_MAKEFILE = Makefile
+MAKEFILE_OLD = $(FIRST_MAKEFILE).old
+MAKE_APERL_FILE = $(FIRST_MAKEFILE).aperl
+PERLMAINCC = $(CC)
+PERL_INC = /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE
+PERL = /usr/bin/perl
+FULLPERL = /usr/bin/perl
+ABSPERL = $(PERL)
+PERLRUN = $(PERL)
+FULLPERLRUN = $(FULLPERL)
+ABSPERLRUN = $(ABSPERL)
+PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
+FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
+ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
+PERL_CORE = 0
+PERM_RW = 644
+PERM_RWX = 755
 
-MAKEMAKER = 
-MM_VERSION = 5.45
+MAKEMAKER   = /usr/lib/perl5/5.8.5/ExtUtils/MakeMaker.pm
+MM_VERSION  = 6.17
+MM_REVISION = 1.133
 
 # FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
 # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
-# ROOTEXT = Directory part of FULLEXT with leading slash (eg /DBD)  !!! Deprecated from MM 5.32  !!!
 # PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
 # DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
-FULLEXT = Font\TTF
+FULLEXT = Font/TTF
 BASEEXT = TTF
 PARENT_NAME = Font
 DLBASE = $(BASEEXT)
@@ -101,52 +145,87 @@
 LINKTYPE = dynamic
 
 # Handy lists of source code files:
-XS_FILES= 
-C_FILES = 
-O_FILES = 
-H_FILES = 
-HTMLLIBPODS    = 
-HTMLSCRIPTPODS = 
+XS_FILES = 
+C_FILES  = 
+O_FILES  = 
+H_FILES  = 
 MAN1PODS = 
-MAN3PODS = 
-HTMLEXT = html
-INST_MAN1DIR = 
-INSTALLMAN1DIR = 
-MAN1EXT = 1
-INST_MAN3DIR = 
-INSTALLMAN3DIR = 
-MAN3EXT = 3
+MAN3PODS = lib/Font/TTF/AATKern.pm \
+	lib/Font/TTF/Anchor.pm \
+	lib/Font/TTF/Bsln.pm \
+	lib/Font/TTF/Cmap.pm \
+	lib/Font/TTF/Coverage.pm \
+	lib/Font/TTF/Cvt_.pm \
+	lib/Font/TTF/Delta.pm \
+	lib/Font/TTF/Fdsc.pm \
+	lib/Font/TTF/Feat.pm \
+	lib/Font/TTF/Fmtx.pm \
+	lib/Font/TTF/Font.pm \
+	lib/Font/TTF/Fpgm.pm \
+	lib/Font/TTF/GDEF.pm \
+	lib/Font/TTF/GPOS.pm \
+	lib/Font/TTF/GSUB.pm \
+	lib/Font/TTF/Glyf.pm \
+	lib/Font/TTF/Glyph.pm \
+	lib/Font/TTF/Hdmx.pm \
+	lib/Font/TTF/Head.pm \
+	lib/Font/TTF/Hhea.pm \
+	lib/Font/TTF/Hmtx.pm \
+	lib/Font/TTF/Kern.pm \
+	lib/Font/TTF/Kern/ClassArray.pm \
+	lib/Font/TTF/Kern/CompactClassArray.pm \
+	lib/Font/TTF/Kern/OrderedList.pm \
+	lib/Font/TTF/Kern/StateTable.pm \
+	lib/Font/TTF/Kern/Subtable.pm \
+	lib/Font/TTF/LTSH.pm \
+	lib/Font/TTF/Loca.pm \
+	lib/Font/TTF/Manual.pod \
+	lib/Font/TTF/Maxp.pm \
+	lib/Font/TTF/Mort.pm \
+	lib/Font/TTF/Mort/Chain.pm \
+	lib/Font/TTF/Mort/Contextual.pm \
+	lib/Font/TTF/Mort/Insertion.pm \
+	lib/Font/TTF/Mort/Ligature.pm \
+	lib/Font/TTF/Mort/Noncontextual.pm \
+	lib/Font/TTF/Mort/Rearrangement.pm \
+	lib/Font/TTF/Mort/Subtable.pm \
+	lib/Font/TTF/Name.pm \
+	lib/Font/TTF/OS_2.pm \
+	lib/Font/TTF/OldCmap.pm \
+	lib/Font/TTF/OldMort.pm \
+	lib/Font/TTF/PCLT.pm \
+	lib/Font/TTF/PSNames.pm \
+	lib/Font/TTF/Post.pm \
+	lib/Font/TTF/Prep.pm \
+	lib/Font/TTF/Prop.pm \
+	lib/Font/TTF/Segarr.pm \
+	lib/Font/TTF/Table.pm \
+	lib/Font/TTF/Ttc.pm \
+	lib/Font/TTF/Ttopen.pm \
+	lib/Font/TTF/Utils.pm \
+	lib/Font/TTF/Vhea.pm \
+	lib/Font/TTF/Vmtx.pm \
+	lib/Font/TTF/XMLparse.pm
 
-# work around a famous dec-osf make(1) feature(?):
-makemakerdflt: all
-
-.SUFFIXES: .xs .c .C .cpp .cxx .cc $(OBJ_EXT)
-
-# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to recall, that
-# some make implementations will delete the Makefile when we rebuild it. Because
-# we call false(1) when we rebuild it. So make(1) is not completely wrong when it
-# does so. Our milage may vary.
-# .PRECIOUS: Makefile    # seems to be not necessary anymore
-
-.PHONY: all config static dynamic test linkext manifest
-
 # Where is the Config information that we are using/depend on
-CONFIGDEP = $(PERL_ARCHLIB)\Config.pm $(PERL_INC)\config.h
+CONFIGDEP = $(PERL_ARCHLIB)$(DIRFILESEP)Config.pm $(PERL_INC)$(DIRFILESEP)config.h
 
-# Where to put things:
-INST_LIBDIR      = $(INST_LIB)\Font
-INST_ARCHLIBDIR  = $(INST_ARCHLIB)\Font
+# Where to build things
+INST_LIBDIR      = $(INST_LIB)/Font
+INST_ARCHLIBDIR  = $(INST_ARCHLIB)/Font
 
-INST_AUTODIR     = $(INST_LIB)\auto\$(FULLEXT)
-INST_ARCHAUTODIR = $(INST_ARCHLIB)\auto\$(FULLEXT)
+INST_AUTODIR     = $(INST_LIB)/auto/$(FULLEXT)
+INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT)
 
-INST_STATIC  =
-INST_DYNAMIC =
-INST_BOOT    =
+INST_STATIC      = 
+INST_DYNAMIC     = 
+INST_BOOT        = 
 
-EXPORT_LIST = TTF.def
+# Extra linker info
+EXPORT_LIST        = 
+PERL_ARCHIVE       = 
+PERL_ARCHIVE_AFTER = 
 
-PERL_ARCHIVE = $(PERL_INC)\perl56.lib
 
 TO_INST_PM = lib/Font/TTF/AATKern.pm \
 	lib/Font/TTF/AATutils.pm \
@@ -210,206 +289,191 @@
 	lib/Font/TTF/XMLparse.pm \
 	lib/ttfmod.pl
 
-PM_TO_BLIB = lib/Font/TTF/Kern/ClassArray.pm \
-	$(INST_LIB)\Font\TTF\Kern\ClassArray.pm \
-	lib/Font/TTF/Anchor.pm \
-	$(INST_LIB)\Font\TTF\Anchor.pm \
+PM_TO_BLIB = lib/Font/TTF/Vmtx.pm \
+	blib/lib/Font/TTF/Vmtx.pm \
+	lib/Font/TTF/Hhea.pm \
+	blib/lib/Font/TTF/Hhea.pm \
+	lib/ttfmod.pl \
+	blib/lib/ttfmod.pl \
+	lib/Font/TTF/Kern/ClassArray.pm \
+	blib/lib/Font/TTF/Kern/ClassArray.pm \
 	lib/Font/TTF/Head.pm \
-	$(INST_LIB)\Font\TTF\Head.pm \
-	lib/Font/TTF/PCLT.pm \
-	$(INST_LIB)\Font\TTF\PCLT.pm \
+	blib/lib/Font/TTF/Head.pm \
+	lib/Font/TTF/Fmtx.pm \
+	blib/lib/Font/TTF/Fmtx.pm \
+	lib/Font/TTF/AATKern.pm \
+	blib/lib/Font/TTF/AATKern.pm \
+	lib/Font/TTF/OldMort.pm \
+	blib/lib/Font/TTF/OldMort.pm \
+	lib/Font/TTF/Bsln.pm \
+	blib/lib/Font/TTF/Bsln.pm \
+	lib/Font/TTF/Manual.pod \
+	blib/lib/Font/TTF/Manual.pod \
+	lib/Font/TTF/Font.pm \
+	blib/lib/Font/TTF/Font.pm \
+	lib/Font/TTF/GDEF.pm \
+	blib/lib/Font/TTF/GDEF.pm \
+	lib/Font/TTF/Vhea.pm \
+	blib/lib/Font/TTF/Vhea.pm \
+	lib/Font/TTF/Fpgm.pm \
+	blib/lib/Font/TTF/Fpgm.pm \
+	lib/Font/TTF/GSUB.pm \
+	blib/lib/Font/TTF/GSUB.pm \
+	lib/Font/TTF/Mort/Contextual.pm \
+	blib/lib/Font/TTF/Mort/Contextual.pm \
+	lib/Font/TTF/OS_2.pm \
+	blib/lib/Font/TTF/OS_2.pm \
+	lib/Font/TTF/Useall.pm \
+	blib/lib/Font/TTF/Useall.pm \
+	lib/Font/TTF/Ttc.pm \
+	blib/lib/Font/TTF/Ttc.pm \
+	lib/Font/TTF/Feat.pm \
+	blib/lib/Font/TTF/Feat.pm \
+	lib/Font/TTF/Name.pm \
+	blib/lib/Font/TTF/Name.pm \
+	lib/Font/TTF/Kern.pm \
+	blib/lib/Font/TTF/Kern.pm \
+	lib/Font/TTF/Kern/StateTable.pm \
+	blib/lib/Font/TTF/Kern/StateTable.pm \
+	lib/Font/TTF/OldCmap.pm \
+	blib/lib/Font/TTF/OldCmap.pm \
+	lib/Font/TTF/Segarr.pm \
+	blib/lib/Font/TTF/Segarr.pm \
+	lib/Font/TTF/Changes \
+	blib/lib/Font/TTF/Changes \
+	lib/Font/TTF/Loca.pm \
+	blib/lib/Font/TTF/Loca.pm \
+	lib/Font/TTF/Mort/Insertion.pm \
+	blib/lib/Font/TTF/Mort/Insertion.pm \
+	lib/Font/TTF/Mort/Chain.pm \
+	blib/lib/Font/TTF/Mort/Chain.pm \
 	lib/Font/TTF/Mort/Rearrangement.pm \
-	$(INST_LIB)\Font\TTF\Mort\Rearrangement.pm \
-	lib/Font/TTF/Vmtx.pm \
-	$(INST_LIB)\Font\TTF\Vmtx.pm \
-	lib/Font/TTF/Mort/Noncontextual.pm \
-	$(INST_LIB)\Font\TTF\Mort\Noncontextual.pm \
-	lib/Font/TTF/Mort/Chain.pm \
-	$(INST_LIB)\Font\TTF\Mort\Chain.pm \
-	lib/Font/TTF/Bsln.pm \
-	$(INST_LIB)\Font\TTF\Bsln.pm \
-	lib/Font/TTF/Post.pm \
-	$(INST_LIB)\Font\TTF\Post.pm \
+	blib/lib/Font/TTF/Mort/Rearrangement.pm \
+	lib/Font/TTF/Fdsc.pm \
+	blib/lib/Font/TTF/Fdsc.pm \
 	lib/Font/TTF/Cvt_.pm \
-	$(INST_LIB)\Font\TTF\Cvt_.pm \
+	blib/lib/Font/TTF/Cvt_.pm \
+	lib/Font/TTF/XMLparse.pm \
+	blib/lib/Font/TTF/XMLparse.pm \
 	lib/Font/TTF/Maxp.pm \
-	$(INST_LIB)\Font\TTF\Maxp.pm \
-	lib/Font/TTF/OS_2.pm \
-	$(INST_LIB)\Font\TTF\OS_2.pm \
-	lib/Font/TTF/Ttc.pm \
-	$(INST_LIB)\Font\TTF\Ttc.pm \
+	blib/lib/Font/TTF/Maxp.pm \
+	lib/Font/TTF/AATutils.pm \
+	blib/lib/Font/TTF/AATutils.pm \
+	lib/Font/TTF/Prop.pm \
+	blib/lib/Font/TTF/Prop.pm \
+	lib/Font/TTF/Coverage.pm \
+	blib/lib/Font/TTF/Coverage.pm \
+	lib/Font/TTF/PCLT.pm \
+	blib/lib/Font/TTF/PCLT.pm \
+	lib/Font/TTF/Mort/Ligature.pm \
+	blib/lib/Font/TTF/Mort/Ligature.pm \
 	lib/Font/TTF/Win32.pm \
-	$(INST_LIB)\Font\TTF\Win32.pm \
-	lib/Font/TTF/Fmtx.pm \
-	$(INST_LIB)\Font\TTF\Fmtx.pm \
-	lib/Font/TTF/Name.pm \
-	$(INST_LIB)\Font\TTF\Name.pm \
-	lib/Font/TTF/Delta.pm \
-	$(INST_LIB)\Font\TTF\Delta.pm \
-	lib/Font/TTF/Kern/CompactClassArray.pm \
-	$(INST_LIB)\Font\TTF\Kern\CompactClassArray.pm \
-	lib/Font/TTF/Mort.pm \
-	$(INST_LIB)\Font\TTF\Mort.pm \
+	blib/lib/Font/TTF/Win32.pm \
 	lib/Font/TTF/Utils.pm \
-	$(INST_LIB)\Font\TTF\Utils.pm \
-	lib/Font/TTF/Loca.pm \
-	$(INST_LIB)\Font\TTF\Loca.pm \
-	lib/Font/TTF/Fpgm.pm \
-	$(INST_LIB)\Font\TTF\Fpgm.pm \
+	blib/lib/Font/TTF/Utils.pm \
+	lib/Font/TTF/Ttopen.pm \
+	blib/lib/Font/TTF/Ttopen.pm \
 	lib/Font/TTF/Kern/Subtable.pm \
-	$(INST_LIB)\Font\TTF\Kern\Subtable.pm \
-	lib/Font/TTF/GPOS.pm \
-	$(INST_LIB)\Font\TTF\GPOS.pm \
-	lib/Font/TTF/OldMort.pm \
-	$(INST_LIB)\Font\TTF\OldMort.pm \
-	lib/Font/TTF/Vhea.pm \
-	$(INST_LIB)\Font\TTF\Vhea.pm \
-	lib/Font/TTF/Manual.pod \
-	$(INST_LIB)\Font\TTF\Manual.pod \
-	lib/Font/TTF/Ttopen.pm \
-	$(INST_LIB)\Font\TTF\Ttopen.pm \
-	lib/Font/TTF/Cmap.pm \
-	$(INST_LIB)\Font\TTF\Cmap.pm \
-	lib/Font/TTF/Prop.pm \
-	$(INST_LIB)\Font\TTF\Prop.pm \
-	lib/Font/TTF/LTSH.pm \
-	$(INST_LIB)\Font\TTF\LTSH.pm \
-	lib/Font/TTF/Mort/Subtable.pm \
-	$(INST_LIB)\Font\TTF\Mort\Subtable.pm \
+	blib/lib/Font/TTF/Kern/Subtable.pm \
 	lib/Font/TTF/Hmtx.pm \
-	$(INST_LIB)\Font\TTF\Hmtx.pm \
-	lib/Font/TTF/AATutils.pm \
-	$(INST_LIB)\Font\TTF\AATutils.pm \
+	blib/lib/Font/TTF/Hmtx.pm \
 	lib/Font/TTF/Kern/OrderedList.pm \
-	$(INST_LIB)\Font\TTF\Kern\OrderedList.pm \
-	lib/Font/TTF/Kern/StateTable.pm \
-	$(INST_LIB)\Font\TTF\Kern\StateTable.pm \
-	lib/Font/TTF/Fdsc.pm \
-	$(INST_LIB)\Font\TTF\Fdsc.pm \
-	lib/Font/TTF/XMLparse.pm \
-	$(INST_LIB)\Font\TTF\XMLparse.pm \
-	lib/Font/TTF/OldCmap.pm \
-	$(INST_LIB)\Font\TTF\OldCmap.pm \
-	lib/Font/TTF/Table.pm \
-	$(INST_LIB)\Font\TTF\Table.pm \
-	lib/Font/TTF/Glyf.pm \
-	$(INST_LIB)\Font\TTF\Glyf.pm \
-	lib/Font/TTF/Mort/Ligature.pm \
-	$(INST_LIB)\Font\TTF\Mort\Ligature.pm \
-	lib/Font/TTF/GSUB.pm \
-	$(INST_LIB)\Font\TTF\GSUB.pm \
+	blib/lib/Font/TTF/Kern/OrderedList.pm \
+	lib/Font/TTF/Glyph.pm \
+	blib/lib/Font/TTF/Glyph.pm \
+	lib/Font/TTF/Mort.pm \
+	blib/lib/Font/TTF/Mort.pm \
+	lib/Font/TTF/Prep.pm \
+	blib/lib/Font/TTF/Prep.pm \
+	lib/Font/TTF/Kern/CompactClassArray.pm \
+	blib/lib/Font/TTF/Kern/CompactClassArray.pm \
 	lib/Font/TTF/Hdmx.pm \
-	$(INST_LIB)\Font\TTF\Hdmx.pm \
-	lib/Font/TTF/AATKern.pm \
-	$(INST_LIB)\Font\TTF\AATKern.pm \
-	lib/Font/TTF/Coverage.pm \
-	$(INST_LIB)\Font\TTF\Coverage.pm \
-	lib/Font/TTF/Prep.pm \
-	$(INST_LIB)\Font\TTF\Prep.pm \
-	lib/Font/TTF/Mort/Insertion.pm \
-	$(INST_LIB)\Font\TTF\Mort\Insertion.pm \
-	lib/Font/TTF/Mort/Contextual.pm \
-	$(INST_LIB)\Font\TTF\Mort\Contextual.pm \
-	lib/Font/TTF/GDEF.pm \
-	$(INST_LIB)\Font\TTF\GDEF.pm \
+	blib/lib/Font/TTF/Hdmx.pm \
+	lib/Font/TTF/Cmap.pm \
+	blib/lib/Font/TTF/Cmap.pm \
+	lib/Font/TTF/GPOS.pm \
+	blib/lib/Font/TTF/GPOS.pm \
 	lib/Font/TTF/PSNames.pm \
-	$(INST_LIB)\Font\TTF\PSNames.pm \
-	lib/Font/TTF/Font.pm \
-	$(INST_LIB)\Font\TTF\Font.pm \
-	lib/Font/TTF/Feat.pm \
-	$(INST_LIB)\Font\TTF\Feat.pm \
-	lib/ttfmod.pl \
-	$(INST_LIB)\ttfmod.pl \
-	lib/Font/TTF/Kern.pm \
-	$(INST_LIB)\Font\TTF\Kern.pm \
-	lib/Font/TTF/Glyph.pm \
-	$(INST_LIB)\Font\TTF\Glyph.pm \
-	lib/Font/TTF/Changes \
-	$(INST_LIB)\Font\TTF\Changes \
-	lib/Font/TTF/Useall.pm \
-	$(INST_LIB)\Font\TTF\Useall.pm \
-	lib/Font/TTF/Hhea.pm \
-	$(INST_LIB)\Font\TTF\Hhea.pm \
-	lib/Font/TTF/Segarr.pm \
-	$(INST_LIB)\Font\TTF\Segarr.pm
+	blib/lib/Font/TTF/PSNames.pm \
+	lib/Font/TTF/Mort/Noncontextual.pm \
+	blib/lib/Font/TTF/Mort/Noncontextual.pm \
+	lib/Font/TTF/Post.pm \
+	blib/lib/Font/TTF/Post.pm \
+	lib/Font/TTF/Anchor.pm \
+	blib/lib/Font/TTF/Anchor.pm \
+	lib/Font/TTF/Glyf.pm \
+	blib/lib/Font/TTF/Glyf.pm \
+	lib/Font/TTF/LTSH.pm \
+	blib/lib/Font/TTF/LTSH.pm \
+	lib/Font/TTF/Table.pm \
+	blib/lib/Font/TTF/Table.pm \
+	lib/Font/TTF/Delta.pm \
+	blib/lib/Font/TTF/Delta.pm \
+	lib/Font/TTF/Mort/Subtable.pm \
+	blib/lib/Font/TTF/Mort/Subtable.pm
 
 
+# --- MakeMaker platform_constants section:
+MM_Unix_VERSION = 1.42
+PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc
+
+
 # --- MakeMaker tool_autosplit section:
-
 # Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
-AUTOSPLITFILE = $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MAutoSplit  -e "autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1);"
+AUTOSPLITFILE = $(PERLRUN)  -e 'use AutoSplit;  autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)'
 
 
+
 # --- MakeMaker tool_xsubpp section:
 
 
 # --- MakeMaker tools_other section:
-
-SHELL = cmd /x /c
-CHMOD = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e chmod
-CP = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp
-LD = link
-MV = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mv
-NOOP = rem
-RM_F = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f
-RM_RF = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_rf
-TEST_F = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e test_f
-TOUCH = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e touch
+SHELL = /bin/sh
+CHMOD = chmod
+CP = cp
+MV = mv
+NOOP = $(SHELL) -c true
+NOECHO = @
+RM_F = rm -f
+RM_RF = rm -rf
+TEST_F = test -f
+TOUCH = touch
 UMASK_NULL = umask 0
-DEV_NULL = > NUL
+DEV_NULL = > /dev/null 2>&1
+MKPATH = $(PERLRUN) "-MExtUtils::Command" -e mkpath
+EQUALIZE_TIMESTAMP = $(PERLRUN) "-MExtUtils::Command" -e eqtime
+ECHO = echo
+ECHO_N = echo -n
+UNINST = 0
+VERBINST = 0
+MOD_INSTALL = $(PERLRUN) -MExtUtils::Install -e 'install({@ARGV}, '\''$(VERBINST)'\'', 0, '\''$(UNINST)'\'');'
+DOC_INSTALL = $(PERLRUN) "-MExtUtils::Command::MM" -e perllocal_install
+UNINSTALL = $(PERLRUN) "-MExtUtils::Command::MM" -e uninstall
+WARN_IF_OLD_PACKLIST = $(PERLRUN) "-MExtUtils::Command::MM" -e warn_if_old_packlist
 
-# The following is a portable way to say mkdir -p
-# To see which directories are created, change the if 0 to if 1
-MKPATH = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mkpath
 
-# This helps us to minimize the effect of the .exists files A yet
-# better solution would be to have a stable file in the perl
-# distribution with a timestamp of zero. But this solution doesn't
-# need any changes to the core distribution and works with older perls
-EQUALIZE_TIMESTAMP = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e eqtime
+# --- MakeMaker makemakerdflt section:
+makemakerdflt: all
+	$(NOECHO) $(NOOP)
 
-# Here we warn users that an old packlist file was found somewhere,
-# and that they should call some uninstall routine
-WARN_IF_OLD_PACKLIST = $(PERL) -lwe "exit unless -f $$ARGV[0];" \
--e "print 'WARNING: I have found an old package in';" \
--e "print '	', $$ARGV[0], '.';" \
--e "print 'Please make sure the two installations are not conflicting';"
 
-UNINST=0
-VERBINST=1
-
-MOD_INSTALL = $(PERL) -I$(INST_LIB) -I$(PERL_LIB) -MExtUtils::Install \
--e "install({ @ARGV },'$(VERBINST)',0,'$(UNINST)');"
-
-DOC_INSTALL = $(PERL) -e "$$\=\"\n\n\";" \
--e "print '=head2 ', scalar(localtime), ': C<', shift, '>', ' L<', $$arg=shift, '|', $$arg, '>';" \
--e "print '=over 4';" \
--e "while (defined($$key = shift) and defined($$val = shift)) { print '=item *';print 'C<', \"$$key: $$val\", '>'; }" \
--e "print '=back';"
-
-UNINSTALL =   $(PERL) -MExtUtils::Install \
--e "uninstall($$ARGV[0],1,1); print \"\nUninstall is deprecated. Please check the";" \
--e "print \" packlist above carefully.\n  There may be errors. Remove the\";" \
--e "print \" appropriate files manually.\n  Sorry for the inconveniences.\n\""
-
-
 # --- MakeMaker dist section:
-
-DISTVNAME = $(DISTNAME)-$(VERSION)
-TAR  = tar
+TAR = tar
 TARFLAGS = cvf
-ZIP  = zip
+ZIP = zip
 ZIPFLAGS = -r
 COMPRESS = gzip --best
 SUFFIX = .gz
 SHAR = shar
-PREOP = @$(NOOP)
-POSTOP = @$(NOOP)
+PREOP = $(NOECHO) $(NOOP)
+POSTOP = $(NOECHO) $(NOOP)
 TO_UNIX = perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"
 CI = ci -u
 RCS_LABEL = rcs -Nv$(VERSION_SYM): -q
 DIST_CP = best
 DIST_DEFAULT = tardist
+DISTNAME = Font-TTF
+DISTVNAME = Font-TTF-0.35
 
 
 # --- MakeMaker macro section:
@@ -431,8 +495,23 @@
 
 
 # --- MakeMaker pasthru section:
-PASTHRU = -nologo
 
+PASTHRU = LIB="$(LIB)"\
+	LIBPERL_A="$(LIBPERL_A)"\
+	LINKTYPE="$(LINKTYPE)"\
+	PREFIX="$(PREFIX)"\
+	OPTIMIZE="$(OPTIMIZE)"\
+	PASTHRU_DEFINE="$(PASTHRU_DEFINE)"\
+	PASTHRU_INC="$(PASTHRU_INC)"
+
+
+# --- MakeMaker special_targets section:
+.SUFFIXES: .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
+
+.PHONY: all config static dynamic test linkext manifest
+
+
+
 # --- MakeMaker c_o section:
 
 
@@ -443,74 +522,70 @@
 
 
 # --- MakeMaker top_targets section:
+all :: pure_all manifypods
+	$(NOECHO) $(NOOP)
 
-#all ::	config $(INST_PM) subdirs linkext manifypods
 
-all :: pure_all htmlifypods manifypods
-	@$(NOOP)
-
 pure_all :: config pm_to_blib subdirs linkext
-	@$(NOOP)
+	$(NOECHO) $(NOOP)
 
 subdirs :: $(MYEXTLIB)
-	@$(NOOP)
+	$(NOECHO) $(NOOP)
 
-config :: Makefile $(INST_LIBDIR)\.exists
-	@$(NOOP)
+config :: $(FIRST_MAKEFILE) $(INST_LIBDIR)$(DIRFILESEP).exists
+	$(NOECHO) $(NOOP)
 
-config :: $(INST_ARCHAUTODIR)\.exists
-	@$(NOOP)
+config :: $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
+	$(NOECHO) $(NOOP)
 
-config :: $(INST_AUTODIR)\.exists
-	@$(NOOP)
+config :: $(INST_AUTODIR)$(DIRFILESEP).exists
+	$(NOECHO) $(NOOP)
 
-$(INST_AUTODIR)\.exists :: D:\Progs\Perl\lib\CORE\perl.h
-	@$(MKPATH) $(INST_AUTODIR)
-	@$(EQUALIZE_TIMESTAMP) D:\Progs\Perl\lib\CORE\perl.h $(INST_AUTODIR)\.exists
+$(INST_AUTODIR)/.exists :: /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h
+	$(NOECHO) $(MKPATH) $(INST_AUTODIR)
+	$(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h $(INST_AUTODIR)/.exists
 
-	-@$(CHMOD) $(PERM_RWX) $(INST_AUTODIR)
+	-$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_AUTODIR)
 
-$(INST_LIBDIR)\.exists :: D:\Progs\Perl\lib\CORE\perl.h
-	@$(MKPATH) $(INST_LIBDIR)
-	@$(EQUALIZE_TIMESTAMP) D:\Progs\Perl\lib\CORE\perl.h $(INST_LIBDIR)\.exists
+$(INST_LIBDIR)/.exists :: /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h
+	$(NOECHO) $(MKPATH) $(INST_LIBDIR)
+	$(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h $(INST_LIBDIR)/.exists
 
-	-@$(CHMOD) $(PERM_RWX) $(INST_LIBDIR)
+	-$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_LIBDIR)
 
-$(INST_ARCHAUTODIR)\.exists :: D:\Progs\Perl\lib\CORE\perl.h
-	@$(MKPATH) $(INST_ARCHAUTODIR)
-	@$(EQUALIZE_TIMESTAMP) D:\Progs\Perl\lib\CORE\perl.h $(INST_ARCHAUTODIR)\.exists
+$(INST_ARCHAUTODIR)/.exists :: /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h
+	$(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
+	$(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h $(INST_ARCHAUTODIR)/.exists
 
-	-@$(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR)
+	-$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR)
 
+config :: $(INST_MAN3DIR)$(DIRFILESEP).exists
+	$(NOECHO) $(NOOP)
+
+
+$(INST_MAN3DIR)/.exists :: /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h
+	$(NOECHO) $(MKPATH) $(INST_MAN3DIR)
+	$(NOECHO) $(EQUALIZE_TIMESTAMP) /usr/lib/perl5/5.8.5/i586-linux-thread-multi/CORE/perl.h $(INST_MAN3DIR)/.exists
+
+	-$(NOECHO) $(CHMOD) $(PERM_RWX) $(INST_MAN3DIR)
+
 help:
 	perldoc ExtUtils::MakeMaker
 
-Version_check:
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
-		-MExtUtils::MakeMaker=Version_check \
-		-e "Version_check('$(MM_VERSION)')"
 
-
 # --- MakeMaker linkext section:
 
 linkext :: $(LINKTYPE)
-	@$(NOOP)
+	$(NOECHO) $(NOOP)
 
 
 # --- MakeMaker dlsyms section:
 
-TTF.def: Makefile.PL
-	$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Mksymlists \
-     -e "Mksymlists('NAME' => 'Font::TTF', 'DLBASE' => '$(BASEEXT)', 'DL_FUNCS' => {  }, 'FUNCLIST' => [], 'IMPORTS' => {  }, 'DL_VARS' => []);"
 
-
 # --- MakeMaker dynamic section:
 
-## $(INST_PM) has been moved to the all: target.
-## It remains here for awhile to allow for old usage: "make dynamic"
-#dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) $(INST_PM)
-dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT)
-	@$(NOOP)
+dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT)
+	$(NOECHO) $(NOOP)
 
 
 # --- MakeMaker dynamic_bs section:
@@ -525,172 +600,290 @@
 
 ## $(INST_PM) has been moved to the all: target.
 ## It remains here for awhile to allow for old usage: "make static"
-#static :: Makefile $(INST_STATIC) $(INST_PM)
-static :: Makefile $(INST_STATIC)
-	@$(NOOP)
+static :: $(FIRST_MAKEFILE) $(INST_STATIC)
+	$(NOECHO) $(NOOP)
 
 
 # --- MakeMaker static_lib section:
 
 
-# --- MakeMaker htmlifypods section:
+# --- MakeMaker manifypods section:
 
-htmlifypods : pure_all
-	@$(NOOP)
+POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
+POD2MAN = $(POD2MAN_EXE)
 
 
-# --- MakeMaker manifypods section:
+manifypods : pure_all  \
+	lib/Font/TTF/Vmtx.pm \
+	lib/Font/TTF/Hhea.pm \
+	lib/Font/TTF/Kern/ClassArray.pm \
+	lib/Font/TTF/Head.pm \
+	lib/Font/TTF/Fmtx.pm \
+	lib/Font/TTF/AATKern.pm \
+	lib/Font/TTF/OldMort.pm \
+	lib/Font/TTF/Bsln.pm \
+	lib/Font/TTF/Manual.pod \
+	lib/Font/TTF/Font.pm \
+	lib/Font/TTF/GDEF.pm \
+	lib/Font/TTF/Vhea.pm \
+	lib/Font/TTF/Fpgm.pm \
+	lib/Font/TTF/GSUB.pm \
+	lib/Font/TTF/Mort/Contextual.pm \
+	lib/Font/TTF/OS_2.pm \
+	lib/Font/TTF/Ttc.pm \
+	lib/Font/TTF/Feat.pm \
+	lib/Font/TTF/Name.pm \
+	lib/Font/TTF/Kern.pm \
+	lib/Font/TTF/Kern/StateTable.pm \
+	lib/Font/TTF/OldCmap.pm \
+	lib/Font/TTF/Segarr.pm \
+	lib/Font/TTF/Loca.pm \
+	lib/Font/TTF/Mort/Insertion.pm \
+	lib/Font/TTF/Mort/Chain.pm \
+	lib/Font/TTF/Mort/Rearrangement.pm \
+	lib/Font/TTF/Fdsc.pm \
+	lib/Font/TTF/Cvt_.pm \
+	lib/Font/TTF/XMLparse.pm \
+	lib/Font/TTF/Maxp.pm \
+	lib/Font/TTF/Coverage.pm \
+	lib/Font/TTF/PCLT.pm \
+	lib/Font/TTF/Prop.pm \
+	lib/Font/TTF/Mort/Ligature.pm \
+	lib/Font/TTF/Utils.pm \
+	lib/Font/TTF/Ttopen.pm \
+	lib/Font/TTF/Kern/Subtable.pm \
+	lib/Font/TTF/Hmtx.pm \
+	lib/Font/TTF/Kern/OrderedList.pm \
+	lib/Font/TTF/Glyph.pm \
+	lib/Font/TTF/Mort.pm \
+	lib/Font/TTF/Prep.pm \
+	lib/Font/TTF/Kern/CompactClassArray.pm \
+	lib/Font/TTF/Hdmx.pm \
+	lib/Font/TTF/Cmap.pm \
+	lib/Font/TTF/GPOS.pm \
+	lib/Font/TTF/PSNames.pm \
+	lib/Font/TTF/Mort/Noncontextual.pm \
+	lib/Font/TTF/Post.pm \
+	lib/Font/TTF/Anchor.pm \
+	lib/Font/TTF/Glyf.pm \
+	lib/Font/TTF/LTSH.pm \
+	lib/Font/TTF/Table.pm \
+	lib/Font/TTF/Delta.pm \
+	lib/Font/TTF/Mort/Subtable.pm \
+	lib/Font/TTF/Vmtx.pm \
+	lib/Font/TTF/Hhea.pm \
+	lib/Font/TTF/Kern/ClassArray.pm \
+	lib/Font/TTF/Head.pm \
+	lib/Font/TTF/Fmtx.pm \
+	lib/Font/TTF/AATKern.pm \
+	lib/Font/TTF/OldMort.pm \
+	lib/Font/TTF/Bsln.pm \
+	lib/Font/TTF/Manual.pod \
+	lib/Font/TTF/Font.pm \
+	lib/Font/TTF/GDEF.pm \
+	lib/Font/TTF/Vhea.pm \
+	lib/Font/TTF/Fpgm.pm \
+	lib/Font/TTF/GSUB.pm \
+	lib/Font/TTF/Mort/Contextual.pm \
+	lib/Font/TTF/OS_2.pm \
+	lib/Font/TTF/Ttc.pm \
+	lib/Font/TTF/Feat.pm \
+	lib/Font/TTF/Name.pm \
+	lib/Font/TTF/Kern.pm \
+	lib/Font/TTF/Kern/StateTable.pm \
+	lib/Font/TTF/OldCmap.pm \
+	lib/Font/TTF/Segarr.pm \
+	lib/Font/TTF/Loca.pm \
+	lib/Font/TTF/Mort/Insertion.pm \
+	lib/Font/TTF/Mort/Chain.pm \
+	lib/Font/TTF/Mort/Rearrangement.pm \
+	lib/Font/TTF/Fdsc.pm \
+	lib/Font/TTF/Cvt_.pm \
+	lib/Font/TTF/XMLparse.pm \
+	lib/Font/TTF/Maxp.pm \
+	lib/Font/TTF/Coverage.pm \
+	lib/Font/TTF/PCLT.pm \
+	lib/Font/TTF/Prop.pm \
+	lib/Font/TTF/Mort/Ligature.pm \
+	lib/Font/TTF/Utils.pm \
+	lib/Font/TTF/Ttopen.pm \
+	lib/Font/TTF/Kern/Subtable.pm \
+	lib/Font/TTF/Hmtx.pm \
+	lib/Font/TTF/Kern/OrderedList.pm \
+	lib/Font/TTF/Glyph.pm \
+	lib/Font/TTF/Mort.pm \
+	lib/Font/TTF/Prep.pm \
+	lib/Font/TTF/Kern/CompactClassArray.pm \
+	lib/Font/TTF/Hdmx.pm \
+	lib/Font/TTF/Cmap.pm \
+	lib/Font/TTF/GPOS.pm \
+	lib/Font/TTF/PSNames.pm \
+	lib/Font/TTF/Mort/Noncontextual.pm \
+	lib/Font/TTF/Post.pm \
+	lib/Font/TTF/Anchor.pm \
+	lib/Font/TTF/Glyf.pm \
+	lib/Font/TTF/LTSH.pm \
+	lib/Font/TTF/Table.pm \
+	lib/Font/TTF/Delta.pm \
+	lib/Font/TTF/Mort/Subtable.pm
+	$(NOECHO) $(POD2MAN) --section=3 --perm_rw=$(PERM_RW)\
+	  lib/Font/TTF/Vmtx.pm $(INST_MAN3DIR)/Font::TTF::Vmtx.$(MAN3EXT) \
+	  lib/Font/TTF/Hhea.pm $(INST_MAN3DIR)/Font::TTF::Hhea.$(MAN3EXT) \
+	  lib/Font/TTF/Kern/ClassArray.pm $(INST_MAN3DIR)/Font::TTF::Kern::ClassArray.$(MAN3EXT) \
+	  lib/Font/TTF/Head.pm $(INST_MAN3DIR)/Font::TTF::Head.$(MAN3EXT) \
+	  lib/Font/TTF/Fmtx.pm $(INST_MAN3DIR)/Font::TTF::Fmtx.$(MAN3EXT) \
+	  lib/Font/TTF/AATKern.pm $(INST_MAN3DIR)/Font::TTF::AATKern.$(MAN3EXT) \
+	  lib/Font/TTF/OldMort.pm $(INST_MAN3DIR)/Font::TTF::OldMort.$(MAN3EXT) \
+	  lib/Font/TTF/Bsln.pm $(INST_MAN3DIR)/Font::TTF::Bsln.$(MAN3EXT) \
+	  lib/Font/TTF/Manual.pod $(INST_MAN3DIR)/Font::TTF::Manual.$(MAN3EXT) \
+	  lib/Font/TTF/Font.pm $(INST_MAN3DIR)/Font::TTF::Font.$(MAN3EXT) \
+	  lib/Font/TTF/GDEF.pm $(INST_MAN3DIR)/Font::TTF::GDEF.$(MAN3EXT) \
+	  lib/Font/TTF/Vhea.pm $(INST_MAN3DIR)/Font::TTF::Vhea.$(MAN3EXT) \
+	  lib/Font/TTF/Fpgm.pm $(INST_MAN3DIR)/Font::TTF::Fpgm.$(MAN3EXT) \
+	  lib/Font/TTF/GSUB.pm $(INST_MAN3DIR)/Font::TTF::GSUB.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Contextual.pm $(INST_MAN3DIR)/Font::TTF::Mort::Contextual.$(MAN3EXT) \
+	  lib/Font/TTF/OS_2.pm $(INST_MAN3DIR)/Font::TTF::OS_2.$(MAN3EXT) \
+	  lib/Font/TTF/Ttc.pm $(INST_MAN3DIR)/Font::TTF::Ttc.$(MAN3EXT) \
+	  lib/Font/TTF/Feat.pm $(INST_MAN3DIR)/Font::TTF::Feat.$(MAN3EXT) \
+	  lib/Font/TTF/Name.pm $(INST_MAN3DIR)/Font::TTF::Name.$(MAN3EXT) \
+	  lib/Font/TTF/Kern.pm $(INST_MAN3DIR)/Font::TTF::Kern.$(MAN3EXT) \
+	  lib/Font/TTF/Kern/StateTable.pm $(INST_MAN3DIR)/Font::TTF::Kern::StateTable.$(MAN3EXT) \
+	  lib/Font/TTF/OldCmap.pm $(INST_MAN3DIR)/Font::TTF::OldCmap.$(MAN3EXT) \
+	  lib/Font/TTF/Segarr.pm $(INST_MAN3DIR)/Font::TTF::Segarr.$(MAN3EXT) \
+	  lib/Font/TTF/Loca.pm $(INST_MAN3DIR)/Font::TTF::Loca.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Insertion.pm $(INST_MAN3DIR)/Font::TTF::Mort::Insertion.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Chain.pm $(INST_MAN3DIR)/Font::TTF::Mort::Chain.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Rearrangement.pm $(INST_MAN3DIR)/Font::TTF::Mort::Rearrangement.$(MAN3EXT) \
+	  lib/Font/TTF/Fdsc.pm $(INST_MAN3DIR)/Font::TTF::Fdsc.$(MAN3EXT) \
+	  lib/Font/TTF/Cvt_.pm $(INST_MAN3DIR)/Font::TTF::Cvt_.$(MAN3EXT) \
+	  lib/Font/TTF/XMLparse.pm $(INST_MAN3DIR)/Font::TTF::XMLparse.$(MAN3EXT) \
+	  lib/Font/TTF/Maxp.pm $(INST_MAN3DIR)/Font::TTF::Maxp.$(MAN3EXT) \
+	  lib/Font/TTF/Coverage.pm $(INST_MAN3DIR)/Font::TTF::Coverage.$(MAN3EXT) \
+	  lib/Font/TTF/PCLT.pm $(INST_MAN3DIR)/Font::TTF::PCLT.$(MAN3EXT) \
+	  lib/Font/TTF/Prop.pm $(INST_MAN3DIR)/Font::TTF::Prop.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Ligature.pm $(INST_MAN3DIR)/Font::TTF::Mort::Ligature.$(MAN3EXT) \
+	  lib/Font/TTF/Utils.pm $(INST_MAN3DIR)/Font::TTF::Utils.$(MAN3EXT) \
+	  lib/Font/TTF/Ttopen.pm $(INST_MAN3DIR)/Font::TTF::Ttopen.$(MAN3EXT) \
+	  lib/Font/TTF/Kern/Subtable.pm $(INST_MAN3DIR)/Font::TTF::Kern::Subtable.$(MAN3EXT) \
+	  lib/Font/TTF/Hmtx.pm $(INST_MAN3DIR)/Font::TTF::Hmtx.$(MAN3EXT) \
+	  lib/Font/TTF/Kern/OrderedList.pm $(INST_MAN3DIR)/Font::TTF::Kern::OrderedList.$(MAN3EXT) \
+	  lib/Font/TTF/Glyph.pm $(INST_MAN3DIR)/Font::TTF::Glyph.$(MAN3EXT) \
+	  lib/Font/TTF/Mort.pm $(INST_MAN3DIR)/Font::TTF::Mort.$(MAN3EXT) \
+	  lib/Font/TTF/Prep.pm $(INST_MAN3DIR)/Font::TTF::Prep.$(MAN3EXT) \
+	  lib/Font/TTF/Kern/CompactClassArray.pm $(INST_MAN3DIR)/Font::TTF::Kern::CompactClassArray.$(MAN3EXT) \
+	  lib/Font/TTF/Hdmx.pm $(INST_MAN3DIR)/Font::TTF::Hdmx.$(MAN3EXT) \
+	  lib/Font/TTF/Cmap.pm $(INST_MAN3DIR)/Font::TTF::Cmap.$(MAN3EXT) \
+	  lib/Font/TTF/GPOS.pm $(INST_MAN3DIR)/Font::TTF::GPOS.$(MAN3EXT) \
+	  lib/Font/TTF/PSNames.pm $(INST_MAN3DIR)/Font::TTF::PSNames.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Noncontextual.pm $(INST_MAN3DIR)/Font::TTF::Mort::Noncontextual.$(MAN3EXT) \
+	  lib/Font/TTF/Post.pm $(INST_MAN3DIR)/Font::TTF::Post.$(MAN3EXT) \
+	  lib/Font/TTF/Anchor.pm $(INST_MAN3DIR)/Font::TTF::Anchor.$(MAN3EXT) \
+	  lib/Font/TTF/Glyf.pm $(INST_MAN3DIR)/Font::TTF::Glyf.$(MAN3EXT) \
+	  lib/Font/TTF/LTSH.pm $(INST_MAN3DIR)/Font::TTF::LTSH.$(MAN3EXT) \
+	  lib/Font/TTF/Table.pm $(INST_MAN3DIR)/Font::TTF::Table.$(MAN3EXT) \
+	  lib/Font/TTF/Delta.pm $(INST_MAN3DIR)/Font::TTF::Delta.$(MAN3EXT) \
+	  lib/Font/TTF/Mort/Subtable.pm $(INST_MAN3DIR)/Font::TTF::Mort::Subtable.$(MAN3EXT) 
 
-manifypods :
-	@$(NOOP)
 
 
+
 # --- MakeMaker processPL section:
 
 
 # --- MakeMaker installbin section:
 
-$(INST_SCRIPT)\.exists :: D:\Progs\Perl\lib\CORE\perl.h
-	@$(MKPATH) $(INST_SCRIPT)
-	@$(EQUALIZE_TIMESTAMP) D:\Progs\Perl\lib\CORE\perl.h $(INST_SCRIPT)\.exists
 
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)
+# --- MakeMaker subdirs section:
 
-EXE_FILES = scripts/check_attach.plx scripts/eurofix.plx scripts/hackos2.plx scripts/psfix.plx scripts/ttfbuilder.plx scripts/ttfname.plx scripts/ttfremap.plx
+# none
 
-FIXIN = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
-    -e "system qq[pl2bat.bat ].shift"
+# --- MakeMaker clean_subdirs section:
+clean_subdirs :
+	$(NOECHO) $(NOOP)
 
-pure_all :: $(INST_SCRIPT)\check_attach.plx $(INST_SCRIPT)\ttfname.plx $(INST_SCRIPT)\ttfbuilder.plx $(INST_SCRIPT)\hackos2.plx $(INST_SCRIPT)\eurofix.plx $(INST_SCRIPT)\psfix.plx $(INST_SCRIPT)\ttfremap.plx
-	@$(NOOP)
 
-realclean ::
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\check_attach.plx $(INST_SCRIPT)\ttfname.plx $(INST_SCRIPT)\ttfbuilder.plx $(INST_SCRIPT)\hackos2.plx $(INST_SCRIPT)\eurofix.plx $(INST_SCRIPT)\psfix.plx $(INST_SCRIPT)\ttfremap.plx
+# --- MakeMaker clean section:
 
-$(INST_SCRIPT)\check_attach.plx: scripts/check_attach.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\check_attach.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/check_attach.plx $(INST_SCRIPT)\check_attach.plx
-	$(FIXIN) $(INST_SCRIPT)\check_attach.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\check_attach.plx
+# Delete temporary files but do not touch installed files. We don't delete
+# the Makefile here so a later make realclean still has a makefile to use.
 
-$(INST_SCRIPT)\ttfname.plx: scripts/ttfname.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\ttfname.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/ttfname.plx $(INST_SCRIPT)\ttfname.plx
-	$(FIXIN) $(INST_SCRIPT)\ttfname.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\ttfname.plx
+clean :: clean_subdirs
+	-$(RM_RF) ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all $(INST_ARCHAUTODIR)/extralibs.ld perlmain.c tmon.out mon.out so_locations pm_to_blib *$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT) $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def lib$(BASEEXT).def $(BASEEXT).exp $(BASEEXT).x core core.*perl.*.? *perl.core core.[0-9] core.[0-9][0-9] core.[0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9] core.[0-9][0-9][0-9][0-9][0-9]
+	-$(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)
 
-$(INST_SCRIPT)\ttfbuilder.plx: scripts/ttfbuilder.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\ttfbuilder.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/ttfbuilder.plx $(INST_SCRIPT)\ttfbuilder.plx
-	$(FIXIN) $(INST_SCRIPT)\ttfbuilder.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\ttfbuilder.plx
 
-$(INST_SCRIPT)\hackos2.plx: scripts/hackos2.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\hackos2.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/hackos2.plx $(INST_SCRIPT)\hackos2.plx
-	$(FIXIN) $(INST_SCRIPT)\hackos2.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\hackos2.plx
+# --- MakeMaker realclean_subdirs section:
+realclean_subdirs :
+	$(NOECHO) $(NOOP)
 
-$(INST_SCRIPT)\eurofix.plx: scripts/eurofix.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\eurofix.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/eurofix.plx $(INST_SCRIPT)\eurofix.plx
-	$(FIXIN) $(INST_SCRIPT)\eurofix.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\eurofix.plx
 
-$(INST_SCRIPT)\psfix.plx: scripts/psfix.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\psfix.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/psfix.plx $(INST_SCRIPT)\psfix.plx
-	$(FIXIN) $(INST_SCRIPT)\psfix.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\psfix.plx
+# --- MakeMaker realclean section:
 
-$(INST_SCRIPT)\ttfremap.plx: scripts/ttfremap.plx Makefile $(INST_SCRIPT)\.exists
-	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_SCRIPT)\ttfremap.plx
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e cp scripts/ttfremap.plx $(INST_SCRIPT)\ttfremap.plx
-	$(FIXIN) $(INST_SCRIPT)\ttfremap.plx
-	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)\ttfremap.plx
+# Delete temporary files (via clean) and also delete installed files
+realclean purge ::  clean realclean_subdirs
+	$(RM_RF) $(INST_AUTODIR) $(INST_ARCHAUTODIR)
+	$(RM_RF) $(DISTVNAME)
+	$(RM_F)  blib/lib/Font/TTF/Fpgm.pm blib/lib/Font/TTF/Font.pm blib/lib/Font/TTF/Hdmx.pm blib/lib/Font/TTF/Head.pm blib/lib/Font/TTF/Bsln.pm blib/lib/Font/TTF/Vmtx.pm blib/lib/Font/TTF/Kern/ClassArray.pm
+	$(RM_F) $(FIRST_MAKEFILE) blib/lib/Font/TTF/Glyf.pm blib/lib/Font/TTF/Prop.pm blib/lib/Font/TTF/AATKern.pm blib/lib/ttfmod.pl blib/lib/Font/TTF/Win32.pm blib/lib/Font/TTF/Fmtx.pm blib/lib/Font/TTF/GDEF.pm
+	$(RM_F) blib/lib/Font/TTF/Maxp.pm blib/lib/Font/TTF/GSUB.pm blib/lib/Font/TTF/OldCmap.pm blib/lib/Font/TTF/Mort.pm blib/lib/Font/TTF/Ttc.pm blib/lib/Font/TTF/Kern/CompactClassArray.pm blib/lib/Font/TTF/Hmtx.pm
+	$(RM_F) blib/lib/Font/TTF/Segarr.pm blib/lib/Font/TTF/OS_2.pm blib/lib/Font/TTF/Changes blib/lib/Font/TTF/Mort/Rearrangement.pm blib/lib/Font/TTF/Mort/Insertion.pm blib/lib/Font/TTF/Utils.pm
+	$(RM_F) blib/lib/Font/TTF/Manual.pod blib/lib/Font/TTF/Kern.pm blib/lib/Font/TTF/Mort/Noncontextual.pm blib/lib/Font/TTF/Mort/Contextual.pm blib/lib/Font/TTF/Useall.pm blib/lib/Font/TTF/GPOS.pm $(MAKEFILE_OLD)
+	$(RM_F) blib/lib/Font/TTF/Fdsc.pm blib/lib/Font/TTF/Coverage.pm blib/lib/Font/TTF/Vhea.pm blib/lib/Font/TTF/OldMort.pm blib/lib/Font/TTF/Table.pm blib/lib/Font/TTF/Feat.pm blib/lib/Font/TTF/Name.pm
+	$(RM_F) blib/lib/Font/TTF/PCLT.pm blib/lib/Font/TTF/XMLparse.pm blib/lib/Font/TTF/LTSH.pm blib/lib/Font/TTF/AATutils.pm blib/lib/Font/TTF/Cvt_.pm blib/lib/Font/TTF/Kern/OrderedList.pm
+	$(RM_F) blib/lib/Font/TTF/Delta.pm blib/lib/Font/TTF/PSNames.pm blib/lib/Font/TTF/Mort/Ligature.pm blib/lib/Font/TTF/Anchor.pm blib/lib/Font/TTF/Glyph.pm blib/lib/Font/TTF/Mort/Chain.pm
+	$(RM_F) blib/lib/Font/TTF/Cmap.pm blib/lib/Font/TTF/Loca.pm blib/lib/Font/TTF/Post.pm blib/lib/Font/TTF/Prep.pm blib/lib/Font/TTF/Kern/StateTable.pm blib/lib/Font/TTF/Mort/Subtable.pm
+	$(RM_F) blib/lib/Font/TTF/Ttopen.pm blib/lib/Font/TTF/Kern/Subtable.pm blib/lib/Font/TTF/Hhea.pm
 
 
-# --- MakeMaker subdirs section:
+# --- MakeMaker metafile section:
+metafile :
+	$(NOECHO) $(ECHO) '# http://module-build.sourceforge.net/META-spec.html' > META.yml
+	$(NOECHO) $(ECHO) '#XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#' >> META.yml
+	$(NOECHO) $(ECHO) 'name:         Font-TTF' >> META.yml
+	$(NOECHO) $(ECHO) 'version:      0.35' >> META.yml
+	$(NOECHO) $(ECHO) 'version_from: lib/Font/TTF/Font.pm' >> META.yml
+	$(NOECHO) $(ECHO) 'installdirs:  site' >> META.yml
+	$(NOECHO) $(ECHO) 'requires:' >> META.yml
+	$(NOECHO) $(ECHO) '' >> META.yml
+	$(NOECHO) $(ECHO) 'distribution_type: module' >> META.yml
+	$(NOECHO) $(ECHO) 'generated_by: ExtUtils::MakeMaker version 6.17' >> META.yml
 
-# none
 
-# --- MakeMaker clean section:
+# --- MakeMaker metafile_addtomanifest section:
+metafile_addtomanifest:
+	$(NOECHO) $(PERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) } ' \
+	-e '    or print "Could not add META.yml to MANIFEST: $${'\''@'\''}\n"'
 
-# Delete temporary files but do not touch installed files. We don't delete
-# the Makefile here so a later make realclean still has a makefile to use.
 
-clean ::
-	-$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_rf ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all perlmain.c mon.out core core.*perl.*.? *perl.core so_locations pm_to_blib *$(OBJ_EXT) *$(LIB_EXT) perl.exe $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def $(BASEEXT).exp
-	-$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mv Makefile Makefile.old $(DEV_NULL)
-
-
-# --- MakeMaker realclean section:
-
-# Delete temporary files (via clean) and also delete installed files
-realclean purge ::  clean
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_rf $(INST_AUTODIR) $(INST_ARCHAUTODIR)
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f  $(INST_LIB)\Font\TTF\Kern\ClassArray.pm $(INST_LIB)\Font\TTF\Anchor.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Head.pm $(INST_LIB)\Font\TTF\PCLT.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Mort\Rearrangement.pm $(INST_LIB)\Font\TTF\Vmtx.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Mort\Noncontextual.pm $(INST_LIB)\Font\TTF\Mort\Chain.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Bsln.pm $(INST_LIB)\Font\TTF\Post.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Cvt_.pm $(INST_LIB)\Font\TTF\Maxp.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\OS_2.pm $(INST_LIB)\Font\TTF\Ttc.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Win32.pm $(INST_LIB)\Font\TTF\Fmtx.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Name.pm $(INST_LIB)\Font\TTF\Delta.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Kern\CompactClassArray.pm $(INST_LIB)\Font\TTF\Mort.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Utils.pm $(INST_LIB)\Font\TTF\Loca.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Fpgm.pm $(INST_LIB)\Font\TTF\Kern\Subtable.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\GPOS.pm $(INST_LIB)\Font\TTF\OldMort.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Vhea.pm $(INST_LIB)\Font\TTF\Manual.pod
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Ttopen.pm $(INST_LIB)\Font\TTF\Cmap.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Prop.pm $(INST_LIB)\Font\TTF\LTSH.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Mort\Subtable.pm $(INST_LIB)\Font\TTF\Hmtx.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\AATutils.pm $(INST_LIB)\Font\TTF\Kern\OrderedList.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Kern\StateTable.pm $(INST_LIB)\Font\TTF\Fdsc.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\XMLparse.pm $(INST_LIB)\Font\TTF\OldCmap.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Table.pm $(INST_LIB)\Font\TTF\Glyf.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Mort\Ligature.pm $(INST_LIB)\Font\TTF\GSUB.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Hdmx.pm $(INST_LIB)\Font\TTF\AATKern.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Coverage.pm $(INST_LIB)\Font\TTF\Prep.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Mort\Insertion.pm $(INST_LIB)\Font\TTF\Mort\Contextual.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\GDEF.pm $(INST_LIB)\Font\TTF\PSNames.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Font.pm $(INST_LIB)\Font\TTF\Feat.pm $(INST_LIB)\ttfmod.pl
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Kern.pm $(INST_LIB)\Font\TTF\Glyph.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Changes $(INST_LIB)\Font\TTF\Useall.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_f $(INST_LIB)\Font\TTF\Hhea.pm $(INST_LIB)\Font\TTF\Segarr.pm
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e rm_rf Makefile Makefile.old
-
-
 # --- MakeMaker dist_basics section:
-
 distclean :: realclean distcheck
+	$(NOECHO) $(NOOP)
 
 distcheck :
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=fullcheck \
-		-e fullcheck
+	$(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck
 
 skipcheck :
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=skipcheck \
-		-e skipcheck
+	$(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck
 
 manifest :
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=mkmanifest \
-		-e mkmanifest
+	$(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
 
 veryclean : realclean
 	$(RM_F) *~ *.orig */*~ */*.orig
 
 
+
 # --- MakeMaker dist_core section:
 
-dist : $(DIST_DEFAULT)
-	@$(PERL) -le "print \"Warning: Makefile possibly out of date with $$vf\" if " \
-	    -e "-e ($$vf=\"$(VERSION_FROM)\") and -M $$vf < -M \"Makefile\";"
+dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE)
+	$(NOECHO) $(PERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \
+	-e '    if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';'
 
 tardist : $(DISTVNAME).tar$(SUFFIX)
+	$(NOECHO) $(NOOP)
 
-zipdist : $(DISTVNAME).zip
+uutardist : $(DISTVNAME).tar$(SUFFIX)
+	uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
 
 $(DISTVNAME).tar$(SUFFIX) : distdir
 	$(PREOP)
@@ -700,17 +893,15 @@
 	$(COMPRESS) $(DISTVNAME).tar
 	$(POSTOP)
 
+zipdist : $(DISTVNAME).zip
+	$(NOECHO) $(NOOP)
+
 $(DISTVNAME).zip : distdir
 	$(PREOP)
 	$(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
 	$(RM_RF) $(DISTVNAME)
 	$(POSTOP)
 
-uutardist : $(DISTVNAME).tar$(SUFFIX)
-	uuencode $(DISTVNAME).tar$(SUFFIX) \
-		$(DISTVNAME).tar$(SUFFIX) > \
-		$(DISTVNAME).tar$(SUFFIX)_uu
-
 shdist : distdir
 	$(PREOP)
 	$(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
@@ -718,29 +909,29 @@
 	$(POSTOP)
 
 
-# --- MakeMaker dist_dir section:
-
-distdir :
+# --- MakeMaker distdir section:
+distdir : metafile metafile_addtomanifest
 	$(RM_RF) $(DISTVNAME)
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=manicopy,maniread \
+	$(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
 		-e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
 
 
+
 # --- MakeMaker dist_test section:
 
 disttest : distdir
-	cd $(DISTVNAME) && $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) Makefile.PL
-	cd $(DISTVNAME) && $(MAKE)
-	cd $(DISTVNAME) && $(MAKE) test
+	cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL
+	cd $(DISTVNAME) && $(MAKE) $(PASTHRU)
+	cd $(DISTVNAME) && $(MAKE) test $(PASTHRU)
 
 
 # --- MakeMaker dist_ci section:
 
 ci :
-	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=maniread \
-		-e "@all = keys %{ maniread() };" \
-		-e "print(\"Executing $(CI) @all\n\"); system(\"$(CI) @all\");" \
-		-e "print(\"Executing $(RCS_LABEL) ...\n\"); system(\"$(RCS_LABEL) @all\");"
+	$(PERLRUN) "-MExtUtils::Manifest=maniread" \
+	  -e "@all = keys %{ maniread() };" \
+	  -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \
+	  -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});"
 
 
 # --- MakeMaker install section:
@@ -751,85 +942,106 @@
 
 install_site :: all pure_site_install doc_site_install
 
-install_ :: install_site
-	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+install_vendor :: all pure_vendor_install doc_vendor_install
 
 pure_install :: pure_$(INSTALLDIRS)_install
 
 doc_install :: doc_$(INSTALLDIRS)_install
-	@echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
 
 pure__install : pure_site_install
-	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+	$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
 
 doc__install : doc_site_install
-	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+	$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
 
 pure_perl_install ::
-	@$(MOD_INSTALL) \
-		read $(PERL_ARCHLIB)\auto\$(FULLEXT)\.packlist \
-		write $(INSTALLARCHLIB)\auto\$(FULLEXT)\.packlist \
-		$(INST_LIB) $(INSTALLPRIVLIB) \
-		$(INST_ARCHLIB) $(INSTALLARCHLIB) \
-		$(INST_BIN) $(INSTALLBIN) \
-		$(INST_SCRIPT) $(INSTALLSCRIPT) \
-		$(INST_HTMLLIBDIR) $(INSTALLHTMLPRIVLIBDIR) \
-		$(INST_HTMLSCRIPTDIR) $(INSTALLHTMLSCRIPTDIR) \
-		$(INST_MAN1DIR) $(INSTALLMAN1DIR) \
-		$(INST_MAN3DIR) $(INSTALLMAN3DIR)
-	@$(WARN_IF_OLD_PACKLIST) \
-		$(SITEARCHEXP)\auto\$(FULLEXT)
+	$(NOECHO) $(MOD_INSTALL) \
+		read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \
+		write $(DESTINSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \
+		$(INST_LIB) $(DESTINSTALLPRIVLIB) \
+		$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \
+		$(INST_BIN) $(DESTINSTALLBIN) \
+		$(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
+		$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \
+		$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR)
+	$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+		$(SITEARCHEXP)/auto/$(FULLEXT)
 
 
 pure_site_install ::
-	@$(MOD_INSTALL) \
-		read $(SITEARCHEXP)\auto\$(FULLEXT)\.packlist \
-		write $(INSTALLSITEARCH)\auto\$(FULLEXT)\.packlist \
-		$(INST_LIB) $(INSTALLSITELIB) \
-		$(INST_ARCHLIB) $(INSTALLSITEARCH) \
-		$(INST_BIN) $(INSTALLBIN) \
-		$(INST_SCRIPT) $(INSTALLSCRIPT) \
-		$(INST_HTMLLIBDIR) $(INSTALLHTMLSITELIBDIR) \
-		$(INST_HTMLSCRIPTDIR) $(INSTALLHTMLSCRIPTDIR) \
-		$(INST_MAN1DIR) $(INSTALLMAN1DIR) \
-		$(INST_MAN3DIR) $(INSTALLMAN3DIR)
-	@$(WARN_IF_OLD_PACKLIST) \
-		$(PERL_ARCHLIB)\auto\$(FULLEXT)
+	$(NOECHO) $(MOD_INSTALL) \
+		read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \
+		write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \
+		$(INST_LIB) $(DESTINSTALLSITELIB) \
+		$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \
+		$(INST_BIN) $(DESTINSTALLSITEBIN) \
+		$(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
+		$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \
+		$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR)
+	$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+		$(PERL_ARCHLIB)/auto/$(FULLEXT)
 
+pure_vendor_install ::
+	$(NOECHO) $(MOD_INSTALL) \
+		read $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist \
+		write $(DESTINSTALLVENDORARCH)/auto/$(FULLEXT)/.packlist \
+		$(INST_LIB) $(DESTINSTALLVENDORLIB) \
+		$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \
+		$(INST_BIN) $(DESTINSTALLVENDORBIN) \
+		$(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
+		$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \
+		$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR)
+
 doc_perl_install ::
-	-@$(MKPATH) $(INSTALLARCHLIB)
-	-@$(DOC_INSTALL) \
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+	-$(NOECHO) $(DOC_INSTALL) \
 		"Module" "$(NAME)" \
 		"installed into" "$(INSTALLPRIVLIB)" \
 		LINKTYPE "$(LINKTYPE)" \
 		VERSION "$(VERSION)" \
 		EXE_FILES "$(EXE_FILES)" \
-		>> $(INSTALLARCHLIB)\perllocal.pod
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
 
 doc_site_install ::
-	-@$(MKPATH) $(INSTALLARCHLIB)
-	-@$(DOC_INSTALL) \
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+	-$(NOECHO) $(DOC_INSTALL) \
 		"Module" "$(NAME)" \
 		"installed into" "$(INSTALLSITELIB)" \
 		LINKTYPE "$(LINKTYPE)" \
 		VERSION "$(VERSION)" \
 		EXE_FILES "$(EXE_FILES)" \
-		>> $(INSTALLARCHLIB)\perllocal.pod
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
 
+doc_vendor_install ::
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+	-$(NOECHO) $(DOC_INSTALL) \
+		"Module" "$(NAME)" \
+		"installed into" "$(INSTALLVENDORLIB)" \
+		LINKTYPE "$(LINKTYPE)" \
+		VERSION "$(VERSION)" \
+		EXE_FILES "$(EXE_FILES)" \
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
 
+
 uninstall :: uninstall_from_$(INSTALLDIRS)dirs
 
 uninstall_from_perldirs ::
-	@$(UNINSTALL) $(PERL_ARCHLIB)\auto\$(FULLEXT)\.packlist
+	$(NOECHO) $(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist
 
 uninstall_from_sitedirs ::
-	@$(UNINSTALL) $(SITEARCHEXP)\auto\$(FULLEXT)\.packlist
+	$(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist
 
+uninstall_from_vendordirs ::
+	$(NOECHO) $(UNINSTALL) $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist
 
+
 # --- MakeMaker force section:
 # Phony target to force checking subdirectories.
 FORCE:
-	@$(NOOP)
+	$(NOECHO) $(NOOP)
 
 
 # --- MakeMaker perldepend section:
@@ -837,37 +1049,33 @@
 
 # --- MakeMaker makefile section:
 
-# We take a very conservative approach here, but it\'s worth it.
+# We take a very conservative approach here, but it's worth it.
 # We move Makefile to Makefile.old here to avoid gnu make looping.
-Makefile : Makefile.PL $(CONFIGDEP)
-	@echo "Makefile out-of-date with respect to $?"
-	@echo "Cleaning current config before rebuilding Makefile..."
-	-@$(RM_F) Makefile.old
-	-@$(MV) Makefile Makefile.old
-	-$(MAKE) -f Makefile.old clean $(DEV_NULL) || $(NOOP)
-	$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL 
-	@echo "==> Your Makefile has been rebuilt. <=="
-	@echo "==> Please rerun the make command.  <=="
+$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
+	$(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?"
+	$(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
+	$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
+	$(NOECHO) $(MV)   $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
+	-$(MAKE) -f $(MAKEFILE_OLD) clean $(DEV_NULL) || $(NOOP)
+	$(PERLRUN) Makefile.PL 
+	$(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
+	$(NOECHO) $(ECHO) "==> Please rerun the make command.  <=="
 	false
 
-# To change behavior to :: would be nice, but would break Tk b9.02
-# so you find such a warning below the dist target.
-#Makefile :: $(VERSION_FROM)
-#	@echo "Warning: Makefile possibly out of date with $(VERSION_FROM)"
 
 
 # --- MakeMaker staticmake section:
 
 # --- MakeMaker makeaperl section ---
 MAP_TARGET    = perl
-FULLPERL      = D:\Progs\Perl\bin\Perl.exe
+FULLPERL      = /usr/bin/perl
 
 $(MAP_TARGET) :: static $(MAKE_APERL_FILE)
 	$(MAKE) -f $(MAKE_APERL_FILE) $@
 
 $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
-	@echo Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
-	@$(PERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
+	$(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
+	$(NOECHO) $(PERLRUNINST) \
 		Makefile.PL DIR= \
 		MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
 		MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=
@@ -884,12 +1092,12 @@
 testdb :: testdb_$(LINKTYPE)
 
 test :: $(TEST_TYPE)
-	@echo 'No tests defined for $(NAME) extension.'
+	$(NOECHO) $(ECHO) 'No tests defined for $(NAME) extension.'
 
 test_dynamic :: pure_all
 
 testdb_dynamic :: pure_all
-	$(FULLPERL) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE)
+	PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE)
 
 test_ : test_dynamic
 
@@ -900,18 +1108,85 @@
 # --- MakeMaker ppd section:
 # Creates a PPD (Perl Package Description) for a binary distribution.
 ppd:
-	@$(PERL) -e "print qq{<SOFTPKG NAME=\"Font-TTF\" VERSION=\"0,34,0,0\">\n}. qq{\t<TITLE>Font-TTF</TITLE>\n}. qq{\t<ABSTRACT>TTF font support for Perl</ABSTRACT>\n}. qq{\t<AUTHOR>martin_hosken\@sil.org</AUTHOR>\n}. qq{\t<IMPLEMENTATION>\n}. qq{\t\t<OS NAME=\"$(OSNAME)\" />\n}. qq{\t\t<ARCHITECTURE NAME=\"MSWin32-x86-multi-thread\" />\n}. qq{\t\t<CODEBASE HREF=\"\" />\n}. qq{\t</IMPLEMENTATION>\n}. qq{</SOFTPKG>\n}" > Font-TTF.ppd
+	$(NOECHO) $(ECHO) '<SOFTPKG NAME="$(DISTNAME)" VERSION="0,35,0,0">' > $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '    <TITLE>$(DISTNAME)</TITLE>' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '    <ABSTRACT>TTF font support for Perl</ABSTRACT>' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '    <AUTHOR>martin_hosken at sil.org</AUTHOR>' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '    <IMPLEMENTATION>' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '        <OS NAME="$(OSNAME)" />' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '        <ARCHITECTURE NAME="i586-linux-thread-multi" />' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '        <CODEBASE HREF="" />' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '    </IMPLEMENTATION>' >> $(DISTNAME).ppd
+	$(NOECHO) $(ECHO) '</SOFTPKG>' >> $(DISTNAME).ppd
 
+
 # --- MakeMaker pm_to_blib section:
 
 pm_to_blib: $(TO_INST_PM)
-	@$(PERL) "-I$(INST_ARCHLINE)" "-I$(INST_LIB)" \
-	"-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Install \
-	-e "pm_to_blib({ qw[$(PM_TO_BLIB)] }, '$(INST_LIB)\auto')
-	@$(TOUCH) $@
+	$(NOECHO) $(PERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', '\''$(PM_FILTER)'\'')'\
+	  lib/Font/TTF/Vmtx.pm blib/lib/Font/TTF/Vmtx.pm \
+	  lib/Font/TTF/Hhea.pm blib/lib/Font/TTF/Hhea.pm \
+	  lib/ttfmod.pl blib/lib/ttfmod.pl \
+	  lib/Font/TTF/Kern/ClassArray.pm blib/lib/Font/TTF/Kern/ClassArray.pm \
+	  lib/Font/TTF/Head.pm blib/lib/Font/TTF/Head.pm \
+	  lib/Font/TTF/Fmtx.pm blib/lib/Font/TTF/Fmtx.pm \
+	  lib/Font/TTF/AATKern.pm blib/lib/Font/TTF/AATKern.pm \
+	  lib/Font/TTF/OldMort.pm blib/lib/Font/TTF/OldMort.pm \
+	  lib/Font/TTF/Bsln.pm blib/lib/Font/TTF/Bsln.pm \
+	  lib/Font/TTF/Manual.pod blib/lib/Font/TTF/Manual.pod \
+	  lib/Font/TTF/Font.pm blib/lib/Font/TTF/Font.pm \
+	  lib/Font/TTF/GDEF.pm blib/lib/Font/TTF/GDEF.pm \
+	  lib/Font/TTF/Vhea.pm blib/lib/Font/TTF/Vhea.pm \
+	  lib/Font/TTF/Fpgm.pm blib/lib/Font/TTF/Fpgm.pm \
+	  lib/Font/TTF/GSUB.pm blib/lib/Font/TTF/GSUB.pm \
+	  lib/Font/TTF/Mort/Contextual.pm blib/lib/Font/TTF/Mort/Contextual.pm \
+	  lib/Font/TTF/OS_2.pm blib/lib/Font/TTF/OS_2.pm \
+	  lib/Font/TTF/Useall.pm blib/lib/Font/TTF/Useall.pm \
+	  lib/Font/TTF/Ttc.pm blib/lib/Font/TTF/Ttc.pm \
+	  lib/Font/TTF/Feat.pm blib/lib/Font/TTF/Feat.pm \
+	  lib/Font/TTF/Name.pm blib/lib/Font/TTF/Name.pm \
+	  lib/Font/TTF/Kern.pm blib/lib/Font/TTF/Kern.pm \
+	  lib/Font/TTF/Kern/StateTable.pm blib/lib/Font/TTF/Kern/StateTable.pm \
+	  lib/Font/TTF/OldCmap.pm blib/lib/Font/TTF/OldCmap.pm \
+	  lib/Font/TTF/Segarr.pm blib/lib/Font/TTF/Segarr.pm \
+	  lib/Font/TTF/Changes blib/lib/Font/TTF/Changes \
+	  lib/Font/TTF/Loca.pm blib/lib/Font/TTF/Loca.pm \
+	  lib/Font/TTF/Mort/Insertion.pm blib/lib/Font/TTF/Mort/Insertion.pm \
+	  lib/Font/TTF/Mort/Chain.pm blib/lib/Font/TTF/Mort/Chain.pm \
+	  lib/Font/TTF/Mort/Rearrangement.pm blib/lib/Font/TTF/Mort/Rearrangement.pm \
+	  lib/Font/TTF/Fdsc.pm blib/lib/Font/TTF/Fdsc.pm \
+	  lib/Font/TTF/Cvt_.pm blib/lib/Font/TTF/Cvt_.pm \
+	  lib/Font/TTF/XMLparse.pm blib/lib/Font/TTF/XMLparse.pm \
+	  lib/Font/TTF/Maxp.pm blib/lib/Font/TTF/Maxp.pm \
+	  lib/Font/TTF/AATutils.pm blib/lib/Font/TTF/AATutils.pm \
+	  lib/Font/TTF/Prop.pm blib/lib/Font/TTF/Prop.pm \
+	  lib/Font/TTF/Coverage.pm blib/lib/Font/TTF/Coverage.pm \
+	  lib/Font/TTF/PCLT.pm blib/lib/Font/TTF/PCLT.pm \
+	  lib/Font/TTF/Mort/Ligature.pm blib/lib/Font/TTF/Mort/Ligature.pm \
+	  lib/Font/TTF/Win32.pm blib/lib/Font/TTF/Win32.pm \
+	  lib/Font/TTF/Utils.pm blib/lib/Font/TTF/Utils.pm \
+	  lib/Font/TTF/Ttopen.pm blib/lib/Font/TTF/Ttopen.pm \
+	  lib/Font/TTF/Kern/Subtable.pm blib/lib/Font/TTF/Kern/Subtable.pm \
+	  lib/Font/TTF/Hmtx.pm blib/lib/Font/TTF/Hmtx.pm \
+	  lib/Font/TTF/Kern/OrderedList.pm blib/lib/Font/TTF/Kern/OrderedList.pm \
+	  lib/Font/TTF/Glyph.pm blib/lib/Font/TTF/Glyph.pm \
+	  lib/Font/TTF/Mort.pm blib/lib/Font/TTF/Mort.pm \
+	  lib/Font/TTF/Prep.pm blib/lib/Font/TTF/Prep.pm \
+	  lib/Font/TTF/Kern/CompactClassArray.pm blib/lib/Font/TTF/Kern/CompactClassArray.pm \
+	  lib/Font/TTF/Hdmx.pm blib/lib/Font/TTF/Hdmx.pm \
+	  lib/Font/TTF/Cmap.pm blib/lib/Font/TTF/Cmap.pm \
+	  lib/Font/TTF/GPOS.pm blib/lib/Font/TTF/GPOS.pm \
+	  lib/Font/TTF/PSNames.pm blib/lib/Font/TTF/PSNames.pm \
+	  lib/Font/TTF/Mort/Noncontextual.pm blib/lib/Font/TTF/Mort/Noncontextual.pm \
+	  lib/Font/TTF/Post.pm blib/lib/Font/TTF/Post.pm \
+	  lib/Font/TTF/Anchor.pm blib/lib/Font/TTF/Anchor.pm \
+	  lib/Font/TTF/Glyf.pm blib/lib/Font/TTF/Glyf.pm \
+	  lib/Font/TTF/LTSH.pm blib/lib/Font/TTF/LTSH.pm \
+	  lib/Font/TTF/Table.pm blib/lib/Font/TTF/Table.pm \
+	  lib/Font/TTF/Delta.pm blib/lib/Font/TTF/Delta.pm \
+	  lib/Font/TTF/Mort/Subtable.pm blib/lib/Font/TTF/Mort/Subtable.pm 
+	$(NOECHO) $(TOUCH) $@
 
-
-
 # --- MakeMaker selfdocument section:
 
 

Modified: packages/libfont-ttf-perl/trunk/Makefile.PL
===================================================================
--- packages/libfont-ttf-perl/trunk/Makefile.PL	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/Makefile.PL	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,41 +1,39 @@
-use ExtUtils::MakeMaker;
-
- at scripts = grep {-f } glob("scripts/*.*");
- at theselibs = grep {-f } glob("lib/Font/TTF/*");
-
-# incantation to enable MY::pm_to_blib later on
-push(@ExtUtils::MakeMaker::Overridable, qw(pm_to_blib)) if ($^O eq 'MSWin32');
-
-WriteMakefile (
-        NAME => "Font::TTF",
-        VERSION_FROM => "lib/Font/TTF/Font.pm",
-        EXE_FILES => \@scripts,
-#        HTMLLIBPODS => {map {my $t = $_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @theselibs},
-#        HTMLSCRIPTPODS => {map {my $t=$_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @scripts},
-        AUTHOR => "martin_hosken\@sil.org",
-        ABSTRACT => "TTF font support for Perl",
-        dist => { 'TO_UNIX' => 'perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"' }
-    );
-
-if ($^O eq 'MSWin32') {
-# incantation to solve the problem of everyone's $Config{make} being 'nmake'
-# when we want 'pmake'. And $Config{} is read only.
-# actually, this is just a copy of the code from ExtUtiles::MM_Win32 tidied
-# up (to expose tabs) and the dependency on Config removed
-sub MY::pm_to_blib
-{
-    my $self = shift;
-    my($autodir) = $self->catdir('$(INST_LIB)','auto');
-    return <<"EOT";
-
-pm_to_blib: \$(TO_INST_PM)
-\t$self->{NOECHO}\$(PERL) \"-I\$(INST_ARCHLINE)\" \"-I\$(INST_LIB)\" \\
-\t\"-I\$(PERL_ARCHLIB)\" \"-I\$(PERL_LIB)\" -MExtUtils::Install \\
-\t-e \"pm_to_blib({ qw[\$(PM_TO_BLIB)] }, '$autodir')
-\t$self->{NOECHO}\$(TOUCH) \$@
-
-EOT
-}
-
-}
-
+use ExtUtils::MakeMaker;
+
+ at theselibs = grep {-f } glob("lib/Font/TTF/*");
+
+# incantation to enable MY::pm_to_blib later on
+push(@ExtUtils::MakeMaker::Overridable, qw(pm_to_blib)) if ($^O eq 'MSWin32');
+
+WriteMakefile (
+        NAME => "Font::TTF",
+        VERSION_FROM => "lib/Font/TTF/Font.pm",
+#        HTMLLIBPODS => {map {my $t = $_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @theselibs},
+#        HTMLSCRIPTPODS => {map {my $t=$_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @scripts},
+        AUTHOR => "martin_hosken\@sil.org",
+        ABSTRACT => "TTF font support for Perl",
+        dist => { 'TO_UNIX' => 'perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"' }
+    );
+
+if ($^O eq 'MSWin32') {
+# incantation to solve the problem of everyone's $Config{make} being 'nmake'
+# when we want 'pmake'. And $Config{} is read only.
+# actually, this is just a copy of the code from ExtUtiles::MM_Win32 tidied
+# up (to expose tabs) and the dependency on Config removed
+sub MY::pm_to_blib
+{
+    my $self = shift;
+    my($autodir) = $self->catdir('$(INST_LIB)','auto');
+    return <<"EOT";
+
+pm_to_blib: \$(TO_INST_PM)
+\t$self->{NOECHO}\$(PERL) \"-I\$(INST_ARCHLINE)\" \"-I\$(INST_LIB)\" \\
+\t\"-I\$(PERL_ARCHLIB)\" \"-I\$(PERL_LIB)\" -MExtUtils::Install \\
+\t-e \"pm_to_blib({ qw[\$(PM_TO_BLIB)] }, '$autodir')
+\t$self->{NOECHO}\$(TOUCH) \$@
+
+EOT
+}
+
+}
+

Modified: packages/libfont-ttf-perl/trunk/README.TXT
===================================================================
--- packages/libfont-ttf-perl/trunk/README.TXT	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/README.TXT	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,163 +1,163 @@
-        Perl Module: Font::TTF
-
-Announcing:
-
-The addition of many new tables including support for the OpenType
-tables: GSUB, GDEF and GPOS and also a bunch of AAT tables. The module
-now also supports XML output and a buggy XML input. All of these new
-features should be considered as Alpha code and particularly the XML
-language is liable to change for some of the more complex table types.
-
-After a long wait, Name tables now try to return UTF8 strings where
-possible. The deprecation period has now passed and by default the
-Name.pm returns strings as utf8 where possible. See Name.pm for details.
-To get old behaviour, set C<$Font::TTF::Name::utf8> to 0.
-
-Solution to the installation problem for users on Win32, without make.
-Use pmake instead. Wherever you see the command: make, in this document,
-type: pmake instead.
-
-=head1 Introduction
-
-Perl module for TrueType font hacking. Supports reading, processing and
-writing of the following tables: GDEF, GPOS, GSUB, LTSH, OS/2, PCLT,
-bsln, cmap, cvt, fdsc, feat, fpgm, glyf, hdmx, head, hhea, hmtx, kern,
-loca, maxp, mort, name, post, prep, prop, vhea, vmtx and the reading and
-writing of all other table types.
-
-In short, you can do almost anything with a standard TrueType font with
-this module. Be Brave!
-
-The module also includes various useful utilities:
-
-check_attach    Checks an attachment point database against a font. See
-                ttfbuilder for details
-eurofix         Fixes fonts created for Win95 so that they work in Win98 and NT4
-                sp4, Win2K and so on.
-hackos2         This old favourite lets you do unspeakable things to your OS/2
-                table, including sorting Unicode range bits and codepage bits
-                (Perl 4)
-psfix           Tidy up the postscript names in a font to be Postscript
-                conformant
-ttfbuilder      Build fonts from other fonts, including ligature building, etc.
-                Has excellent explanatory POD
-ttfname         Renames a font and allows access to name strings. This needs
-                a rewrite (Perl 4)
-ttfremap        Simpler font subsetter than ttfbuilder
-
-
-Also included are the following example scripts. To use these you will need to
-install them manually from the examples directory included in the distribution.
-
-StripCmap       Strips a specified cmap from the given font
-addpclt         Makes up values and adds a PCLT table to a font
-makemono        Makes a font mono spaced (Perl 4)
-symbol.rmp      Example remap file for ttfremap
-ttfdeltable     Deletes a specified table from a font
-ttfenc          Create .enc, .afm, .tfm and .map entry for a ttf file based on
-                Unicode rather than postscript. Requires afm2tfm and ttf2afm.
-ttfwidth        Create a table of interesting information regarding widths of
-                characters. FRET is a much better tool for this now (Perl 4)
-xmldump         Dumps a font as XML. The XML needs some work for some of the
-                more complex tables
-zerohyph        Create a zero width hyphen in place of the normal hyphen
-
-Any suggestions, improvements, additions, subclasses, etc. would be gratefully
-received and probably included in a future release. Please send them to me.
-
-This module has been tested on Win32, Unix and Mac.
-
-=head1 SYNOPSIS
-
-Here is the regression test (you provide your own font). Run it once and then
-again on the output of the first run. There should be no differences between
-the outputs of the two runs.
-
-    use Font::TTF::Font;
-
-    $f = Font::TTF::Font->open($ARGV[0]);
-
-    # force a read of all the tables
-    $f->tables_do(sub { $_[0]->read; });
-
-    # force read of all glyphs (use read_dat to use lots of memory!)
-    # $f->{'loca'}->glyphs_do(sub { $_[0]->read; });
-    $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; });
-    # NB. no need to $g->update since $_[0]->{'glyf'}->out will do it for us
-
-    $f->out($ARGV[1]);
-    $f->DESTROY;               # forces close of $in and maybe memory reclaim!
-
-=head1 PERL4 Utilities
-
-As an aside, the following Perl4 system and utilities have been slung in:
-
-perlmod.pl      This is the Perl4 library for these programs
-
-addpclt         Create a PCLT table for a font with lots of junk in it
-Hackos2         Do all sorts of unspeakable things to the OS/2 table
-MakeMono        Force a font to be mono-spaced
-Ttfname         Rename a font (and set any other name strings)
-TTFWIDTH        Find the centre of every glyph in a font and print report
-
-=head1 Installation
-
-If you have received this package as part of an Activestate PPM style .zip file
-then type
-
-    ppm install Font-TTF.ppd
-
-Otherwise.
-
-To configure this module, cd to the directory that contains this README file
-and type the following.
-
-    perl Makefile.PL
-
-Alternatively, if you plan to install Font::TTF somewhere other than
-your system's perl library directory. You can type something like this:
-
-    perl Makefile.PL PREFIX=/home/me/perl INSTALLDIRS=perl
-
-Then to build you run make.
-
-    make
-
-If you have write access to the perl library directories, you may then
-install by typing:
-
-    make install
-
-To tidy up, type:
-
-    make realclean
-
-Win32 users should use pmake instead of make. Alternatively installation can be
-done on Win32 by typing:
-
-    Setup
-
-Or using the install feature in tools like WinZip.
-
-=head1 CHANGES
-
-=head2 Future Changes
-
-I do not anticipate any more restructuring changes (but reserve the right to do so).
-One area I am waiting to change is that of the Name table where I would like to 
-pass strings using UTF-8. When the UTF-8 version of Perl is ported to Win32 then I
-can start the changes and cross-mappings (for the Mac).
-
-=head1 AUTHOR
-
-Martin Hosken L<Martin_Hosken at sil.org>
-
-Copyright Martin Hosken 1998 and following.
-
-No warranty or expression of effectiveness for anything, least of all anyone's
-safety, is implied in this software or documentation.
-
-=head2 Licensing
-
-The Perl TTF module is licensed under the Perl Artistic License.
-
+        Perl Module: Font::TTF
+
+Announcing:
+
+The addition of many new tables including support for the OpenType
+tables: GSUB, GDEF and GPOS and also a bunch of AAT tables. The module
+now also supports XML output and a buggy XML input. All of these new
+features should be considered as Alpha code and particularly the XML
+language is liable to change for some of the more complex table types.
+
+After a long wait, Name tables now try to return UTF8 strings where
+possible. The deprecation period has now passed and by default the
+Name.pm returns strings as utf8 where possible. See Name.pm for details.
+To get old behaviour, set C<$Font::TTF::Name::utf8> to 0.
+
+Solution to the installation problem for users on Win32, without make.
+Use pmake instead. Wherever you see the command: make, in this document,
+type: pmake instead.
+
+=head1 Introduction
+
+Perl module for TrueType font hacking. Supports reading, processing and
+writing of the following tables: GDEF, GPOS, GSUB, LTSH, OS/2, PCLT,
+bsln, cmap, cvt, fdsc, feat, fpgm, glyf, hdmx, head, hhea, hmtx, kern,
+loca, maxp, mort, name, post, prep, prop, vhea, vmtx and the reading and
+writing of all other table types.
+
+In short, you can do almost anything with a standard TrueType font with
+this module. Be Brave!
+
+The module also includes various useful utilities:
+
+check_attach    Checks an attachment point database against a font. See
+                ttfbuilder for details
+eurofix         Fixes fonts created for Win95 so that they work in Win98 and NT4
+                sp4, Win2K and so on.
+hackos2         This old favourite lets you do unspeakable things to your OS/2
+                table, including sorting Unicode range bits and codepage bits
+                (Perl 4)
+psfix           Tidy up the postscript names in a font to be Postscript
+                conformant
+ttfbuilder      Build fonts from other fonts, including ligature building, etc.
+                Has excellent explanatory POD
+ttfname         Renames a font and allows access to name strings. This needs
+                a rewrite (Perl 4)
+ttfremap        Simpler font subsetter than ttfbuilder
+
+
+Also included are the following example scripts. To use these you will need to
+install them manually from the examples directory included in the distribution.
+
+StripCmap       Strips a specified cmap from the given font
+addpclt         Makes up values and adds a PCLT table to a font
+makemono        Makes a font mono spaced (Perl 4)
+symbol.rmp      Example remap file for ttfremap
+ttfdeltable     Deletes a specified table from a font
+ttfenc          Create .enc, .afm, .tfm and .map entry for a ttf file based on
+                Unicode rather than postscript. Requires afm2tfm and ttf2afm.
+ttfwidth        Create a table of interesting information regarding widths of
+                characters. FRET is a much better tool for this now (Perl 4)
+xmldump         Dumps a font as XML. The XML needs some work for some of the
+                more complex tables
+zerohyph        Create a zero width hyphen in place of the normal hyphen
+
+Any suggestions, improvements, additions, subclasses, etc. would be gratefully
+received and probably included in a future release. Please send them to me.
+
+This module has been tested on Win32, Unix and Mac.
+
+=head1 SYNOPSIS
+
+Here is the regression test (you provide your own font). Run it once and then
+again on the output of the first run. There should be no differences between
+the outputs of the two runs.
+
+    use Font::TTF::Font;
+
+    $f = Font::TTF::Font->open($ARGV[0]);
+
+    # force a read of all the tables
+    $f->tables_do(sub { $_[0]->read; });
+
+    # force read of all glyphs (use read_dat to use lots of memory!)
+    # $f->{'loca'}->glyphs_do(sub { $_[0]->read; });
+    $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; });
+    # NB. no need to $g->update since $_[0]->{'glyf'}->out will do it for us
+
+    $f->out($ARGV[1]);
+    $f->DESTROY;               # forces close of $in and maybe memory reclaim!
+
+=head1 PERL4 Utilities
+
+As an aside, the following Perl4 system and utilities have been slung in:
+
+perlmod.pl      This is the Perl4 library for these programs
+
+addpclt         Create a PCLT table for a font with lots of junk in it
+Hackos2         Do all sorts of unspeakable things to the OS/2 table
+MakeMono        Force a font to be mono-spaced
+Ttfname         Rename a font (and set any other name strings)
+TTFWIDTH        Find the centre of every glyph in a font and print report
+
+=head1 Installation
+
+If you have received this package as part of an Activestate PPM style .zip file
+then type
+
+    ppm install Font-TTF.ppd
+
+Otherwise.
+
+To configure this module, cd to the directory that contains this README file
+and type the following.
+
+    perl Makefile.PL
+
+Alternatively, if you plan to install Font::TTF somewhere other than
+your system's perl library directory. You can type something like this:
+
+    perl Makefile.PL PREFIX=/home/me/perl INSTALLDIRS=perl
+
+Then to build you run make.
+
+    make
+
+If you have write access to the perl library directories, you may then
+install by typing:
+
+    make install
+
+To tidy up, type:
+
+    make realclean
+
+Win32 users should use pmake instead of make. Alternatively installation can be
+done on Win32 by typing:
+
+    Setup
+
+Or using the install feature in tools like WinZip.
+
+=head1 CHANGES
+
+=head2 Future Changes
+
+I do not anticipate any more restructuring changes (but reserve the right to do so).
+One area I am waiting to change is that of the Name table where I would like to 
+pass strings using UTF-8. When the UTF-8 version of Perl is ported to Win32 then I
+can start the changes and cross-mappings (for the Mac).
+
+=head1 AUTHOR
+
+Martin Hosken L<Martin_Hosken at sil.org>
+
+Copyright Martin Hosken 1998 and following.
+
+No warranty or expression of effectiveness for anything, least of all anyone's
+safety, is implied in this software or documentation.
+
+=head2 Licensing
+
+The Perl TTF module is licensed under the Perl Artistic License.
+

Deleted: packages/libfont-ttf-perl/trunk/Setup.bat
===================================================================
--- packages/libfont-ttf-perl/trunk/Setup.bat	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/Setup.bat	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,4 +0,0 @@
-perl Makefile.PL
-call pmake install
-call pmake realclean
-

Modified: packages/libfont-ttf-perl/trunk/debian/changelog
===================================================================
--- packages/libfont-ttf-perl/trunk/debian/changelog	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/debian/changelog	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,3 +1,12 @@
+libfont-ttf-perl (0.35-1) unstable; urgency=low
+
+  * New upstream release
+  * Transferred maintainership to the Debian Perl group
+  * Fixed debian/watch, as it was reporting another module with a
+    seemingly derived name
+
+ -- Gunnar Wolf <gwolf at debian.org>  Wed, 25 May 2005 10:21:11 -0500
+
 libfont-ttf-perl (0.34-4) unstable; urgency=low
 
   * Fixed a little rules ordering problem in debian/rules which led to a

Modified: packages/libfont-ttf-perl/trunk/debian/control
===================================================================
--- packages/libfont-ttf-perl/trunk/debian/control	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/debian/control	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,7 +1,8 @@
 Source: libfont-ttf-perl
 Section: perl
 Priority: optional
-Maintainer: Gunnar Wolf <gwolf at debian.org>
+Maintainer: Debian Perl Group <pkg-perl-maintainers at lists.alioth.debian.org>
+Uploaders: Gunnar Wolf <gwolf at debian.org>
 Build-Depends-Indep: debhelper (>= 3.0.5), perl (>= 5.8.0-19)
 Standards-Version: 3.6.1
 

Modified: packages/libfont-ttf-perl/trunk/debian/watch
===================================================================
--- packages/libfont-ttf-perl/trunk/debian/watch	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/debian/watch	2005-05-25 15:22:16 UTC (rev 1050)
@@ -3,4 +3,4 @@
 # to check for upstream updates and more.
 # Site		Directory		Pattern			Version	Script
 version=2
-http://www.cpan.org/modules/by-module/Font/Font-TTF-(.*)\.tar\.gz
+http://www.cpan.org/modules/by-module/Font/Font-TTF-(\d.*)\.tar\.gz

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATKern.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATKern.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATKern.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,140 +1,140 @@
-package Font::TTF::AATKern;
-
-=head1 NAME
-
-Font::TTF::AATKern
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Kern::Subtable;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    
-    $self->SUPER::read or return $self;
-
-    my ($dat, $fh, $numSubtables);
-    $fh = $self->{' INFILE'};
-
-    $fh->read($dat, 8);
-    ($self->{'version'}, $numSubtables) = TTF_Unpack("fL", $dat);
-    
-    my $subtables = [];
-    foreach (1 .. $numSubtables) {
-        my $subtableStart = $fh->tell();
-        
-        $fh->read($dat, 8);
-        my ($length, $coverage, $tupleIndex) = TTF_Unpack("LSS", $dat);
-        my $type = $coverage & 0x00ff;
-
-        my $subtable = Font::TTF::Kern::Subtable->create($type, $coverage, $length);
-        $subtable->read($fh);
-
-        $subtable->{'tupleIndex'} = $tupleIndex if $subtable->{'variation'};
-        $subtable->{' PARENT'} = $self;
-        push @$subtables, $subtable;
-    }
-
-    $self->{'subtables'} = $subtables;
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    my $subtables = $self->{'subtables'};
-    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$subtables));
-
-    foreach (@$subtables) {
-        $_->out($fh);
-    }
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    $self->read unless $self->{' read'};
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $fh->printf("version %f\n", $self->{'version'});
-    
-    my $subtables = $self->{'subtables'};
-    foreach (@$subtables) {
-        $_->print($fh);
-    }
-}
-
-sub dumpXML
-{
-    my ($self, $fh) = @_;
-    $self->read unless $self->{' read'};
-
-    my $post = $self->{' PARENT'}->{'post'};
-    $post->read;
-    
-    $fh = 'STDOUT' unless defined $fh;
-    $fh->printf("<kern version=\"%f\">\n", $self->{'version'});
-    
-    my $subtables = $self->{'subtables'};
-    foreach (@$subtables) {
-        $fh->printf("<%s", $_->type);
-        $fh->printf(" vertical=\"1\"") if $_->{'vertical'};
-        $fh->printf(" crossStream=\"1\"") if $_->{'crossStream'};
-        $fh->printf(" variation=\"1\"") if $_->{'variation'};
-        $fh->printf(" tupleIndex=\"%s\"", $_->{'tupleIndex'}) if exists $_->{'tupleIndex'};
-        $fh->printf(">\n");
-
-        $_->dumpXML($fh);
-
-        $fh->printf("</%s>\n", $_->type);
-    }
-
-    $fh->printf("</kern>\n");
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::AATKern;
+
+=head1 NAME
+
+Font::TTF::AATKern
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Kern::Subtable;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    
+    $self->SUPER::read or return $self;
+
+    my ($dat, $fh, $numSubtables);
+    $fh = $self->{' INFILE'};
+
+    $fh->read($dat, 8);
+    ($self->{'version'}, $numSubtables) = TTF_Unpack("fL", $dat);
+    
+    my $subtables = [];
+    foreach (1 .. $numSubtables) {
+        my $subtableStart = $fh->tell();
+        
+        $fh->read($dat, 8);
+        my ($length, $coverage, $tupleIndex) = TTF_Unpack("LSS", $dat);
+        my $type = $coverage & 0x00ff;
+
+        my $subtable = Font::TTF::Kern::Subtable->create($type, $coverage, $length);
+        $subtable->read($fh);
+
+        $subtable->{'tupleIndex'} = $tupleIndex if $subtable->{'variation'};
+        $subtable->{' PARENT'} = $self;
+        push @$subtables, $subtable;
+    }
+
+    $self->{'subtables'} = $subtables;
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    my $subtables = $self->{'subtables'};
+    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$subtables));
+
+    foreach (@$subtables) {
+        $_->out($fh);
+    }
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    $self->read unless $self->{' read'};
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $fh->printf("version %f\n", $self->{'version'});
+    
+    my $subtables = $self->{'subtables'};
+    foreach (@$subtables) {
+        $_->print($fh);
+    }
+}
+
+sub dumpXML
+{
+    my ($self, $fh) = @_;
+    $self->read unless $self->{' read'};
+
+    my $post = $self->{' PARENT'}->{'post'};
+    $post->read;
+    
+    $fh = 'STDOUT' unless defined $fh;
+    $fh->printf("<kern version=\"%f\">\n", $self->{'version'});
+    
+    my $subtables = $self->{'subtables'};
+    foreach (@$subtables) {
+        $fh->printf("<%s", $_->type);
+        $fh->printf(" vertical=\"1\"") if $_->{'vertical'};
+        $fh->printf(" crossStream=\"1\"") if $_->{'crossStream'};
+        $fh->printf(" variation=\"1\"") if $_->{'variation'};
+        $fh->printf(" tupleIndex=\"%s\"", $_->{'tupleIndex'}) if exists $_->{'tupleIndex'};
+        $fh->printf(">\n");
+
+        $_->dumpXML($fh);
+
+        $fh->printf("</%s>\n", $_->type);
+    }
+
+    $fh->printf("</kern>\n");
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATutils.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATutils.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/AATutils.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,688 +1,688 @@
-package Font::TTF::AATutils;
-
-use strict;
-use vars qw(@ISA @EXPORT);
-require Exporter;
-
-use Font::TTF::Utils;
-
- at ISA = qw(Exporter);
- at EXPORT = qw(
-    AAT_read_lookup
-    AAT_pack_lookup
-    AAT_write_lookup
-    AAT_pack_classes
-    AAT_write_classes
-    AAT_pack_states
-    AAT_write_states
-    AAT_read_state_table
-    AAT_read_subtable
-    xmldump
-);
-
-sub xmldump
-{
-    my ($var, $links, $depth, $processedVars, $type) = @_;
-
-    $processedVars = {} unless (defined $processedVars);
-    print("<?xml version='1.0' encoding='UTF-8'?>\n") if $depth == 0;    # not necessarily true encoding for all text!
-
-    my $indent = "\t" x $depth;
-
-    my ($objType, $addr) = ($var =~ m/^.+=(.+)\((.+)\)$/);
-    unless (defined $type) {
-        if (defined $addr) {
-            if (defined $processedVars->{$addr}) {
-                if ($links) {
-                    printf("%s%s\n", $indent, "<a href=\"#$addr\">$objType</a>");
-                }
-                else {
-                    printf("%s%s\n", $indent, "<a>$objType</a>");
-                }
-                return;
-            }
-            $processedVars->{$addr} = 1;
-        }
-    }
-    
-    $type = ref $var unless defined $type;
-    
-    if ($type eq 'REF') {
-        printf("%s<ref val=\"%s\"/>\n", $indent, $$var);
-    }
-    elsif ($type eq 'SCALAR') {
-        printf("%s<scalar>%s</scalar>\n", $indent, $var);
-    }
-    elsif ($type eq 'ARRAY') {
-        # printf("%s<array>\n", $indent);
-        foreach (0 .. $#$var) {
-            if (ref($var->[$_])) {
-                printf("%s<arrayItem index=\"%d\">\n", $indent, $_);
-                xmldump($var->[$_], $links, $depth + 1, $processedVars);
-                printf("%s</arrayItem>\n", $indent);
-            }
-            else {
-                printf("%s<arrayItem index=\"%d\">%s</arrayItem>\n", $indent, $_, $var->[$_]);
-            }
-        }
-        # printf("%s</array>\n", $indent);
-    }
-    elsif ($type eq 'HASH') {
-        # printf("%s<hash>\n", $indent);
-        foreach (sort keys %$var) {
-            if (ref($var->{$_})) {
-                printf("%s<hashElem key=\"%s\">\n", $indent, $_);
-                xmldump($var->{$_}, $links, $depth + 1, $processedVars);
-                printf("%s</hashElem>\n", $indent);
-            }
-            else {
-                printf("%s<hashElem key=\"%s\">%s</hashElem>\n", $indent, $_, $var->{$_});
-            }
-        }
-        # printf("%s</hash>\n", $indent);
-    }
-    elsif ($type eq 'CODE') {
-        printf("%s<CODE/>\n", $indent, $var);
-    }
-    elsif ($type eq 'GLOB') {
-        printf("%s<GLOB/>\n", $indent, $var);
-    }
-    elsif ($type eq '') {
-        printf("%s<val>%s</val>\n", $indent, $var);
-    }
-    else {
-        if ($links) {
-            printf("%s<obj class=\"%s\" id=\"#%s\">\n", $indent, $type, $addr);
-        }
-        else {
-            printf("%s<obj class=\"%s\">\n", $indent, $type);
-        }
-        xmldump($var, $links, $depth + 1, $processedVars, $objType);
-        printf("%s</obj>\n", $indent);
-    }
-}
-
-=head2 ($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits)
-
-=cut
-
-sub AAT_read_subtable
-{
-    my ($fh, $baseOffset, $subtableStart, $limits) = @_;
-    
-    my $limit = 0xffffffff;
-    foreach (@$limits) {
-        $limit = $_ if ($_ > $subtableStart and $_ < $limit);
-    }
-    die if $limit == 0xffffffff;
-    
-    my $dat;
-    $fh->seek($baseOffset + $subtableStart, IO::File::SEEK_SET);
-    $fh->read($dat, $limit - $subtableStart);
-    
-    $dat;
-}
-
-=head2 $length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry)
-
-$packEntry is a subroutine for packing an entry into binary form, called as
-
-$dat = $packEntry($entry, $entryTable, $numEntries)
-
-where the entry is a comma-separated list of nextStateOffset, flags, actions
-
-=cut
-
-sub AAT_pack_state_table
-{
-    my ($classes, $states, $numExtraTables, $packEntry) = @_;
-    
-    my ($dat) = pack("n*", (0) x (4 + $numExtraTables));    # placeholders for stateSize, classTable, stateArray, entryTable
-    
-    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
-    my (@classTable, $i);
-    foreach $i (0 .. $#$classes) {
-        my $class = $classes->[$i];
-        foreach (@$class) {
-            $firstGlyph = $_ if $_ < $firstGlyph;
-            $lastGlyph = $_ if $_ > $lastGlyph;
-            $classTable[$_] = $i;
-        }
-    }
-    
-    my $classTable = length($dat);
-    $dat .= pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
-                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph));
-    $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
-    
-    my $stateArray = length($dat);
-    my (@entries, %entries);
-    my $state = $states->[0];
-    my $stateSize = @$state;
-    die "stateSize below minimum allowed (4)" if $stateSize < 4;
-    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
-    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
-
-    foreach (@$states) {
-        die "inconsistent state size" if @$_ != $stateSize;
-        foreach (@$_) {
-            my $actions = $_->{'actions'};
-            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions);
-            if (not defined $entries{$entry}) {
-                push @entries, $entry;
-                $entries{$entry} = $#entries;
-                die "too many different state array entries" if $#entries == 256;
-            }
-            $dat .= pack("C", $entries{$entry});
-        }
-    }
-    $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
-    
-    my $entryTable = length($dat);
-    $dat .= map { &$packEntry($_, $entryTable, $#entries + 1) } @entries;
-    
-    my ($dat1) = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable);
-    substr($dat, 0, length($dat1)) = $dat1;
-    
-    return $dat;
-}
-
-sub AAT_write_state_table
-{
-    my ($fh, $classes, $states, $numExtraTables, $packEntry) = @_;
-    
-    my $stateTableStart = $fh->tell();
-
-    $fh->print(pack("n*", (0) x (4 + $numExtraTables)));    # placeholders for stateSize, classTable, stateArray, entryTable
-    
-    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
-    my (@classTable, $i);
-    foreach $i (0 .. $#$classes) {
-        my $class = $classes->[$i];
-        foreach (@$class) {
-            $firstGlyph = $_ if $_ < $firstGlyph;
-            $lastGlyph = $_ if $_ > $lastGlyph;
-            $classTable[$_] = $i;
-        }
-    }
-    
-    my $classTable = $fh->tell() - $stateTableStart;
-    $fh->print(pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
-                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)));
-    $fh->print(pack("C", 0)) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
-    
-    my $stateArray = $fh->tell() - $stateTableStart;
-    my (@entries, %entries);
-    my $state = $states->[0];
-    my $stateSize = @$state;
-    die "stateSize below minimum allowed (4)" if $stateSize < 4;
-    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
-    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
-
-    foreach (@$states) {
-        die "inconsistent state size" if @$_ != $stateSize;
-        foreach (@$_) {
-            my $actions = $_->{'actions'};
-            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions);
-            if (not defined $entries{$entry}) {
-                push @entries, $entry;
-                $entries{$entry} = $#entries;
-                die "too many different state array entries" if $#entries == 256;
-            }
-            $fh->print(pack("C", $entries{$entry}));
-        }
-    }
-    $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
-    
-    my $entryTable = $fh->tell() - $stateTableStart;
-    $fh->print(map { &$packEntry($_, $entryTable, $#entries + 1) } @entries);
-    
-    my $length = $fh->tell() - $stateTableStart;
-    $fh->seek($stateTableStart, IO::File::SEEK_SET);
-    $fh->print(pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable));
-    
-    $fh->seek($stateTableStart + $length, IO::File::SEEK_SET);
-    $length;
-}
-
-sub AAT_pack_classes
-{
-    my ($classes) = @_;
-    
-    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
-    my (@classTable, $i);
-    foreach $i (0 .. $#$classes) {
-        my $class = $classes->[$i];
-        foreach (@$class) {
-            $firstGlyph = $_ if $_ < $firstGlyph;
-            $lastGlyph = $_ if $_ > $lastGlyph;
-            $classTable[$_] = $i;
-        }
-    }
-    
-    my ($dat) = pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
-                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph));
-    $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
-    
-    return $dat;
-}
-
-sub AAT_write_classes
-{
-    my ($fh, $classes) = @_;
-    
-    $fh->print(AAT_pack_classes($fh, $classes));
-}
-
-sub AAT_pack_states
-{
-    my ($classes, $stateArray, $states, $buildEntryProc) = @_;
-    
-    my ($entries, %entryHash);
-    my $state = $states->[0];
-    my $stateSize = @$state;
-    
-    die "stateSize below minimum allowed (4)" if $stateSize < 4;
-    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
-    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
-    
-    my ($dat);
-    foreach (@$states) {
-        die "inconsistent state size" if @$_ != $stateSize;
-        foreach (@$_) {
-            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_));
-            if (not defined $entryHash{$entry}) {
-                push @$entries, $entry;
-                $entryHash{$entry} = $#$entries;
-                die "too many different state array entries" if $#$entries == 256;
-            }
-            $dat .= pack("C", $entryHash{$entry});
-        }
-    }
-    $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
-
-    ($dat, $stateSize, $entries);
-}
-
-sub AAT_write_states
-{
-    my ($fh, $classes, $stateArray, $states, $buildEntryProc) = @_;
-    
-    my ($entries, %entryHash);
-    my $state = $states->[0];
-    my $stateSize = @$state;
-    
-    die "stateSize below minimum allowed (4)" if $stateSize < 4;
-    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
-    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
-
-    foreach (@$states) {
-        die "inconsistent state size" if @$_ != $stateSize;
-        foreach (@$_) {
-            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_));
-            if (not defined $entryHash{$entry}) {
-                push @$entries, $entry;
-                $entryHash{$entry} = $#$entries;
-                die "too many different state array entries" if $#$entries == 256;
-            }
-            $fh->print(pack("C", $entryHash{$entry}));
-        }
-    }
-    $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
-
-    ($stateSize, $entries);
-}
-
-=head2 ($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords)
-
-=cut
-
-sub AAT_read_state_table
-{
-    my ($fh, $numActionWords) = @_;
-    
-    my $stateTableStart = $fh->tell();
-    my $dat;
-    $fh->read($dat, 8);
-    my ($stateSize, $classTable, $stateArray, $entryTable) = unpack("nnnn", $dat);
-    
-    my $classes;    # array of lists of glyphs
-
-    $fh->seek($stateTableStart + $classTable, IO::File::SEEK_SET);
-    $fh->read($dat, 4);
-    my ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
-    $fh->read($dat, $nGlyphs);
-    foreach (unpack("C*", $dat)) {
-        if ($_ != 1) {
-            my $class = $classes->[$_];
-            push(@$class, $firstGlyph);
-            $classes->[$_] = $class unless defined $classes->[$_];
-        }
-        $firstGlyph++;
-    }
-
-    $fh->seek($stateTableStart + $stateArray, IO::File::SEEK_SET);
-    my $states;    # array of arrays of hashes{nextState, flags, actions}
-
-    my $entrySize = 4 + ($numActionWords * 2);
-    my $lastState = 1;
-    my $entries;
-    while ($#$states < $lastState) {
-        $fh->read($dat, $stateSize);
-        my @stateEntries = unpack("C*", $dat);
-        my $state;
-        foreach (@stateEntries) {
-            if (not defined $entries->[$_]) {
-                my $loc = $fh->tell();
-                $fh->seek($stateTableStart + $entryTable + ($_ * $entrySize), IO::File::SEEK_SET);
-                $fh->read($dat, $entrySize);
-                my ($nextState, $flags, $actions);
-                ($nextState, $flags, @$actions) = unpack("n*", $dat);
-                $nextState -= $stateArray;
-                $nextState /= $stateSize;
-                $entries->[$_] = { 'nextState' => $nextState, 'flags' => $flags };
-                $entries->[$_]->{'actions'} = $actions if $numActionWords > 0;
-                $lastState = $nextState if ($nextState > $lastState);
-                $fh->seek($loc, IO::File::SEEK_SET);
-            }
-            push(@$state, $entries->[$_]);
-        }
-        push(@$states, $state);
-    }
-
-    ($classes, $states, $entries);
-}
-
-=head2 ($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default)
-
-=cut
-
-sub AAT_read_lookup
-{
-    my ($fh, $valueSize, $length, $default) = @_;
-
-    my $lookupStart = $fh->tell();
-    my ($dat, $unpackChar);
-    if ($valueSize == 1) {
-        $unpackChar = "C";
-    }
-    elsif ($valueSize == 2) {
-        $unpackChar = "n";
-    }
-    elsif ($valueSize == 4) {
-        $unpackChar = "N";
-    }
-    else {
-        die "unsupported value size";
-    }
-        
-    $fh->read($dat, 2);
-    my $format = unpack("n", $dat);
-    my $lookup;
-    
-    if ($format == 0) {
-        $fh->read($dat, $length - 2);
-        my $i = -1;
-        $lookup = { map { $i++; ($_ != $default) ? ($i, $_) : () } unpack($unpackChar . "*", $dat) };
-    }
-    
-    elsif ($format == 2) {
-        $fh->read($dat, 10);
-        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
-        die if $unitSize != 4 + $valueSize;
-        foreach (1 .. $nUnits) {
-            $fh->read($dat, $unitSize);
-            my ($lastGlyph, $firstGlyph, $value) = unpack("nn" . $unpackChar, $dat);
-            if ($firstGlyph != 0xffff and $value != $default) {
-                foreach ($firstGlyph .. $lastGlyph) {
-                    $lookup->{$_} = $value;
-                }
-            }
-        }
-    }
-    
-    elsif ($format == 4) {
-        $fh->read($dat, 10);
-        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
-        die if $unitSize != 6;
-        foreach (1 .. $nUnits) {
-            $fh->read($dat, $unitSize);
-            my ($lastGlyph, $firstGlyph, $offset) = unpack("nnn", $dat);
-            if ($firstGlyph != 0xffff) {
-                my $loc = $fh->tell();
-                $fh->seek($lookupStart + $offset, IO::File::SEEK_SET);
-                $fh->read($dat, ($lastGlyph - $firstGlyph + 1) * $valueSize);
-                my @values = unpack($unpackChar . "*", $dat);
-                foreach (0 .. $lastGlyph - $firstGlyph) {
-                    $lookup->{$firstGlyph + $_} = $values[$_] if $values[$_] != $default;
-                }
-                $fh->seek($loc, IO::File::SEEK_SET);
-            }
-        }
-    }
-    
-    elsif ($format == 6) {
-        $fh->read($dat, 10);
-        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
-        die if $unitSize != 2 + $valueSize;
-        foreach (1 .. $nUnits) {
-            $fh->read($dat, $unitSize);
-            my ($glyph, $value) = unpack("n" . $unpackChar, $dat);
-            $lookup->{$glyph} = $value if $glyph != 0xffff and $value != $default;
-        }
-    }
-    
-    elsif ($format == 8) {
-        $fh->read($dat, 4);
-        my ($firstGlyph, $glyphCount) = unpack("nn", $dat);
-        $fh->read($dat, $glyphCount * $valueSize);
-        $firstGlyph--;
-        $lookup = { map { $firstGlyph++; $_ != $default ? ($firstGlyph, $_) : () } unpack($unpackChar . "*", $dat) };
-    }
-    
-    else {
-        die "unknown lookup format";
-    }
-
-    $fh->seek($lookupStart + $length, IO::File::SEEK_SET);
-
-    ($format, $lookup);
-}
-
-=head2 AAT_write_lookup($fh, $format, $lookup, $valueSize, $default)
-
-=cut
-
-sub AAT_pack_lookup
-{
-    my ($format, $lookup, $valueSize, $default) = @_;
-
-    my $packChar;
-    if ($valueSize == 1) {
-        $packChar = "C";
-    }
-    elsif ($valueSize == 2) {
-        $packChar = "n";
-    }
-    elsif ($valueSize == 4) {
-        $packChar = "N";
-    }
-    else {
-        die "unsupported value size";
-    }
-        
-    my ($dat) = pack("n", $format);
-
-    my ($firstGlyph, $lastGlyph) = (0xffff, 0);
-    foreach (keys %$lookup) {
-        $firstGlyph = $_ if $_ < $firstGlyph;
-        $lastGlyph = $_ if $_ > $lastGlyph;
-    }
-    my $glyphCount = $lastGlyph - $firstGlyph + 1;
-
-    if ($format == 0) {
-        $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph));
-    }
-
-    elsif ($format == 2) {
-        my $prev = $default;
-        my $segStart = $firstGlyph;
-        my $dat1;
-        foreach ($firstGlyph .. $lastGlyph + 1) {
-            my $val = $lookup->{$_};
-            $val = $default unless defined $val;
-            if ($val != $prev) {
-                $dat1 .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default;
-                $prev = $val;
-                $segStart = $_;
-            }
-        }
-        $dat1 .= pack("nn" . $packChar, 0xffff, 0xffff, 0);
-        my $unitSize = 4 + $valueSize;
-        $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize));
-        $dat .= $dat1;
-    }
-        
-    elsif ($format == 4) {
-        my $segArray = new Font::TTF::Segarr($valueSize);
-        $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph));
-        my ($start, $end, $offset);
-        $offset = 12 + @$segArray * 6 + 6;    # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment
-        my $dat1;
-        foreach (@$segArray) {
-            $start = $_->{'START'};
-            $end = $start + $_->{'LEN'} - 1;
-            $dat1 .= pack("nnn", $end, $start, $offset);
-            $offset += $_->{'LEN'} * 2;
-        }
-        $dat1 .= pack("nnn", 0xffff, 0xffff, 0);
-        $dat .= pack("nnnnn", 6, TTF_bininfo(length($dat1) / 6, 6));
-        $dat .= $dat1;
-        foreach (@$segArray) {
-            $dat1 = $_->{'VAL'};
-            $dat .= pack($packChar . "*", @$dat1);
-        }
-    }
-        
-    elsif ($format == 6) {
-        die "unsupported" if $valueSize != 2;
-        my $dat1 = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup);
-        my $unitSize = 2 + $valueSize;
-        $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize));
-        $dat .= $dat1;
-    }
-        
-    elsif ($format == 8) {
-        $dat .= pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1);
-        $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph));
-    }
-    
-    else {
-        die "unknown lookup format";
-    }
-    
-    my $padBytes = (4 - (length($dat) & 3)) & 3;
-    $dat .= pack("C*", (0) x $padBytes);
-    
-    return $dat;
-}
-
-sub AAT_write_lookup
-{
-    my ($fh, $format, $lookup, $valueSize, $default) = @_;
-
-    my $lookupStart = $fh->tell();
-    my $packChar;
-    if ($valueSize == 1) {
-        $packChar = "C";
-    }
-    elsif ($valueSize == 2) {
-        $packChar = "n";
-    }
-    elsif ($valueSize == 4) {
-        $packChar = "N";
-    }
-    else {
-        die "unsupported value size";
-    }
-        
-    $fh->print(pack("n", $format));
-
-    my ($firstGlyph, $lastGlyph) = (0xffff, 0);
-    foreach (keys %$lookup) {
-        $firstGlyph = $_ if $_ < $firstGlyph;
-        $lastGlyph = $_ if $_ > $lastGlyph;
-    }
-    my $glyphCount = $lastGlyph - $firstGlyph + 1;
-
-    if ($format == 0) {
-        $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph)));
-    }
-
-    elsif ($format == 2) {
-        my $prev = $default;
-        my $segStart = $firstGlyph;
-        my $dat;
-        foreach ($firstGlyph .. $lastGlyph + 1) {
-            my $val = $lookup->{$_};
-            $val = $default unless defined $val;
-            if ($val != $prev) {
-                $dat .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default;
-                $prev = $val;
-                $segStart = $_;
-            }
-        }
-        $dat .= pack("nn" . $packChar, 0xffff, 0xffff, 0);
-        my $unitSize = 4 + $valueSize;
-        $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize)));
-        $fh->print($dat);
-    }
-        
-    elsif ($format == 4) {
-        my $segArray = new Font::TTF::Segarr($valueSize);
-        $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph));
-        my ($start, $end, $offset);
-        $offset = 12 + @$segArray * 6 + 6;    # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment
-        my $dat;
-        foreach (@$segArray) {
-            $start = $_->{'START'};
-            $end = $start + $_->{'LEN'} - 1;
-            $dat .= pack("nnn", $end, $start, $offset);
-            $offset += $_->{'LEN'} * 2;
-        }
-        $dat .= pack("nnn", 0xffff, 0xffff, 0);
-        $fh->print(pack("nnnnn", 6, TTF_bininfo(length($dat) / 6, 6)));
-        $fh->print($dat);
-        foreach (@$segArray) {
-            $dat = $_->{'VAL'};
-            $fh->print(pack($packChar . "*", @$dat));
-        }
-    }
-        
-    elsif ($format == 6) {
-        die "unsupported" if $valueSize != 2;
-        my $dat = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup);
-        my $unitSize = 2 + $valueSize;
-        $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize)));
-        $fh->print($dat);
-    }
-        
-    elsif ($format == 8) {
-        $fh->print(pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1));
-        $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph)));
-    }
-    
-    else {
-        die "unknown lookup format";
-    }
-    
-    my $length = $fh->tell() - $lookupStart;
-    my $padBytes = (4 - ($length & 3)) & 3;
-    $fh->print(pack("C*", (0) x $padBytes));
-    $length += $padBytes;
-    
-    $length;
-}
-
-1;
-
+package Font::TTF::AATutils;
+
+use strict;
+use vars qw(@ISA @EXPORT);
+require Exporter;
+
+use Font::TTF::Utils;
+
+ at ISA = qw(Exporter);
+ at EXPORT = qw(
+    AAT_read_lookup
+    AAT_pack_lookup
+    AAT_write_lookup
+    AAT_pack_classes
+    AAT_write_classes
+    AAT_pack_states
+    AAT_write_states
+    AAT_read_state_table
+    AAT_read_subtable
+    xmldump
+);
+
+sub xmldump
+{
+    my ($var, $links, $depth, $processedVars, $type) = @_;
+
+    $processedVars = {} unless (defined $processedVars);
+    print("<?xml version='1.0' encoding='UTF-8'?>\n") if $depth == 0;    # not necessarily true encoding for all text!
+
+    my $indent = "\t" x $depth;
+
+    my ($objType, $addr) = ($var =~ m/^.+=(.+)\((.+)\)$/);
+    unless (defined $type) {
+        if (defined $addr) {
+            if (defined $processedVars->{$addr}) {
+                if ($links) {
+                    printf("%s%s\n", $indent, "<a href=\"#$addr\">$objType</a>");
+                }
+                else {
+                    printf("%s%s\n", $indent, "<a>$objType</a>");
+                }
+                return;
+            }
+            $processedVars->{$addr} = 1;
+        }
+    }
+    
+    $type = ref $var unless defined $type;
+    
+    if ($type eq 'REF') {
+        printf("%s<ref val=\"%s\"/>\n", $indent, $$var);
+    }
+    elsif ($type eq 'SCALAR') {
+        printf("%s<scalar>%s</scalar>\n", $indent, $var);
+    }
+    elsif ($type eq 'ARRAY') {
+        # printf("%s<array>\n", $indent);
+        foreach (0 .. $#$var) {
+            if (ref($var->[$_])) {
+                printf("%s<arrayItem index=\"%d\">\n", $indent, $_);
+                xmldump($var->[$_], $links, $depth + 1, $processedVars);
+                printf("%s</arrayItem>\n", $indent);
+            }
+            else {
+                printf("%s<arrayItem index=\"%d\">%s</arrayItem>\n", $indent, $_, $var->[$_]);
+            }
+        }
+        # printf("%s</array>\n", $indent);
+    }
+    elsif ($type eq 'HASH') {
+        # printf("%s<hash>\n", $indent);
+        foreach (sort keys %$var) {
+            if (ref($var->{$_})) {
+                printf("%s<hashElem key=\"%s\">\n", $indent, $_);
+                xmldump($var->{$_}, $links, $depth + 1, $processedVars);
+                printf("%s</hashElem>\n", $indent);
+            }
+            else {
+                printf("%s<hashElem key=\"%s\">%s</hashElem>\n", $indent, $_, $var->{$_});
+            }
+        }
+        # printf("%s</hash>\n", $indent);
+    }
+    elsif ($type eq 'CODE') {
+        printf("%s<CODE/>\n", $indent, $var);
+    }
+    elsif ($type eq 'GLOB') {
+        printf("%s<GLOB/>\n", $indent, $var);
+    }
+    elsif ($type eq '') {
+        printf("%s<val>%s</val>\n", $indent, $var);
+    }
+    else {
+        if ($links) {
+            printf("%s<obj class=\"%s\" id=\"#%s\">\n", $indent, $type, $addr);
+        }
+        else {
+            printf("%s<obj class=\"%s\">\n", $indent, $type);
+        }
+        xmldump($var, $links, $depth + 1, $processedVars, $objType);
+        printf("%s</obj>\n", $indent);
+    }
+}
+
+=head2 ($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits)
+
+=cut
+
+sub AAT_read_subtable
+{
+    my ($fh, $baseOffset, $subtableStart, $limits) = @_;
+    
+    my $limit = 0xffffffff;
+    foreach (@$limits) {
+        $limit = $_ if ($_ > $subtableStart and $_ < $limit);
+    }
+    die if $limit == 0xffffffff;
+    
+    my $dat;
+    $fh->seek($baseOffset + $subtableStart, IO::File::SEEK_SET);
+    $fh->read($dat, $limit - $subtableStart);
+    
+    $dat;
+}
+
+=head2 $length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry)
+
+$packEntry is a subroutine for packing an entry into binary form, called as
+
+$dat = $packEntry($entry, $entryTable, $numEntries)
+
+where the entry is a comma-separated list of nextStateOffset, flags, actions
+
+=cut
+
+sub AAT_pack_state_table
+{
+    my ($classes, $states, $numExtraTables, $packEntry) = @_;
+    
+    my ($dat) = pack("n*", (0) x (4 + $numExtraTables));    # placeholders for stateSize, classTable, stateArray, entryTable
+    
+    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
+    my (@classTable, $i);
+    foreach $i (0 .. $#$classes) {
+        my $class = $classes->[$i];
+        foreach (@$class) {
+            $firstGlyph = $_ if $_ < $firstGlyph;
+            $lastGlyph = $_ if $_ > $lastGlyph;
+            $classTable[$_] = $i;
+        }
+    }
+    
+    my $classTable = length($dat);
+    $dat .= pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
+                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph));
+    $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
+    
+    my $stateArray = length($dat);
+    my (@entries, %entries);
+    my $state = $states->[0];
+    my $stateSize = @$state;
+    die "stateSize below minimum allowed (4)" if $stateSize < 4;
+    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
+    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
+
+    foreach (@$states) {
+        die "inconsistent state size" if @$_ != $stateSize;
+        foreach (@$_) {
+            my $actions = $_->{'actions'};
+            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions);
+            if (not defined $entries{$entry}) {
+                push @entries, $entry;
+                $entries{$entry} = $#entries;
+                die "too many different state array entries" if $#entries == 256;
+            }
+            $dat .= pack("C", $entries{$entry});
+        }
+    }
+    $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
+    
+    my $entryTable = length($dat);
+    $dat .= map { &$packEntry($_, $entryTable, $#entries + 1) } @entries;
+    
+    my ($dat1) = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable);
+    substr($dat, 0, length($dat1)) = $dat1;
+    
+    return $dat;
+}
+
+sub AAT_write_state_table
+{
+    my ($fh, $classes, $states, $numExtraTables, $packEntry) = @_;
+    
+    my $stateTableStart = $fh->tell();
+
+    $fh->print(pack("n*", (0) x (4 + $numExtraTables)));    # placeholders for stateSize, classTable, stateArray, entryTable
+    
+    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
+    my (@classTable, $i);
+    foreach $i (0 .. $#$classes) {
+        my $class = $classes->[$i];
+        foreach (@$class) {
+            $firstGlyph = $_ if $_ < $firstGlyph;
+            $lastGlyph = $_ if $_ > $lastGlyph;
+            $classTable[$_] = $i;
+        }
+    }
+    
+    my $classTable = $fh->tell() - $stateTableStart;
+    $fh->print(pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
+                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)));
+    $fh->print(pack("C", 0)) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
+    
+    my $stateArray = $fh->tell() - $stateTableStart;
+    my (@entries, %entries);
+    my $state = $states->[0];
+    my $stateSize = @$state;
+    die "stateSize below minimum allowed (4)" if $stateSize < 4;
+    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
+    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
+
+    foreach (@$states) {
+        die "inconsistent state size" if @$_ != $stateSize;
+        foreach (@$_) {
+            my $actions = $_->{'actions'};
+            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions);
+            if (not defined $entries{$entry}) {
+                push @entries, $entry;
+                $entries{$entry} = $#entries;
+                die "too many different state array entries" if $#entries == 256;
+            }
+            $fh->print(pack("C", $entries{$entry}));
+        }
+    }
+    $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
+    
+    my $entryTable = $fh->tell() - $stateTableStart;
+    $fh->print(map { &$packEntry($_, $entryTable, $#entries + 1) } @entries);
+    
+    my $length = $fh->tell() - $stateTableStart;
+    $fh->seek($stateTableStart, IO::File::SEEK_SET);
+    $fh->print(pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable));
+    
+    $fh->seek($stateTableStart + $length, IO::File::SEEK_SET);
+    $length;
+}
+
+sub AAT_pack_classes
+{
+    my ($classes) = @_;
+    
+    my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0);
+    my (@classTable, $i);
+    foreach $i (0 .. $#$classes) {
+        my $class = $classes->[$i];
+        foreach (@$class) {
+            $firstGlyph = $_ if $_ < $firstGlyph;
+            $lastGlyph = $_ if $_ > $lastGlyph;
+            $classTable[$_] = $i;
+        }
+    }
+    
+    my ($dat) = pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1,
+                    map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph));
+    $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0;    # pad if odd number of glyphs
+    
+    return $dat;
+}
+
+sub AAT_write_classes
+{
+    my ($fh, $classes) = @_;
+    
+    $fh->print(AAT_pack_classes($fh, $classes));
+}
+
+sub AAT_pack_states
+{
+    my ($classes, $stateArray, $states, $buildEntryProc) = @_;
+    
+    my ($entries, %entryHash);
+    my $state = $states->[0];
+    my $stateSize = @$state;
+    
+    die "stateSize below minimum allowed (4)" if $stateSize < 4;
+    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
+    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
+    
+    my ($dat);
+    foreach (@$states) {
+        die "inconsistent state size" if @$_ != $stateSize;
+        foreach (@$_) {
+            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_));
+            if (not defined $entryHash{$entry}) {
+                push @$entries, $entry;
+                $entryHash{$entry} = $#$entries;
+                die "too many different state array entries" if $#$entries == 256;
+            }
+            $dat .= pack("C", $entryHash{$entry});
+        }
+    }
+    $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
+
+    ($dat, $stateSize, $entries);
+}
+
+sub AAT_write_states
+{
+    my ($fh, $classes, $stateArray, $states, $buildEntryProc) = @_;
+    
+    my ($entries, %entryHash);
+    my $state = $states->[0];
+    my $stateSize = @$state;
+    
+    die "stateSize below minimum allowed (4)" if $stateSize < 4;
+    die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1;
+    warn "state array has unreachable columns" if $stateSize > $#$classes + 1;
+
+    foreach (@$states) {
+        die "inconsistent state size" if @$_ != $stateSize;
+        foreach (@$_) {
+            my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_));
+            if (not defined $entryHash{$entry}) {
+                push @$entries, $entry;
+                $entryHash{$entry} = $#$entries;
+                die "too many different state array entries" if $#$entries == 256;
+            }
+            $fh->print(pack("C", $entryHash{$entry}));
+        }
+    }
+    $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0;    # pad if state array size is odd
+
+    ($stateSize, $entries);
+}
+
+=head2 ($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords)
+
+=cut
+
+sub AAT_read_state_table
+{
+    my ($fh, $numActionWords) = @_;
+    
+    my $stateTableStart = $fh->tell();
+    my $dat;
+    $fh->read($dat, 8);
+    my ($stateSize, $classTable, $stateArray, $entryTable) = unpack("nnnn", $dat);
+    
+    my $classes;    # array of lists of glyphs
+
+    $fh->seek($stateTableStart + $classTable, IO::File::SEEK_SET);
+    $fh->read($dat, 4);
+    my ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
+    $fh->read($dat, $nGlyphs);
+    foreach (unpack("C*", $dat)) {
+        if ($_ != 1) {
+            my $class = $classes->[$_];
+            push(@$class, $firstGlyph);
+            $classes->[$_] = $class unless defined $classes->[$_];
+        }
+        $firstGlyph++;
+    }
+
+    $fh->seek($stateTableStart + $stateArray, IO::File::SEEK_SET);
+    my $states;    # array of arrays of hashes{nextState, flags, actions}
+
+    my $entrySize = 4 + ($numActionWords * 2);
+    my $lastState = 1;
+    my $entries;
+    while ($#$states < $lastState) {
+        $fh->read($dat, $stateSize);
+        my @stateEntries = unpack("C*", $dat);
+        my $state;
+        foreach (@stateEntries) {
+            if (not defined $entries->[$_]) {
+                my $loc = $fh->tell();
+                $fh->seek($stateTableStart + $entryTable + ($_ * $entrySize), IO::File::SEEK_SET);
+                $fh->read($dat, $entrySize);
+                my ($nextState, $flags, $actions);
+                ($nextState, $flags, @$actions) = unpack("n*", $dat);
+                $nextState -= $stateArray;
+                $nextState /= $stateSize;
+                $entries->[$_] = { 'nextState' => $nextState, 'flags' => $flags };
+                $entries->[$_]->{'actions'} = $actions if $numActionWords > 0;
+                $lastState = $nextState if ($nextState > $lastState);
+                $fh->seek($loc, IO::File::SEEK_SET);
+            }
+            push(@$state, $entries->[$_]);
+        }
+        push(@$states, $state);
+    }
+
+    ($classes, $states, $entries);
+}
+
+=head2 ($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default)
+
+=cut
+
+sub AAT_read_lookup
+{
+    my ($fh, $valueSize, $length, $default) = @_;
+
+    my $lookupStart = $fh->tell();
+    my ($dat, $unpackChar);
+    if ($valueSize == 1) {
+        $unpackChar = "C";
+    }
+    elsif ($valueSize == 2) {
+        $unpackChar = "n";
+    }
+    elsif ($valueSize == 4) {
+        $unpackChar = "N";
+    }
+    else {
+        die "unsupported value size";
+    }
+        
+    $fh->read($dat, 2);
+    my $format = unpack("n", $dat);
+    my $lookup;
+    
+    if ($format == 0) {
+        $fh->read($dat, $length - 2);
+        my $i = -1;
+        $lookup = { map { $i++; ($_ != $default) ? ($i, $_) : () } unpack($unpackChar . "*", $dat) };
+    }
+    
+    elsif ($format == 2) {
+        $fh->read($dat, 10);
+        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
+        die if $unitSize != 4 + $valueSize;
+        foreach (1 .. $nUnits) {
+            $fh->read($dat, $unitSize);
+            my ($lastGlyph, $firstGlyph, $value) = unpack("nn" . $unpackChar, $dat);
+            if ($firstGlyph != 0xffff and $value != $default) {
+                foreach ($firstGlyph .. $lastGlyph) {
+                    $lookup->{$_} = $value;
+                }
+            }
+        }
+    }
+    
+    elsif ($format == 4) {
+        $fh->read($dat, 10);
+        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
+        die if $unitSize != 6;
+        foreach (1 .. $nUnits) {
+            $fh->read($dat, $unitSize);
+            my ($lastGlyph, $firstGlyph, $offset) = unpack("nnn", $dat);
+            if ($firstGlyph != 0xffff) {
+                my $loc = $fh->tell();
+                $fh->seek($lookupStart + $offset, IO::File::SEEK_SET);
+                $fh->read($dat, ($lastGlyph - $firstGlyph + 1) * $valueSize);
+                my @values = unpack($unpackChar . "*", $dat);
+                foreach (0 .. $lastGlyph - $firstGlyph) {
+                    $lookup->{$firstGlyph + $_} = $values[$_] if $values[$_] != $default;
+                }
+                $fh->seek($loc, IO::File::SEEK_SET);
+            }
+        }
+    }
+    
+    elsif ($format == 6) {
+        $fh->read($dat, 10);
+        my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat);
+        die if $unitSize != 2 + $valueSize;
+        foreach (1 .. $nUnits) {
+            $fh->read($dat, $unitSize);
+            my ($glyph, $value) = unpack("n" . $unpackChar, $dat);
+            $lookup->{$glyph} = $value if $glyph != 0xffff and $value != $default;
+        }
+    }
+    
+    elsif ($format == 8) {
+        $fh->read($dat, 4);
+        my ($firstGlyph, $glyphCount) = unpack("nn", $dat);
+        $fh->read($dat, $glyphCount * $valueSize);
+        $firstGlyph--;
+        $lookup = { map { $firstGlyph++; $_ != $default ? ($firstGlyph, $_) : () } unpack($unpackChar . "*", $dat) };
+    }
+    
+    else {
+        die "unknown lookup format";
+    }
+
+    $fh->seek($lookupStart + $length, IO::File::SEEK_SET);
+
+    ($format, $lookup);
+}
+
+=head2 AAT_write_lookup($fh, $format, $lookup, $valueSize, $default)
+
+=cut
+
+sub AAT_pack_lookup
+{
+    my ($format, $lookup, $valueSize, $default) = @_;
+
+    my $packChar;
+    if ($valueSize == 1) {
+        $packChar = "C";
+    }
+    elsif ($valueSize == 2) {
+        $packChar = "n";
+    }
+    elsif ($valueSize == 4) {
+        $packChar = "N";
+    }
+    else {
+        die "unsupported value size";
+    }
+        
+    my ($dat) = pack("n", $format);
+
+    my ($firstGlyph, $lastGlyph) = (0xffff, 0);
+    foreach (keys %$lookup) {
+        $firstGlyph = $_ if $_ < $firstGlyph;
+        $lastGlyph = $_ if $_ > $lastGlyph;
+    }
+    my $glyphCount = $lastGlyph - $firstGlyph + 1;
+
+    if ($format == 0) {
+        $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph));
+    }
+
+    elsif ($format == 2) {
+        my $prev = $default;
+        my $segStart = $firstGlyph;
+        my $dat1;
+        foreach ($firstGlyph .. $lastGlyph + 1) {
+            my $val = $lookup->{$_};
+            $val = $default unless defined $val;
+            if ($val != $prev) {
+                $dat1 .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default;
+                $prev = $val;
+                $segStart = $_;
+            }
+        }
+        $dat1 .= pack("nn" . $packChar, 0xffff, 0xffff, 0);
+        my $unitSize = 4 + $valueSize;
+        $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize));
+        $dat .= $dat1;
+    }
+        
+    elsif ($format == 4) {
+        my $segArray = new Font::TTF::Segarr($valueSize);
+        $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph));
+        my ($start, $end, $offset);
+        $offset = 12 + @$segArray * 6 + 6;    # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment
+        my $dat1;
+        foreach (@$segArray) {
+            $start = $_->{'START'};
+            $end = $start + $_->{'LEN'} - 1;
+            $dat1 .= pack("nnn", $end, $start, $offset);
+            $offset += $_->{'LEN'} * 2;
+        }
+        $dat1 .= pack("nnn", 0xffff, 0xffff, 0);
+        $dat .= pack("nnnnn", 6, TTF_bininfo(length($dat1) / 6, 6));
+        $dat .= $dat1;
+        foreach (@$segArray) {
+            $dat1 = $_->{'VAL'};
+            $dat .= pack($packChar . "*", @$dat1);
+        }
+    }
+        
+    elsif ($format == 6) {
+        die "unsupported" if $valueSize != 2;
+        my $dat1 = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup);
+        my $unitSize = 2 + $valueSize;
+        $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize));
+        $dat .= $dat1;
+    }
+        
+    elsif ($format == 8) {
+        $dat .= pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1);
+        $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph));
+    }
+    
+    else {
+        die "unknown lookup format";
+    }
+    
+    my $padBytes = (4 - (length($dat) & 3)) & 3;
+    $dat .= pack("C*", (0) x $padBytes);
+    
+    return $dat;
+}
+
+sub AAT_write_lookup
+{
+    my ($fh, $format, $lookup, $valueSize, $default) = @_;
+
+    my $lookupStart = $fh->tell();
+    my $packChar;
+    if ($valueSize == 1) {
+        $packChar = "C";
+    }
+    elsif ($valueSize == 2) {
+        $packChar = "n";
+    }
+    elsif ($valueSize == 4) {
+        $packChar = "N";
+    }
+    else {
+        die "unsupported value size";
+    }
+        
+    $fh->print(pack("n", $format));
+
+    my ($firstGlyph, $lastGlyph) = (0xffff, 0);
+    foreach (keys %$lookup) {
+        $firstGlyph = $_ if $_ < $firstGlyph;
+        $lastGlyph = $_ if $_ > $lastGlyph;
+    }
+    my $glyphCount = $lastGlyph - $firstGlyph + 1;
+
+    if ($format == 0) {
+        $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph)));
+    }
+
+    elsif ($format == 2) {
+        my $prev = $default;
+        my $segStart = $firstGlyph;
+        my $dat;
+        foreach ($firstGlyph .. $lastGlyph + 1) {
+            my $val = $lookup->{$_};
+            $val = $default unless defined $val;
+            if ($val != $prev) {
+                $dat .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default;
+                $prev = $val;
+                $segStart = $_;
+            }
+        }
+        $dat .= pack("nn" . $packChar, 0xffff, 0xffff, 0);
+        my $unitSize = 4 + $valueSize;
+        $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize)));
+        $fh->print($dat);
+    }
+        
+    elsif ($format == 4) {
+        my $segArray = new Font::TTF::Segarr($valueSize);
+        $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph));
+        my ($start, $end, $offset);
+        $offset = 12 + @$segArray * 6 + 6;    # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment
+        my $dat;
+        foreach (@$segArray) {
+            $start = $_->{'START'};
+            $end = $start + $_->{'LEN'} - 1;
+            $dat .= pack("nnn", $end, $start, $offset);
+            $offset += $_->{'LEN'} * 2;
+        }
+        $dat .= pack("nnn", 0xffff, 0xffff, 0);
+        $fh->print(pack("nnnnn", 6, TTF_bininfo(length($dat) / 6, 6)));
+        $fh->print($dat);
+        foreach (@$segArray) {
+            $dat = $_->{'VAL'};
+            $fh->print(pack($packChar . "*", @$dat));
+        }
+    }
+        
+    elsif ($format == 6) {
+        die "unsupported" if $valueSize != 2;
+        my $dat = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup);
+        my $unitSize = 2 + $valueSize;
+        $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize)));
+        $fh->print($dat);
+    }
+        
+    elsif ($format == 8) {
+        $fh->print(pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1));
+        $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph)));
+    }
+    
+    else {
+        die "unknown lookup format";
+    }
+    
+    my $length = $fh->tell() - $lookupStart;
+    my $padBytes = (4 - ($length & 3)) & 3;
+    $fh->print(pack("C*", (0) x $padBytes));
+    $length += $padBytes;
+    
+    $length;
+}
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Anchor.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Anchor.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Anchor.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,208 +1,208 @@
-package Font::TTF::Anchor;
-
-=head1 NAME
-
-Font::TTF::Anchor - Anchor points for GPOS tables
-
-=head1 DESCRIPTION
-
-The Anchor defines an anchor point on a glyph providing various information
-depending on how much is available, including such information as the co-ordinates,
-a curve point and even device specific modifiers.
-
-=head1 INSTANCE VARIABLES
-
-=over 4
-
-=item x
-
-XCoordinate of the anchor point
-
-=item y
-
-YCoordinate of the anchor point
-
-=item p
-
-Curve point on the glyph to use as the anchor point
-
-=item xdev
-
-Device table (delta) for the xcoordinate
-
-=item ydev
-
-Device table (delta) for the ycoordinate
-
-=item xid
-
-XIdAnchor for multiple master horizontal metric id
-
-=item yid
-
-YIdAnchor for multiple master vertical metric id
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-
-
-=head2 new
-
-Creates a new Anchor
-
-=cut
-
-sub new
-{
-    my ($class) = shift;
-    my ($self) = {@_};
-
-    bless $self, $class;
-}
-
-
-=head2 read($fh)
-
-Reads the anchor from the given file handle at that point. The file handle is left
-at an arbitrary read point, usually the end of something!
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat, $loc, $fmt, $x, $y, $p, $xoff, $yoff);
-
-    $fh->read($dat, 6);
-    ($fmt, $x, $y) = unpack('n*', $dat);
-    if ($fmt == 4)
-    { ($self->{'xid'}, $self->{'yid'}) = ($x, $y); }
-    else
-    { ($self->{'x'}, $self->{'y'}) = ($x, $y); }
-
-    if ($fmt == 2)
-    {
-        $fh->read($dat, 2);
-        $self->{'p'} = unpack('n', $dat);
-    } elsif ($fmt == 3)
-    {
-        $fh->read($dat, 4);
-        ($xoff, $yoff) = unpack('n2', $dat);
-        $loc = $fh->tell() - 10;
-        if ($xoff)
-        {
-            $fh->seek($loc + $xoff, 0);
-            $self->{'xdev'} = Font::TTF::Delta->new->read($fh);
-        }
-        if ($yoff)
-        {
-            $fh->seek($loc + $yoff, 0);
-            $self->{'ydev'} = Font::TTF::Delta->new->read($fh);
-        }
-    }
-    $self;
-}
-
-
-=head2 out($fh, $style)
-
-Outputs the Anchor to the given file handle at this point also addressing issues
-of deltas. If $style is set, then no output is set to the file handle. The return
-value is the output string.
-
-=cut
-
-sub out
-{
-    my ($self, $fh, $style) = @_;
-    my ($xoff, $yoff, $fmt, $out);
-
-    if (defined $self->{'xid'} || defined $self->{'yid'})
-    { $out = pack('n*', 4, $self->{'xid'}, $self->{'yid'}); }
-    elsif (defined $self->{'p'})
-    { $out = pack('n*', 2, @{$self}{'x', 'y', 'p'}); }
-    elsif (defined $self->{'xdev'} || defined $self->{'ydev'})
-    {
-        $out = pack('n*', 3, @{$self}{'x', 'y'});
-        if (defined $self->{'xdev'})
-        {
-            $out .= pack('n2', 10, 0);
-            $out .= $self->{'xdev'}->out($fh, 1);
-            $yoff = length($out) - 10;
-        }
-        else
-        { $out .= pack('n2', 0, 0); }
-        if (defined $self->{'ydev'})
-        {
-            $yoff = 10 unless $yoff;
-            substr($out, 8, 2) = pack('n', $yoff);
-            $out .= $self->{'ydev'}->out($fh, 1);
-        }
-    } else
-    { $out = pack('n3', 1, @{$self}{'x', 'y'}); }
-    $fh->print($out) unless $style;
-    $out;
-}
-
-
-=head2 $a->out_xml($context)
-
-Outputs the anchor in XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($end);
-    
-    $fh->print("$depth<anchor x='$self->{'x'}' y='$self->{'y'}'");
-    $fh->print(" p='$self->{'p'}'") if defined ($self->{'p'});
-    $end = (defined $self->{'xdev'} || defined $self->{'ydev'} || defined $self->{'xid'} || defined $self->{'yid'});
-    unless ($end)
-    {
-        $fh->print("/>\n");
-        return $self;
-    }
-
-    if (defined $self->{'xdev'})
-    {
-        $fh->print("$depth$context->{'indent'}<xdev>\n");
-        $self->{'xdev'}->out_xml($context, $depth . ($context->{'indent'} x 2));
-        $fh->print("$depth$context->{'indent'}</xdev>\n");
-    }
-    
-    if (defined $self->{'ydev'})
-    {
-        $fh->print("$depth$context->{'indent'}<ydev>\n");
-        $self->{'ydev'}->out_xml($context, $depth . ($context->{'indent'} x 2));
-        $fh->print("$depth$context->{'indent'}</ydev>\n");
-    }
-    
-    if (defined $self->{'xid'} || defined $self->{'yid'})
-    {
-        $fh->print("$depth$context->{'indent'}<mmaster");
-        $fh->print(" xid='$self->{'xid'}'") if defined ($self->{'xid'});
-        $fh->print(" yid='$self->{'yid'}'") if defined ($self->{'yid'});
-        $fh->print("/>\n");
-    }
-    $fh->print("$depth</anchor>\n");
-    $self;
-}
-        
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+package Font::TTF::Anchor;
+
+=head1 TITLE
+
+Font::TTF::Anchor - Anchor points for GPOS tables
+
+=head1 DESCRIPTION
+
+The Anchor defines an anchor point on a glyph providing various information
+depending on how much is available, including such information as the co-ordinates,
+a curve point and even device specific modifiers.
+
+=head1 INSTANCE VARIABLES
+
+=over 4
+
+=item x
+
+XCoordinate of the anchor point
+
+=item y
+
+YCoordinate of the anchor point
+
+=item p
+
+Curve point on the glyph to use as the anchor point
+
+=item xdev
+
+Device table (delta) for the xcoordinate
+
+=item ydev
+
+Device table (delta) for the ycoordinate
+
+=item xid
+
+XIdAnchor for multiple master horizontal metric id
+
+=item yid
+
+YIdAnchor for multiple master vertical metric id
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+
+
+=head2 new
+
+Creates a new Anchor
+
+=cut
+
+sub new
+{
+    my ($class) = shift;
+    my ($self) = {@_};
+
+    bless $self, $class;
+}
+
+
+=head2 read($fh)
+
+Reads the anchor from the given file handle at that point. The file handle is left
+at an arbitrary read point, usually the end of something!
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat, $loc, $fmt, $x, $y, $p, $xoff, $yoff);
+
+    $fh->read($dat, 6);
+    ($fmt, $x, $y) = unpack('n*', $dat);
+    if ($fmt == 4)
+    { ($self->{'xid'}, $self->{'yid'}) = ($x, $y); }
+    else
+    { ($self->{'x'}, $self->{'y'}) = ($x, $y); }
+
+    if ($fmt == 2)
+    {
+        $fh->read($dat, 2);
+        $self->{'p'} = unpack('n', $dat);
+    } elsif ($fmt == 3)
+    {
+        $fh->read($dat, 4);
+        ($xoff, $yoff) = unpack('n2', $dat);
+        $loc = $fh->tell() - 10;
+        if ($xoff)
+        {
+            $fh->seek($loc + $xoff, 0);
+            $self->{'xdev'} = Font::TTF::Delta->new->read($fh);
+        }
+        if ($yoff)
+        {
+            $fh->seek($loc + $yoff, 0);
+            $self->{'ydev'} = Font::TTF::Delta->new->read($fh);
+        }
+    }
+    $self;
+}
+
+
+=head2 out($fh, $style)
+
+Outputs the Anchor to the given file handle at this point also addressing issues
+of deltas. If $style is set, then no output is set to the file handle. The return
+value is the output string.
+
+=cut
+
+sub out
+{
+    my ($self, $fh, $style) = @_;
+    my ($xoff, $yoff, $fmt, $out);
+
+    if (defined $self->{'xid'} || defined $self->{'yid'})
+    { $out = pack('n*', 4, $self->{'xid'}, $self->{'yid'}); }
+    elsif (defined $self->{'p'})
+    { $out = pack('n*', 2, @{$self}{'x', 'y', 'p'}); }
+    elsif (defined $self->{'xdev'} || defined $self->{'ydev'})
+    {
+        $out = pack('n*', 3, @{$self}{'x', 'y'});
+        if (defined $self->{'xdev'})
+        {
+            $out .= pack('n2', 10, 0);
+            $out .= $self->{'xdev'}->out($fh, 1);
+            $yoff = length($out) - 10;
+        }
+        else
+        { $out .= pack('n2', 0, 0); }
+        if (defined $self->{'ydev'})
+        {
+            $yoff = 10 unless $yoff;
+            substr($out, 8, 2) = pack('n', $yoff);
+            $out .= $self->{'ydev'}->out($fh, 1);
+        }
+    } else
+    { $out = pack('n3', 1, @{$self}{'x', 'y'}); }
+    $fh->print($out) unless $style;
+    $out;
+}
+
+
+=head2 $a->out_xml($context)
+
+Outputs the anchor in XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($end);
+    
+    $fh->print("$depth<anchor x='$self->{'x'}' y='$self->{'y'}'");
+    $fh->print(" p='$self->{'p'}'") if defined ($self->{'p'});
+    $end = (defined $self->{'xdev'} || defined $self->{'ydev'} || defined $self->{'xid'} || defined $self->{'yid'});
+    unless ($end)
+    {
+        $fh->print("/>\n");
+        return $self;
+    }
+
+    if (defined $self->{'xdev'})
+    {
+        $fh->print("$depth$context->{'indent'}<xdev>\n");
+        $self->{'xdev'}->out_xml($context, $depth . ($context->{'indent'} x 2));
+        $fh->print("$depth$context->{'indent'}</xdev>\n");
+    }
+    
+    if (defined $self->{'ydev'})
+    {
+        $fh->print("$depth$context->{'indent'}<ydev>\n");
+        $self->{'ydev'}->out_xml($context, $depth . ($context->{'indent'} x 2));
+        $fh->print("$depth$context->{'indent'}</ydev>\n");
+    }
+    
+    if (defined $self->{'xid'} || defined $self->{'yid'})
+    {
+        $fh->print("$depth$context->{'indent'}<mmaster");
+        $fh->print(" xid='$self->{'xid'}'") if defined ($self->{'xid'});
+        $fh->print(" yid='$self->{'yid'}'") if defined ($self->{'yid'});
+        $fh->print("/>\n");
+    }
+    $fh->print("$depth</anchor>\n");
+    $self;
+}
+        
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Bsln.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Bsln.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Bsln.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,163 +1,163 @@
-package Font::TTF::Bsln;
-
-=head1 NAME
-
-Font::TTF::AAT::Bsln - Baseline table in a font
-
-=head1 DESCRIPTION
-
-=head1 INSTANCE VARIABLES
-
-=item version
-
-=item xformat
-
-=item defaultBaseline
-
-=item deltas
-
-=item stdGlyph
-
-=item ctlPoints
-
-=item lookupFormat
-
-=item lookup
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-
-use Font::TTF::AATutils;
-use Font::TTF::Utils;
-require Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $fh);
-    
-    $self->SUPER::read or return $self;
-
-    $fh = $self->{' INFILE'};
-    $fh->read($dat, 8);
-    my ($version, $format, $defaultBaseline) = TTF_Unpack("fSS", $dat);
-
-    if ($format == 0 or $format == 1) {
-        $fh->read($dat, 64);
-        $self->{'deltas'} = [TTF_Unpack("s*", $dat)];
-    }
-    elsif ($format == 2 or $format == 3) {
-        $fh->read($dat, 2);
-        $self->{'stdGlyph'} = unpack("n", $dat);
-        $fh->read($dat, 64);
-        $self->{'ctlPoints'} = unpack("n*", $dat);
-    }
-    else {
-        die "unknown table format";
-    }
-    
-    if ($format == 1 or $format == 3) {
-        my $len = $self->{' LENGTH'} - ($fh->tell() - $self->{' OFFSET'});
-        my ($lookupFormat, $lookup) = AAT_read_lookup($fh, 2, $len, $defaultBaseline);
-        $self->{'lookupFormat'} = $lookupFormat;
-        $self->{'lookup'} = $lookup;
-    }
-
-    $self->{'version'} = $version;
-    $self->{'format'} = $format;
-    $self->{'defaultBaseline'} = $defaultBaseline;
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    my $format = $self->{'format'};
-    my $defaultBaseline = $self->{'defaultBaseline'};
-    $fh->print(TTF_Pack("fSS", $self->{'version'}, $format, $defaultBaseline));
-
-    AAT_write_lookup($fh, $self->{'lookupFormat'}, $self->{'lookup'}, 2, $defaultBaseline) if ($format == 1 or $format == 3);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-
-    $self->read;
-        
-    $fh = 'STDOUT' unless defined $fh;
-    
-    my $format = $self->{'format'};
-    $fh->printf("version %f\nformat %d\ndefaultBaseline %d\n", $self->{'version'}, $format, $self->{'defaultBaseline'});
-    if ($format == 0 or $format == 1) {
-        $fh->printf("\tdeltas:\n");
-        my $deltas = $self->{'deltas'};
-        foreach (0 .. 31) {
-            $fh->printf("\t\t%d: %d%s\n", $_, $deltas->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
-        }
-    }
-    if ($format == 2 or $format == 3) {
-        $fh->printf("\tstdGlyph = %d\n", $self->{'stdGlyph'});
-        my $ctlPoints = $self->{'ctlPoints'};
-        foreach (0 .. 31) {
-            $fh->printf("\t\t%d: %d%s\n", $_, $ctlPoints->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
-        }
-    }
-    if ($format == 1 or $format == 3) {
-        $fh->printf("lookupFormat %d\n", $self->{'lookupFormat'});
-        my $lookup = $self->{'lookup'};
-        foreach (sort { $a <=> $b } keys %$lookup) {
-            $fh->printf("\tglyph %d: %d%s\n", $_, $lookup->{$_}, defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
-        }
-    }
-}
-
-sub baselineName_
-{
-    my ($b) = @_;
-    my @baselines = ( 'Roman', 'Ideographic centered', 'Ideographic low', 'Hanging', 'Math' );
-    $baselines[$b];
-}
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Bsln;
+
+=head1 NAME
+
+Font::TTF::AAT::Bsln - Baseline table in a font
+
+=head1 DESCRIPTION
+
+=head1 INSTANCE VARIABLES
+
+=item version
+
+=item xformat
+
+=item defaultBaseline
+
+=item deltas
+
+=item stdGlyph
+
+=item ctlPoints
+
+=item lookupFormat
+
+=item lookup
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+
+use Font::TTF::AATutils;
+use Font::TTF::Utils;
+require Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $fh);
+    
+    $self->SUPER::read or return $self;
+
+    $fh = $self->{' INFILE'};
+    $fh->read($dat, 8);
+    my ($version, $format, $defaultBaseline) = TTF_Unpack("fSS", $dat);
+
+    if ($format == 0 or $format == 1) {
+        $fh->read($dat, 64);
+        $self->{'deltas'} = [TTF_Unpack("s*", $dat)];
+    }
+    elsif ($format == 2 or $format == 3) {
+        $fh->read($dat, 2);
+        $self->{'stdGlyph'} = unpack("n", $dat);
+        $fh->read($dat, 64);
+        $self->{'ctlPoints'} = unpack("n*", $dat);
+    }
+    else {
+        die "unknown table format";
+    }
+    
+    if ($format == 1 or $format == 3) {
+        my $len = $self->{' LENGTH'} - ($fh->tell() - $self->{' OFFSET'});
+        my ($lookupFormat, $lookup) = AAT_read_lookup($fh, 2, $len, $defaultBaseline);
+        $self->{'lookupFormat'} = $lookupFormat;
+        $self->{'lookup'} = $lookup;
+    }
+
+    $self->{'version'} = $version;
+    $self->{'format'} = $format;
+    $self->{'defaultBaseline'} = $defaultBaseline;
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    my $format = $self->{'format'};
+    my $defaultBaseline = $self->{'defaultBaseline'};
+    $fh->print(TTF_Pack("fSS", $self->{'version'}, $format, $defaultBaseline));
+
+    AAT_write_lookup($fh, $self->{'lookupFormat'}, $self->{'lookup'}, 2, $defaultBaseline) if ($format == 1 or $format == 3);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+
+    $self->read;
+        
+    $fh = 'STDOUT' unless defined $fh;
+    
+    my $format = $self->{'format'};
+    $fh->printf("version %f\nformat %d\ndefaultBaseline %d\n", $self->{'version'}, $format, $self->{'defaultBaseline'});
+    if ($format == 0 or $format == 1) {
+        $fh->printf("\tdeltas:\n");
+        my $deltas = $self->{'deltas'};
+        foreach (0 .. 31) {
+            $fh->printf("\t\t%d: %d%s\n", $_, $deltas->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
+        }
+    }
+    if ($format == 2 or $format == 3) {
+        $fh->printf("\tstdGlyph = %d\n", $self->{'stdGlyph'});
+        my $ctlPoints = $self->{'ctlPoints'};
+        foreach (0 .. 31) {
+            $fh->printf("\t\t%d: %d%s\n", $_, $ctlPoints->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
+        }
+    }
+    if ($format == 1 or $format == 3) {
+        $fh->printf("lookupFormat %d\n", $self->{'lookupFormat'});
+        my $lookup = $self->{'lookup'};
+        foreach (sort { $a <=> $b } keys %$lookup) {
+            $fh->printf("\tglyph %d: %d%s\n", $_, $lookup->{$_}, defined baselineName_($_) ? "\t# " . baselineName_($_) : "");
+        }
+    }
+}
+
+sub baselineName_
+{
+    my ($b) = @_;
+    my @baselines = ( 'Roman', 'Ideographic centered', 'Ideographic low', 'Hanging', 'Math' );
+    $baselines[$b];
+}
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Changes
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Changes	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Changes	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,108 +1,108 @@
-Note. The version number implies a release point. Thus changes that go into a
-version occur above the version number, not after it.
-
-* 0.05
-** cmap
-	debug reverse()
-        provide scripts as .pl instead of .bat to placate Unix world
-        rename makefile.pl to Makefile.PL to keep Unix happy
-        Add ttfremap script
-
-* 0.06 .. 0.08
-    Fixes to get this stuff working in Unix
-
-* 0.09
-    Never released
-
-* 0.10
-** cmap
-        Make reverse return the lowest codepoint that matches rather than
-        the highest
-** font
-        Use IO::File everywhere to allow passing in of psuedo-file objects
-        rather than file names
-** Utils
-        Debug FDot2.14 conversion
-
-* 0.11
-** cmap
-        Don't store empty entries in the cmap
-
-* 0.12
-Various changes to reduce warnings
-
-** glyph
-        Add update_bbox
-        Do full glyph writes if loca read rather than glyf read
-        Get glyph update working usefully. Clarify glyf->read
-
-* 0.13
-
-** glyph
-        Debug update_bbox for compound glyphs
-        Add empty() to clear to unread state (allows apps to save memory)
-
-** OS/2
-        update update() to account for new cmap structure
-
-** Post
-        Correct mu to pi in Postscript name list. The list now follows the
-        MS convention for good or ill.
-
-** Table
-        Add empty() to clear a table to its unread state
-
-** Scripts
-*** psfix
-        Added. Creates Post table based on cmap information
-
-*** eurofix 
-        Added bullet hacking and generally backwards, forwards, all
-        ways mapping.
-
-*** ttfenc
-        Now supports the difference between MS post name list and TeXs
-
-* 0.14
-
-        Sort out mix up over CVS mess
-
-* 0.15
-
-** Table
-        read_dat no longer marks table as read
-
-** Cvt_
-        Mark table as read when read
-
-** Fpgm
-        Mark table as read when read
-
-** Prep
-        Mark table as read when read
-
-** Font
-        Add support for Mac sfnt version code ('true')
-        Be stricter on out @fontlist, only output tables that exist
-
-* 0.16
-
-** Install
-        add pmake support
-
-** glyph
-        tidy up pod
-
-** kern
-        tidy up pod
-
-** name
-        add utf8 support
-
-* 0.17
-
-** Utils
-        Debug TTF_bininfo >>= seems to have stopped working!
-        
-* 0.18
-
+Note. The version number implies a release point. Thus changes that go into a
+version occur above the version number, not after it.
+
+* 0.05
+** cmap
+	debug reverse()
+        provide scripts as .pl instead of .bat to placate Unix world
+        rename makefile.pl to Makefile.PL to keep Unix happy
+        Add ttfremap script
+
+* 0.06 .. 0.08
+    Fixes to get this stuff working in Unix
+
+* 0.09
+    Never released
+
+* 0.10
+** cmap
+        Make reverse return the lowest codepoint that matches rather than
+        the highest
+** font
+        Use IO::File everywhere to allow passing in of psuedo-file objects
+        rather than file names
+** Utils
+        Debug FDot2.14 conversion
+
+* 0.11
+** cmap
+        Don't store empty entries in the cmap
+
+* 0.12
+Various changes to reduce warnings
+
+** glyph
+        Add update_bbox
+        Do full glyph writes if loca read rather than glyf read
+        Get glyph update working usefully. Clarify glyf->read
+
+* 0.13
+
+** glyph
+        Debug update_bbox for compound glyphs
+        Add empty() to clear to unread state (allows apps to save memory)
+
+** OS/2
+        update update() to account for new cmap structure
+
+** Post
+        Correct mu to pi in Postscript name list. The list now follows the
+        MS convention for good or ill.
+
+** Table
+        Add empty() to clear a table to its unread state
+
+** Scripts
+*** psfix
+        Added. Creates Post table based on cmap information
+
+*** eurofix 
+        Added bullet hacking and generally backwards, forwards, all
+        ways mapping.
+
+*** ttfenc
+        Now supports the difference between MS post name list and TeXs
+
+* 0.14
+
+        Sort out mix up over CVS mess
+
+* 0.15
+
+** Table
+        read_dat no longer marks table as read
+
+** Cvt_
+        Mark table as read when read
+
+** Fpgm
+        Mark table as read when read
+
+** Prep
+        Mark table as read when read
+
+** Font
+        Add support for Mac sfnt version code ('true')
+        Be stricter on out @fontlist, only output tables that exist
+
+* 0.16
+
+** Install
+        add pmake support
+
+** glyph
+        tidy up pod
+
+** kern
+        tidy up pod
+
+** name
+        add utf8 support
+
+* 0.17
+
+** Utils
+        Debug TTF_bininfo >>= seems to have stopped working!
+        
+* 0.18
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cmap.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cmap.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cmap.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,478 +1,478 @@
-package Font::TTF::Cmap;
-
-=head1 NAME
-
-Font::TTF::Cmap - Character map table
-
-=head1 DESCRIPTION
-
-Looks after the character map. For ease of use, the actual cmap is held in
-a hash against codepoint. Thus for a given table:
-
-    $gid = $font->{'cmap'}{'Tables'}[0]{'val'}{$code};
-
-Note that C<$code> should be a true value (0x1234) rather than a string representation.
-
-=head1 INSTANCE VARIABLES
-
-The instance variables listed here are not preceeded by a space due to their
-emulating structural information in the font.
-
-=over 4
-
-=item Num
-
-Number of subtables in this table
-
-=item Tables
-
-An array of subtables ([0..Num-1])
-
-=back
-
-Each subtables also has its own instance variables which are, again, not
-preceeded by a space.
-
-=over 4
-
-=item Platform
-
-The platform number for this subtable
-
-=item Encoding
-
-The encoding number for this subtable
-
-=item Format
-
-Gives the stored format of this subtable
-
-=item Ver
-
-Gives the version (or language) information for this subtable
-
-=item val
-
-A hash keyed by the codepoint value (not a string) storing the glyph id
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
-
-
-=head2 $t->read
-
-Reads the cmap into memory. Format 4 subtables read the whole subtable and
-fill in the segmented array accordingly.
-
-Format 2 subtables are not read at all.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $i, $j, $k, $id, @ids, $s);
-    my ($start, $end, $range, $delta, $form, $len, $num, $ver, $sg);
-    my ($fh) = $self->{' INFILE'};
-
-    $self->SUPER::read or return $self;
-    $fh->read($dat, 4);
-    $self->{'Num'} = unpack("x2n", $dat);
-    $self->{'Tables'} = [];
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = {};
-        $fh->read($dat, 8);
-        ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat));
-        $s->{'LOC'} += $self->{' OFFSET'};
-        push(@{$self->{'Tables'}}, $s);
-    }
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        $fh->seek($s->{'LOC'}, 0);
-        $fh->read($dat, 2);
-        $form = unpack("n", $dat);
-
-        $s->{'Format'} = $form;
-        if ($form == 0)
-        {
-            my ($j) = 0;
-
-            $fh->read($dat, 4);
-            ($len, $s->{'Ver'}) = unpack('n2', $dat);
-            $fh->read($dat, 256);
-            $s->{'val'} = {map {$j++; ($_ ? ($j - 1, $_) : ())} unpack("C*", $dat)};
-        } elsif ($form == 6)
-        {
-            my ($start, $ecount);
-            
-            $fh->read($dat, 8);
-            ($len, $s->{'Ver'}, $start, $ecount) = unpack('n4', $dat);
-            $fh->read($dat, $ecount << 1);
-            $s->{'val'} = {map {$start++; ($_ ? ($start - 1, $_) : ())} unpack("n*", $dat)};
-        } elsif ($form == 2)
-        {
-# no idea what to do here yet
-        } elsif ($form == 4)
-        {
-            $fh->read($dat, 12);
-            ($len, $s->{'Ver'}, $num) = unpack('n3', $dat);
-            $num >>= 1;
-            $fh->read($dat, $len - 14);
-            for ($j = 0; $j < $num; $j++)
-            {
-                $end = unpack("n", substr($dat, $j << 1, 2));
-                $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2));
-                $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2));
-                $delta -= 65536 if $delta > 32767;
-                $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2));
-                for ($k = $start; $k <= $end; $k++)
-                {
-                    if ($range == 0 || $range == 65535)         # support the buggy FOG with its range=65535 for final segment
-                    { $id = $k + $delta; }
-                    else
-                    { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 +
-                                        2 + ($k - $start) * 2 + $range, 2)) + $delta; }
-		            $id -= 65536 if $id >= 65536;
-                    $s->{'val'}{$k} = $id if ($id);
-                }
-            }
-        } elsif ($form == 8 || $form == 12)
-        {
-            $fh->read($dat, 10);
-            ($len, $s->{'Ver'}) = unpack('x2N2', $dat);
-            if ($form == 8)
-            {
-                $fh->read($dat, 8196);
-                $num = unpack("N", substr($dat, 8192, 4)); # don't need the map
-            } else
-            {
-                $fh->read($dat, 4);
-                $num = unpack("N", $dat);
-            }
-            $fh->read($dat, 12 * $num);
-            for ($j = 0; $j < $num; $j++)
-            {
-                ($start, $end, $sg) = unpack("N3", substr($dat, $j * 12, 12));
-                for ($k = $start; $k <= $end; $k++)
-                { $s->{'val'}{$k} = $sg++; }
-            }
-        } elsif ($form == 10)
-        {
-            $fh->read($dat, 18);
-            ($len, $s->{'Ver'}, $start, $num) = unpack('x2N4', $dat);
-            $fh->read($dat, $num << 1);
-            for ($j = 0; $j < $num; $j++)
-            { $s->{'val'}{$start + $j} = unpack("n", substr($dat, $j << 1, 2)); }
-        }
-    }
-    $self;
-}
-
-
-=head2 $t->ms_lookup($uni)
-
-Finds a Unicode table, giving preference to the MS one, and looks up the given
-Unicode codepoint in it to find the glyph id.
-
-=cut
-
-sub ms_lookup
-{
-    my ($self, $uni) = @_;
-
-    $self->find_ms || return undef unless (defined $self->{' mstable'});
-    return $self->{' mstable'}{'val'}{$uni};
-}
-
-
-=head2 $t->find_ms
-
-Finds the a Unicode table, giving preference to the Microsoft one, and sets the C<mstable> instance variable
-to it if found. Returns the table it finds.
-
-=cut
-sub find_ms
-{
-    my ($self) = @_;
-    my ($i, $s, $alt, $found);
-
-    return $self->{' mstable'} if defined $self->{' mstable'};
-    $self->read;
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        if ($s->{'Platform'} == 3)
-        {
-            $self->{' mstable'} = $s;
-            last if ($s->{'Encoding'} == 10);
-            $found = 1 if ($s->{'Encoding'} == 1);
-        } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1))
-        { $alt = $s; }
-    }
-    $self->{' mstable'} = $alt if ($alt && !$found);
-    $self->{' mstable'};
-}
-
-
-=head2 $t->ms_enc
-
-Returns the encoding of the microsoft table (0 => symbol, etc.). Returns undef if there is
-no Microsoft cmap.
-
-=cut
-
-sub ms_enc
-{
-    my ($self) = @_;
-    my ($s);
-    
-    return $self->{' mstable'}{'Encoding'} 
-        if (defined $self->{' mstable'} && $self->{' mstable'}{'Platform'} == 3);
-    
-    foreach $s (@{$self->{'Tables'}})
-    {
-        return $s->{'Encoding'} if ($s->{'Platform'} == 3);
-    }
-    return undef;
-}
-
-
-=head2 $t->out($fh)
-
-Writes out a cmap table to a filehandle. If it has not been read, then
-just copies from input file to output
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($loc, $s, $i, $base_loc, $j, @keys);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-
-    $self->{'Tables'} = [sort {$a->{'Platform'} <=> $b->{'Platform'}
-                                || $a->{'Encoding'} <=> $b->{'Encoding'}
-                                || $a->{'Ver'} <=> $b->{'Ver'}} @{$self->{'Tables'}}];
-    $self->{'Num'} = scalar @{$self->{'Tables'}};
-
-    $base_loc = $fh->tell();
-    $fh->print(pack("n2", 0, $self->{'Num'}));
-
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); }
-
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        @keys = sort {$a <=> $b} keys %{$s->{'val'}};
-        $s->{' outloc'} = $fh->tell();
-        if ($s->{'Format'} < 8)
-        { $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); }       # come back for length
-        else
-        { $fh->print(pack("n2N2", $s->{'Format'}, 0, 0, $s->{'Ver'})); }
-            
-        if ($s->{'Format'} == 0)
-        {
-            $fh->print(pack("C256", @{$s->{'val'}}{0 .. 255}));
-        } elsif ($s->{'Format'} == 6)
-        {
-            $fh->print(pack("n2", $keys[0], $keys[-1] - $keys[0] + 1));
-            $fh->print(pack("n*", @{$s->{'val'}}{$keys[0] .. $keys[-1]}));
-        } elsif ($s->{'Format'} == 2)
-        {
-        } elsif ($s->{'Format'} == 4)
-        {
-            my ($num, $sRange, $eSel, $eShift, @starts, @ends, $doff);
-            my (@deltas, $delta, @range, $flat, $k, $segs, $count, $newseg, $v);
-
-            push(@keys, 0xFFFF) unless ($keys[-1] == 0xFFFF);
-            $newseg = 1; $num = 0;
-            for ($j = 0; $j <= $#keys && $keys[$j] <= 0xFFFF; $j++)
-            {
-                $v = $s->{'val'}{$keys[$j]};
-                if ($newseg)
-                {
-                    $delta = $v;
-                    $doff = $j;
-                    $flat = 1;
-                    push(@starts, $keys[$j]);
-                    $newseg = 0;
-                }
-                $delta = 0 if ($delta + $j - $doff != $v);
-                $flat = 0 if ($v == 0);
-                if ($j == $#keys || $keys[$j] + 1 != $keys[$j+1])
-                {
-                    push (@ends, $keys[$j]);
-                    push (@deltas, $delta ? $delta - $keys[$doff] : 0);
-                    push (@range, $flat);
-                    $num++;
-                    $newseg = 1;
-                }
-            }
-
-            ($num, $sRange, $eSel, $eShift) = Font::TTF::Utils::TTF_bininfo($num, 2);
-            $fh->print(pack("n4", $num * 2, $sRange, $eSel, $eShift));
-            $fh->print(pack("n*", @ends));
-            $fh->print(pack("n", 0));
-            $fh->print(pack("n*", @starts));
-            $fh->print(pack("n*", @deltas));
-
-            $count = 0;
-            for ($j = 0; $j < $num; $j++)
-            {
-                $delta = $deltas[$j];
-                if ($delta != 0 && $range[$j] == 1)
-                { $range[$j] = 0; }
-                else
-                {
-                    $range[$j] = ($count + $num - $j) << 1;
-                    $count += $ends[$j] - $starts[$j] + 1;
-                }
-            }
-
-            $fh->print(pack("n*", @range));
-
-            for ($j = 0; $j < $num; $j++)
-            {
-                next if ($range[$j] == 0);
-                $fh->print(pack("n*", @{$s->{'val'}}{$starts[$j] .. $ends[$j]}));
-            }
-        } elsif ($s->{'Format'} == 8 || $s->{'Format'} == 12)
-        {
-            my (@jobs, $start, $current, $curr_glyf, $map);
-            
-            $map = "\000" x 8192;
-            foreach $j (@keys)
-            {
-                if ($j > 0xFFFF)
-                {
-                    if (defined $s->{'val'}{$j >> 16})
-                    { $s->{'Format'} = 12; }
-                    vec($map, $j >> 16, 1) = 1;
-                }
-                if ($j != $current + 1 || $s->{'val'}{$j} != $curr_glyf + 1)
-                {
-                    push (@jobs, [$start, $current, $curr_glyf - ($current - $start)]) if (defined $start);
-                    $start = $j; $current = $j; $curr_glyf = $s->{'val'}{$j};
-                }
-                $current = $j;
-                $curr_glyf = $s->{'val'}{$j};
-            }
-            push (@jobs, [$start, $current, $curr_glyf - ($current - $start)]) if (defined $start);
-            $fh->print($map) if ($s->{'Format'} == 8);
-            $fh->print(pack('N', $#jobs + 1));
-            foreach $j (@jobs)
-            { $fh->print(pack('N3', @{$j})); }
-        } elsif ($s->{'Format'} == 10)
-        {
-            $fh->print(pack('N2', $keys[0], $keys[-1] - $keys[0] + 1));
-            $fh->print(pack('n*', $s->{'val'}{$keys[0] .. $keys[-1]}));
-        }
-
-        $loc = $fh->tell();
-        if ($s->{'Format'} < 8)
-        {
-            $fh->seek($s->{' outloc'} + 2, 0);
-            $fh->print(pack("n", $loc - $s->{' outloc'}));
-        } else
-        {
-            $fh->seek($s->{' outloc'} + 4, 0);
-            $fh->print(pack("N", $loc - $s->{' outloc'}));
-        }
-        $fh->seek($base_loc + 8 + ($i << 3), 0);
-        $fh->print(pack("N", $s->{' outloc'} - $base_loc));
-        $fh->seek($loc, 0);
-    }
-    $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $name, $val)
-
-Outputs the elements of the cmap in XML. We only need to process val here
-
-=cut
-
-sub XML_element
-{
-    my ($self, $context, $depth, $k, $val) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($i);
-
-    return $self if ($k eq 'LOC');
-    return $self->SUPER::XML_element($context, $depth, $k, $val) unless ($k eq 'val');
-
-    $fh->print("$depth<mappings>\n");
-    foreach $i (sort {$a <=> $b} keys %{$val})
-    { $fh->printf("%s<map code='%04X' glyph='%s'/>\n", $depth . $context->{'indent'}, $i, $val->{$i}); }
-    $fh->print("$depth</mappings>\n");
-    $self;
-}
-
-=head2 @map = $t->reverse([$num])
-
-Returns a reverse map of the table of given number or the Unicode
-cmap. I.e. given a glyph gives the Unicode value for it.
-
-=cut
-
-sub reverse
-{
-    my ($self, $tnum) = @_;
-    my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms;
-    my (@res, $code, $gid);
-
-    while (($code, $gid) = each(%{$table->{'val'}}))
-    { $res[$gid] = $code unless (defined $res[$gid] && $res[$gid] > 0 && $res[$gid] < $code); }
-    @res;
-}
-
-
-=head2 is_unicode($index)
-
-Returns whether the table of a given index is known to be a unicode table
-(as specified in the specifications)
-
-=cut
-
-sub is_unicode
-{
-    my ($self, $index) = @_;
-    my ($pid, $eid) = ($self->{'Tables'}[$index]{'Platform'}, $self->{'Tables'}[$index]{'Encoding'});
-
-    return ($pid == 3 || $pid == 0 || ($pid == 2 && $eid == 1));
-}
-
-1;
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-No support for format 2 tables (MBCS)
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Cmap;
+
+=head1 NAME
+
+Font::TTF::Cmap - Character map table
+
+=head1 DESCRIPTION
+
+Looks after the character map. For ease of use, the actual cmap is held in
+a hash against codepoint. Thus for a given table:
+
+    $gid = $font->{'cmap'}{'Tables'}[0]{'val'}{$code};
+
+Note that C<$code> should be a true value (0x1234) rather than a string representation.
+
+=head1 INSTANCE VARIABLES
+
+The instance variables listed here are not preceeded by a space due to their
+emulating structural information in the font.
+
+=over 4
+
+=item Num
+
+Number of subtables in this table
+
+=item Tables
+
+An array of subtables ([0..Num-1])
+
+=back
+
+Each subtables also has its own instance variables which are, again, not
+preceeded by a space.
+
+=over 4
+
+=item Platform
+
+The platform number for this subtable
+
+=item Encoding
+
+The encoding number for this subtable
+
+=item Format
+
+Gives the stored format of this subtable
+
+=item Ver
+
+Gives the version (or language) information for this subtable
+
+=item val
+
+A hash keyed by the codepoint value (not a string) storing the glyph id
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+
+
+=head2 $t->read
+
+Reads the cmap into memory. Format 4 subtables read the whole subtable and
+fill in the segmented array accordingly.
+
+Format 2 subtables are not read at all.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $i, $j, $k, $id, @ids, $s);
+    my ($start, $end, $range, $delta, $form, $len, $num, $ver, $sg);
+    my ($fh) = $self->{' INFILE'};
+
+    $self->SUPER::read or return $self;
+    $fh->read($dat, 4);
+    $self->{'Num'} = unpack("x2n", $dat);
+    $self->{'Tables'} = [];
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = {};
+        $fh->read($dat, 8);
+        ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat));
+        $s->{'LOC'} += $self->{' OFFSET'};
+        push(@{$self->{'Tables'}}, $s);
+    }
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        $fh->seek($s->{'LOC'}, 0);
+        $fh->read($dat, 2);
+        $form = unpack("n", $dat);
+
+        $s->{'Format'} = $form;
+        if ($form == 0)
+        {
+            my ($j) = 0;
+
+            $fh->read($dat, 4);
+            ($len, $s->{'Ver'}) = unpack('n2', $dat);
+            $fh->read($dat, 256);
+            $s->{'val'} = {map {$j++; ($_ ? ($j - 1, $_) : ())} unpack("C*", $dat)};
+        } elsif ($form == 6)
+        {
+            my ($start, $ecount);
+            
+            $fh->read($dat, 8);
+            ($len, $s->{'Ver'}, $start, $ecount) = unpack('n4', $dat);
+            $fh->read($dat, $ecount << 1);
+            $s->{'val'} = {map {$start++; ($_ ? ($start - 1, $_) : ())} unpack("n*", $dat)};
+        } elsif ($form == 2)
+        {
+# no idea what to do here yet
+        } elsif ($form == 4)
+        {
+            $fh->read($dat, 12);
+            ($len, $s->{'Ver'}, $num) = unpack('n3', $dat);
+            $num >>= 1;
+            $fh->read($dat, $len - 14);
+            for ($j = 0; $j < $num; $j++)
+            {
+                $end = unpack("n", substr($dat, $j << 1, 2));
+                $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2));
+                $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2));
+                $delta -= 65536 if $delta > 32767;
+                $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2));
+                for ($k = $start; $k <= $end; $k++)
+                {
+                    if ($range == 0 || $range == 65535)         # support the buggy FOG with its range=65535 for final segment
+                    { $id = $k + $delta; }
+                    else
+                    { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 +
+                                        2 + ($k - $start) * 2 + $range, 2)) + $delta; }
+		            $id -= 65536 if $id >= 65536;
+                    $s->{'val'}{$k} = $id if ($id);
+                }
+            }
+        } elsif ($form == 8 || $form == 12)
+        {
+            $fh->read($dat, 10);
+            ($len, $s->{'Ver'}) = unpack('x2N2', $dat);
+            if ($form == 8)
+            {
+                $fh->read($dat, 8196);
+                $num = unpack("N", substr($dat, 8192, 4)); # don't need the map
+            } else
+            {
+                $fh->read($dat, 4);
+                $num = unpack("N", $dat);
+            }
+            $fh->read($dat, 12 * $num);
+            for ($j = 0; $j < $num; $j++)
+            {
+                ($start, $end, $sg) = unpack("N3", substr($dat, $j * 12, 12));
+                for ($k = $start; $k <= $end; $k++)
+                { $s->{'val'}{$k} = $sg++; }
+            }
+        } elsif ($form == 10)
+        {
+            $fh->read($dat, 18);
+            ($len, $s->{'Ver'}, $start, $num) = unpack('x2N4', $dat);
+            $fh->read($dat, $num << 1);
+            for ($j = 0; $j < $num; $j++)
+            { $s->{'val'}{$start + $j} = unpack("n", substr($dat, $j << 1, 2)); }
+        }
+    }
+    $self;
+}
+
+
+=head2 $t->ms_lookup($uni)
+
+Finds a Unicode table, giving preference to the MS one, and looks up the given
+Unicode codepoint in it to find the glyph id.
+
+=cut
+
+sub ms_lookup
+{
+    my ($self, $uni) = @_;
+
+    $self->find_ms || return undef unless (defined $self->{' mstable'});
+    return $self->{' mstable'}{'val'}{$uni};
+}
+
+
+=head2 $t->find_ms
+
+Finds the a Unicode table, giving preference to the Microsoft one, and sets the C<mstable> instance variable
+to it if found. Returns the table it finds.
+
+=cut
+sub find_ms
+{
+    my ($self) = @_;
+    my ($i, $s, $alt, $found);
+
+    return $self->{' mstable'} if defined $self->{' mstable'};
+    $self->read;
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        if ($s->{'Platform'} == 3)
+        {
+            $self->{' mstable'} = $s;
+            last if ($s->{'Encoding'} == 10);
+            $found = 1 if ($s->{'Encoding'} == 1);
+        } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1))
+        { $alt = $s; }
+    }
+    $self->{' mstable'} = $alt if ($alt && !$found);
+    $self->{' mstable'};
+}
+
+
+=head2 $t->ms_enc
+
+Returns the encoding of the microsoft table (0 => symbol, etc.). Returns undef if there is
+no Microsoft cmap.
+
+=cut
+
+sub ms_enc
+{
+    my ($self) = @_;
+    my ($s);
+    
+    return $self->{' mstable'}{'Encoding'} 
+        if (defined $self->{' mstable'} && $self->{' mstable'}{'Platform'} == 3);
+    
+    foreach $s (@{$self->{'Tables'}})
+    {
+        return $s->{'Encoding'} if ($s->{'Platform'} == 3);
+    }
+    return undef;
+}
+
+
+=head2 $t->out($fh)
+
+Writes out a cmap table to a filehandle. If it has not been read, then
+just copies from input file to output
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($loc, $s, $i, $base_loc, $j, @keys);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+
+    $self->{'Tables'} = [sort {$a->{'Platform'} <=> $b->{'Platform'}
+                                || $a->{'Encoding'} <=> $b->{'Encoding'}
+                                || $a->{'Ver'} <=> $b->{'Ver'}} @{$self->{'Tables'}}];
+    $self->{'Num'} = scalar @{$self->{'Tables'}};
+
+    $base_loc = $fh->tell();
+    $fh->print(pack("n2", 0, $self->{'Num'}));
+
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); }
+
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        @keys = sort {$a <=> $b} keys %{$s->{'val'}};
+        $s->{' outloc'} = $fh->tell();
+        if ($s->{'Format'} < 8)
+        { $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); }       # come back for length
+        else
+        { $fh->print(pack("n2N2", $s->{'Format'}, 0, 0, $s->{'Ver'})); }
+            
+        if ($s->{'Format'} == 0)
+        {
+            $fh->print(pack("C256", @{$s->{'val'}}{0 .. 255}));
+        } elsif ($s->{'Format'} == 6)
+        {
+            $fh->print(pack("n2", $keys[0], $keys[-1] - $keys[0] + 1));
+            $fh->print(pack("n*", @{$s->{'val'}}{$keys[0] .. $keys[-1]}));
+        } elsif ($s->{'Format'} == 2)
+        {
+        } elsif ($s->{'Format'} == 4)
+        {
+            my ($num, $sRange, $eSel, $eShift, @starts, @ends, $doff);
+            my (@deltas, $delta, @range, $flat, $k, $segs, $count, $newseg, $v);
+
+            push(@keys, 0xFFFF) unless ($keys[-1] == 0xFFFF);
+            $newseg = 1; $num = 0;
+            for ($j = 0; $j <= $#keys && $keys[$j] <= 0xFFFF; $j++)
+            {
+                $v = $s->{'val'}{$keys[$j]};
+                if ($newseg)
+                {
+                    $delta = $v;
+                    $doff = $j;
+                    $flat = 1;
+                    push(@starts, $keys[$j]);
+                    $newseg = 0;
+                }
+                $delta = 0 if ($delta + $j - $doff != $v);
+                $flat = 0 if ($v == 0);
+                if ($j == $#keys || $keys[$j] + 1 != $keys[$j+1])
+                {
+                    push (@ends, $keys[$j]);
+                    push (@deltas, $delta ? $delta - $keys[$doff] : 0);
+                    push (@range, $flat);
+                    $num++;
+                    $newseg = 1;
+                }
+            }
+
+            ($num, $sRange, $eSel, $eShift) = Font::TTF::Utils::TTF_bininfo($num, 2);
+            $fh->print(pack("n4", $num * 2, $sRange, $eSel, $eShift));
+            $fh->print(pack("n*", @ends));
+            $fh->print(pack("n", 0));
+            $fh->print(pack("n*", @starts));
+            $fh->print(pack("n*", @deltas));
+
+            $count = 0;
+            for ($j = 0; $j < $num; $j++)
+            {
+                $delta = $deltas[$j];
+                if ($delta != 0 && $range[$j] == 1)
+                { $range[$j] = 0; }
+                else
+                {
+                    $range[$j] = ($count + $num - $j) << 1;
+                    $count += $ends[$j] - $starts[$j] + 1;
+                }
+            }
+
+            $fh->print(pack("n*", @range));
+
+            for ($j = 0; $j < $num; $j++)
+            {
+                next if ($range[$j] == 0);
+                $fh->print(pack("n*", @{$s->{'val'}}{$starts[$j] .. $ends[$j]}));
+            }
+        } elsif ($s->{'Format'} == 8 || $s->{'Format'} == 12)
+        {
+            my (@jobs, $start, $current, $curr_glyf, $map);
+            
+            $map = "\000" x 8192;
+            foreach $j (@keys)
+            {
+                if ($j > 0xFFFF)
+                {
+                    if (defined $s->{'val'}{$j >> 16})
+                    { $s->{'Format'} = 12; }
+                    vec($map, $j >> 16, 1) = 1;
+                }
+                if ($j != $current + 1 || $s->{'val'}{$j} != $curr_glyf + 1)
+                {
+                    push (@jobs, [$start, $current, $curr_glyf - ($current - $start)]) if (defined $start);
+                    $start = $j; $current = $j; $curr_glyf = $s->{'val'}{$j};
+                }
+                $current = $j;
+                $curr_glyf = $s->{'val'}{$j};
+            }
+            push (@jobs, [$start, $current, $curr_glyf - ($current - $start)]) if (defined $start);
+            $fh->print($map) if ($s->{'Format'} == 8);
+            $fh->print(pack('N', $#jobs + 1));
+            foreach $j (@jobs)
+            { $fh->print(pack('N3', @{$j})); }
+        } elsif ($s->{'Format'} == 10)
+        {
+            $fh->print(pack('N2', $keys[0], $keys[-1] - $keys[0] + 1));
+            $fh->print(pack('n*', $s->{'val'}{$keys[0] .. $keys[-1]}));
+        }
+
+        $loc = $fh->tell();
+        if ($s->{'Format'} < 8)
+        {
+            $fh->seek($s->{' outloc'} + 2, 0);
+            $fh->print(pack("n", $loc - $s->{' outloc'}));
+        } else
+        {
+            $fh->seek($s->{' outloc'} + 4, 0);
+            $fh->print(pack("N", $loc - $s->{' outloc'}));
+        }
+        $fh->seek($base_loc + 8 + ($i << 3), 0);
+        $fh->print(pack("N", $s->{' outloc'} - $base_loc));
+        $fh->seek($loc, 0);
+    }
+    $self;
+}
+
+
+=head2 $t->XML_element($context, $depth, $name, $val)
+
+Outputs the elements of the cmap in XML. We only need to process val here
+
+=cut
+
+sub XML_element
+{
+    my ($self, $context, $depth, $k, $val) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($i);
+
+    return $self if ($k eq 'LOC');
+    return $self->SUPER::XML_element($context, $depth, $k, $val) unless ($k eq 'val');
+
+    $fh->print("$depth<mappings>\n");
+    foreach $i (sort {$a <=> $b} keys %{$val})
+    { $fh->printf("%s<map code='%04X' glyph='%s'/>\n", $depth . $context->{'indent'}, $i, $val->{$i}); }
+    $fh->print("$depth</mappings>\n");
+    $self;
+}
+
+=head2 @map = $t->reverse([$num])
+
+Returns a reverse map of the table of given number or the Unicode
+cmap. I.e. given a glyph gives the Unicode value for it.
+
+=cut
+
+sub reverse
+{
+    my ($self, $tnum) = @_;
+    my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms;
+    my (@res, $code, $gid);
+
+    while (($code, $gid) = each(%{$table->{'val'}}))
+    { $res[$gid] = $code unless (defined $res[$gid] && $res[$gid] > 0 && $res[$gid] < $code); }
+    @res;
+}
+
+
+=head2 is_unicode($index)
+
+Returns whether the table of a given index is known to be a unicode table
+(as specified in the specifications)
+
+=cut
+
+sub is_unicode
+{
+    my ($self, $index) = @_;
+    my ($pid, $eid) = ($self->{'Tables'}[$index]{'Platform'}, $self->{'Tables'}[$index]{'Encoding'});
+
+    return ($pid == 3 || $pid == 0 || ($pid == 2 && $eid == 1));
+}
+
+1;
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+No support for format 2 tables (MBCS)
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Coverage.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Coverage.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Coverage.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,253 +1,253 @@
-package Font::TTF::Coverage;
-
-=head1 NAME
-
-Font::TTF::Coverage - Opentype coverage and class definition objects
-
-=head1 DESCRIPTION
-
-Coverage tables and class definition objects are virtually identical concepts
-in OpenType. Their difference comes purely in their storage. Therefore we can
-say that a coverage table is a class definition in which the class definition
-for each glyph is the corresponding index in the coverage table. The resulting
-data structure is that a Coverage table has the following fields:
-
-=item cover
-
-A boolean to indicate whether this table is a coverage table (TRUE) or a
-class definition (FALSE)
-
-=item val
-
-A hash of glyph ids against values (either coverage index or class value)
-
-=item fmt
-
-The storage format used is given here, but is recalculated when the table
-is written out.
-
-=item count
-
-A count of the elements in a coverage table for use with add. Each subsequent
-addition is added with the current count and increments the count.
-
-=head1 METHODS
-
-=cut
-
-=head2 new($isCover [, vals])
-
-Creates a new coverage table or class definition table, depending upon the
-value of $isCover. if $isCover then vals may be a list of glyphs to include in order.
-If no $isCover, then vals is a hash of glyphs against class values.
-
-=cut
-
-sub new
-{
-    my ($class) = shift;
-    my ($isCover) = shift;
-    my ($self) = {};
-
-    $self->{'cover'} = $isCover;
-    $self->{'count'} = 0;
-    if ($isCover)
-    {
-        my ($v);
-        foreach $v (@_)
-        { $self->{'val'}{$v} = $self->{'count'}++; }
-    }
-    else
-    { $self->{'val'} = {@_}; }
-    bless $self, $class;
-}
-
-
-=head2 read($fh)
-
-Reads the coverage/class table from the given file handle
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat, $fmt, $num, $i, $c);
-
-    $fh->read($dat, 4);
-    ($fmt, $num) = unpack("n2", $dat);
-    $self->{'fmt'} = $fmt;
-
-    if ($self->{'cover'})
-    {
-        if ($fmt == 1)
-        {
-            $fh->read($dat, $num << 1);
-            map {$self->{'val'}{$_} = $i++} unpack("n*", $dat);
-        } elsif ($fmt == 2)
-        {
-            $fh->read($dat, $num * 6);
-            for ($i = 0; $i < $num; $i++)
-            {
-                ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6));
-                map {$self->{'val'}{$_} = $c++} ($first .. $last);
-            }
-        }
-    } elsif ($fmt == 1)
-    {
-        $fh->read($dat, 2);
-        $first = $num;
-        ($num) = unpack("n", $dat);
-        $fh->read($dat, $num << 1);
-        map {$self->{'val'}{$first++} = $_} unpack("n*", $dat);
-    } elsif ($fmt == 2)
-    {
-        $fh->read($dat, $num * 6);
-        for ($i = 0; $i < $num; $i++)
-        {
-            ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6));
-            map {$self->{'val'}{$_} = $c} ($first .. $last);
-        }
-    }
-    $self;
-}
-
-
-=head2 out($fh, $state)
-
-Writes the coverage/class table to the given file handle. If $state is 1 then
-the output string is returned rather than being output to a filehandle.
-
-=cut
-
-sub out
-{
-    my ($self, $fh, $state) = @_;
-    my ($g, $eff, $grp, $out);
-    my ($shipout) = ($state ? sub {$out .= $_[0];} : sub {$fh->print($_[0]);});
-    my (@gids) = sort {$a <=> $b} keys %{$self->{'val'}};
-
-    $fmt = 1; $grp = 1;
-    for ($i = 1; $i <= $#gids; $i++)
-    {
-        if ($self->{'val'}{$gids[$i]} < $self->{'val'}{$gids[$i-1]} && $self->{'cover'})
-        {
-            $fmt = 2;
-            last;
-        } elsif ($gids[$i] == $gids[$i-1] + 1)
-        { $eff++; }
-        else
-        { $grp++; }
-    }
-    if ($self->{'cover'})
-    { $fmt = 2 if ($eff / $grp > 4); }
-    else
-    { $fmt = 2 if ($grp > 1); }
-    
-    if ($fmt == 1 && $self->{'cover'})
-    {
-        my ($last) = 0;
-        &$shipout(pack('n2', 1, scalar @gids));
-        &$shipout(pack('n*', @gids));
-    } elsif ($fmt == 1)
-    {
-        my ($last) = $gids[0];
-        &$shipout(pack("n3", 1, $last, $gids[-1] - $last + 1));
-        foreach $g (@gids)
-        {
-            if ($g > $last + 1)
-            { &$shipout(pack('n*', 0 x ($g - $last - 1))); }
-            &$shipout(pack('n', $self->{'val'}{$g}));
-            $last = $g;
-        }
-    } else
-    {
-        my ($start, $end, $ind, $numloc, $endloc, $num);
-        &$shipout(pack("n2", 2, 0));
-        $numloc = $fh->tell() - 2 unless $state;
-
-        $start = 0; $end = 0; $num = 0;
-        while ($end < $#gids)
-        {
-            if ($gids[$end + 1] == $gids[$end] + 1
-                && $self->{'val'}{$gids[$end + 1]}
-                        == $self->{'val'}{$gids[$end]}
-                           + ($self->{'cover'} ? 1 : 0))
-            {
-                $end++;
-                next;
-            }
-
-            &$shipout(pack("n3", $gids[$start], $gids[$end],
-                    $self->{'val'}{$gids[$start]}));
-            $start = $end + 1;
-            $end++;
-            $num++;
-        }
-        &$shipout(pack("n3", $gids[$start], $gids[$end],
-                $self->{'val'}{$gids[$start]}));
-        $num++;
-        if ($state)
-        { substr($out, 2, 2) = pack('n', $num); }
-        else
-        {
-            $endloc = $fh->tell();
-            $fh->seek($numloc, 0);
-            $fh->print(pack("n", $num));
-            $fh->seek($endloc, 0);
-        }
-    }
-    return ($state ? $out : $self);
-}
-
-
-=head2 $c->add($glyphid)
-
-Adds a glyph id to the coverage table incrementing the count so that each subsequent addition
-has the next sequential number. Returns the index number of the glyphid added
-
-=cut
-
-sub add
-{
-    my ($self, $gid) = @_;
-    
-    return $self->{'val'}{$gid} if (defined $self->{'val'}{$gid});
-    $self->{'val'}{$gid} = $self->{'count'};
-    return $self->{'count'}++;
-}
-
-
-=head2 $c->out_xml($context)
-
-Outputs this coverage/class in XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-
-    $fh->print("$depth<" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n");
-    foreach $gid (sort {$a <=> $b} keys %{$self->{'val'}})
-    {
-        $fh->printf("$depth$context->{'indent'}<gref glyph='%s' val='%s'/>\n", $gid, $self->{'val'}{$gid});
-    }
-    $fh->print("$depth</" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n");
-    $self;
-}
-
-sub release
-{ }
-
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+package Font::TTF::Coverage;
+
+=head1 TITLE
+
+Font::TTF::Coverage - Opentype coverage and class definition objects
+
+=head1 DESCRIPTION
+
+Coverage tables and class definition objects are virtually identical concepts
+in OpenType. Their difference comes purely in their storage. Therefore we can
+say that a coverage table is a class definition in which the class definition
+for each glyph is the corresponding index in the coverage table. The resulting
+data structure is that a Coverage table has the following fields:
+
+=item cover
+
+A boolean to indicate whether this table is a coverage table (TRUE) or a
+class definition (FALSE)
+
+=item val
+
+A hash of glyph ids against values (either coverage index or class value)
+
+=item fmt
+
+The storage format used is given here, but is recalculated when the table
+is written out.
+
+=item count
+
+A count of the elements in a coverage table for use with add. Each subsequent
+addition is added with the current count and increments the count.
+
+=head1 METHODS
+
+=cut
+
+=head2 new($isCover [, vals])
+
+Creates a new coverage table or class definition table, depending upon the
+value of $isCover. if $isCover then vals may be a list of glyphs to include in order.
+If no $isCover, then vals is a hash of glyphs against class values.
+
+=cut
+
+sub new
+{
+    my ($class) = shift;
+    my ($isCover) = shift;
+    my ($self) = {};
+
+    $self->{'cover'} = $isCover;
+    $self->{'count'} = 0;
+    if ($isCover)
+    {
+        my ($v);
+        foreach $v (@_)
+        { $self->{'val'}{$v} = $self->{'count'}++; }
+    }
+    else
+    { $self->{'val'} = {@_}; }
+    bless $self, $class;
+}
+
+
+=head2 read($fh)
+
+Reads the coverage/class table from the given file handle
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat, $fmt, $num, $i, $c);
+
+    $fh->read($dat, 4);
+    ($fmt, $num) = unpack("n2", $dat);
+    $self->{'fmt'} = $fmt;
+
+    if ($self->{'cover'})
+    {
+        if ($fmt == 1)
+        {
+            $fh->read($dat, $num << 1);
+            map {$self->{'val'}{$_} = $i++} unpack("n*", $dat);
+        } elsif ($fmt == 2)
+        {
+            $fh->read($dat, $num * 6);
+            for ($i = 0; $i < $num; $i++)
+            {
+                ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6));
+                map {$self->{'val'}{$_} = $c++} ($first .. $last);
+            }
+        }
+    } elsif ($fmt == 1)
+    {
+        $fh->read($dat, 2);
+        $first = $num;
+        ($num) = unpack("n", $dat);
+        $fh->read($dat, $num << 1);
+        map {$self->{'val'}{$first++} = $_} unpack("n*", $dat);
+    } elsif ($fmt == 2)
+    {
+        $fh->read($dat, $num * 6);
+        for ($i = 0; $i < $num; $i++)
+        {
+            ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6));
+            map {$self->{'val'}{$_} = $c} ($first .. $last);
+        }
+    }
+    $self;
+}
+
+
+=head2 out($fh, $state)
+
+Writes the coverage/class table to the given file handle. If $state is 1 then
+the output string is returned rather than being output to a filehandle.
+
+=cut
+
+sub out
+{
+    my ($self, $fh, $state) = @_;
+    my ($g, $eff, $grp, $out);
+    my ($shipout) = ($state ? sub {$out .= $_[0];} : sub {$fh->print($_[0]);});
+    my (@gids) = sort {$a <=> $b} keys %{$self->{'val'}};
+
+    $fmt = 1; $grp = 1;
+    for ($i = 1; $i <= $#gids; $i++)
+    {
+        if ($self->{'val'}{$gids[$i]} < $self->{'val'}{$gids[$i-1]} && $self->{'cover'})
+        {
+            $fmt = 2;
+            last;
+        } elsif ($gids[$i] == $gids[$i-1] + 1)
+        { $eff++; }
+        else
+        { $grp++; }
+    }
+    if ($self->{'cover'})
+    { $fmt = 2 if ($eff / $grp > 4); }
+    else
+    { $fmt = 2 if ($grp > 1); }
+    
+    if ($fmt == 1 && $self->{'cover'})
+    {
+        my ($last) = 0;
+        &$shipout(pack('n2', 1, scalar @gids));
+        &$shipout(pack('n*', @gids));
+    } elsif ($fmt == 1)
+    {
+        my ($last) = $gids[0];
+        &$shipout(pack("n3", 1, $last, $gids[-1] - $last + 1));
+        foreach $g (@gids)
+        {
+            if ($g > $last + 1)
+            { &$shipout(pack('n*', 0 x ($g - $last - 1))); }
+            &$shipout(pack('n', $self->{'val'}{$g}));
+            $last = $g;
+        }
+    } else
+    {
+        my ($start, $end, $ind, $numloc, $endloc, $num);
+        &$shipout(pack("n2", 2, 0));
+        $numloc = $fh->tell() - 2 unless $state;
+
+        $start = 0; $end = 0; $num = 0;
+        while ($end < $#gids)
+        {
+            if ($gids[$end + 1] == $gids[$end] + 1
+                && $self->{'val'}{$gids[$end + 1]}
+                        == $self->{'val'}{$gids[$end]}
+                           + ($self->{'cover'} ? 1 : 0))
+            {
+                $end++;
+                next;
+            }
+
+            &$shipout(pack("n3", $gids[$start], $gids[$end],
+                    $self->{'val'}{$gids[$start]}));
+            $start = $end + 1;
+            $end++;
+            $num++;
+        }
+        &$shipout(pack("n3", $gids[$start], $gids[$end],
+                $self->{'val'}{$gids[$start]}));
+        $num++;
+        if ($state)
+        { substr($out, 2, 2) = pack('n', $num); }
+        else
+        {
+            $endloc = $fh->tell();
+            $fh->seek($numloc, 0);
+            $fh->print(pack("n", $num));
+            $fh->seek($endloc, 0);
+        }
+    }
+    return ($state ? $out : $self);
+}
+
+
+=head2 $c->add($glyphid)
+
+Adds a glyph id to the coverage table incrementing the count so that each subsequent addition
+has the next sequential number. Returns the index number of the glyphid added
+
+=cut
+
+sub add
+{
+    my ($self, $gid) = @_;
+    
+    return $self->{'val'}{$gid} if (defined $self->{'val'}{$gid});
+    $self->{'val'}{$gid} = $self->{'count'};
+    return $self->{'count'}++;
+}
+
+
+=head2 $c->out_xml($context)
+
+Outputs this coverage/class in XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+
+    $fh->print("$depth<" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n");
+    foreach $gid (sort {$a <=> $b} keys %{$self->{'val'}})
+    {
+        $fh->printf("$depth$context->{'indent'}<gref glyph='%s' val='%s'/>\n", $gid, $self->{'val'}{$gid});
+    }
+    $fh->print("$depth</" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n");
+    $self;
+}
+
+sub release
+{ }
+
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cvt_.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cvt_.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Cvt_.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,81 +1,81 @@
-package Font::TTF::Cvt_;
-
-=head1 NAME
-
-Font::TTF::Cvt_ - Control Value Table in a TrueType font
-
-=head1 DESCRIPTION
-
-This is a minimal class adding nothing beyond a table, but is a repository
-for cvt type information for those processes brave enough to address hinting.
-
-=head1 INSTANCE VARIABLES
-
-=over 4
-
-=item val
-
-This is an array of CVT values. Thus access to the CVT is via:
-
-    $f->{'cvt_'}{'val'}[$num];
-
-=back    
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA $VERSION);
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
-
-$VERSION = 0.0001;
-
-=head2 $t->read
-
-Reads the CVT table into both the tables C<' dat'> variable and the C<val>
-array.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-
-    $self->read_dat || return undef;
-    $self->{' read'} = 1;
-    $self->{'val'} = [TTF_Unpack("s*", $self->{' dat'})];
-    $self;
-}
-
-
-=head2 $t->update
-
-Updates the RAM file copy C<' dat'> to be the same as the array.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-
-    return undef unless ($self->{' read'} && $#{$self->{'val'}} >= 0);
-    $self->{' dat'} = TTF_Pack("s*", @{$self->{'val'}});
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Cvt_;
+
+=head1 NAME
+
+Font::TTF::Cvt_ - Control Value Table in a TrueType font
+
+=head1 DESCRIPTION
+
+This is a minimal class adding nothing beyond a table, but is a repository
+for cvt type information for those processes brave enough to address hinting.
+
+=head1 INSTANCE VARIABLES
+
+=over 4
+
+=item val
+
+This is an array of CVT values. Thus access to the CVT is via:
+
+    $f->{'cvt_'}{'val'}[$num];
+
+=back    
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA $VERSION);
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+
+$VERSION = 0.0001;
+
+=head2 $t->read
+
+Reads the CVT table into both the tables C<' dat'> variable and the C<val>
+array.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+
+    $self->read_dat || return undef;
+    $self->{' read'} = 1;
+    $self->{'val'} = [TTF_Unpack("s*", $self->{' dat'})];
+    $self;
+}
+
+
+=head2 $t->update
+
+Updates the RAM file copy C<' dat'> to be the same as the array.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+
+    return undef unless ($self->{' read'} && $#{$self->{'val'}} >= 0);
+    $self->{' dat'} = TTF_Pack("s*", @{$self->{'val'}});
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Delta.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Delta.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Delta.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,160 +1,160 @@
-package Font::TTF::Delta;
-
-=head1 NAME
-
-SIL::TTF::Delta - Opentype Device tables
-
-=head1 DESCRIPTION
-
-Each device table corresponds to a set of deltas for a particular point over
-a range of ppem values.
-
-=item first
-
-The first ppem value in the range
-
-=item last
-
-The last ppem value in the range
-
-=item val
-
-This is an array of deltas corresponding to each ppem in the range between
-first and last inclusive.
-
-=item fmt
-
-This is the fmt used (log2 of number bits per value) when the device table was
-read. It is recalculated on output.
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use Font::TTF::Utils;
-
-=head2 new
-
-Creates a new device table
-
-=cut
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-
-    bless $self, $class;
-}
-
-
-=head2 read
-
-Reads a device table from the given IO object at the current location
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat, $fmt, $num, $i, $j, $mask);
-
-    $fh->read($dat, 6);
-    ($self->{'first'}, $self->{'last'}, $fmt) = TTF_Unpack("S3", $dat);
-    $self->{'fmt'} = $fmt;
-
-    $fmt = 1 << $fmt;
-    $num = ((($self->{'last'} - $self->{'first'} + 1) * $fmt) + 15) >> 8;
-    $fh->read($dat, $num);
-
-    $mask = (0xffff << (16 - $fmt)) & 0xffff;
-    $j = 0;
-    for ($i = $self->{'first'}; $i <= $self->{'last'}; $i++)
-    {
-        if ($j == 0)
-        {
-            $num = TTF_Unpack("S", substr($dat, 0, 2));
-            substr($dat, 0, 2) = '';
-        }
-        push (@{$self->{'val'}}, ($num & $mask) >> (16 - $fmt));
-        $num <<= $fmt;
-        $j += $fmt;
-        $j = 0 if ($j >= 16);
-    }
-    $self;
-}
-
-
-=head2 out($fh, $style)
-
-Outputs a device table to the given IO object at the current location, or just
-returns the data to be output if $style != 0
-
-=cut
-
-sub out
-{
-    my ($self, $fh, $style) = @_;
-    my ($dat, $fmt, $num, $mask, $j, $f, $out);
-
-    foreach $f (@{$self->{'val'}})
-    {
-        my ($tfmt) = $f > 0 ? $f + 1 : -$f;
-        $fmt = $tfmt if $tfmt > $fmt;
-    }
-
-    if ($fmt > 8)
-    { $fmt = 3; }
-    elsif ($fmt > 2)
-    { $fmt = 2; }
-    else
-    { $fmt = 1; }
-
-    $out = TTF_Pack("S3", $self->{'first'}, $self->{'last'}, $fmt);
-
-    $fmt = 1 << $fmt;
-    $mask = 0xffff >> (16 - $fmt);
-    $j = 0; $dat = 0;
-    foreach $f (@{$self->{'val'}})
-    {
-        $dat |= ($f & $mask) << (16 - $fmt - $j);
-        $j += $fmt;
-        if ($j >= 16)
-        {
-            $j = 0;
-            $out .= TTF_Pack("S", $dat);
-            $dat = 0;
-        }
-    }
-    $out .= pack('n', $dat) if ($j > 0);
-    $fh->print($out) unless $style;
-    $out;
-}
-
-
-=head2 $d->out_xml($context)
-
-Outputs a delta in XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-
-    $fh->printf("%s<delta first='%s' last='%s'>\n", $depth, $self->{'first'}, $self->{'last'});
-    $fh->print("$depth$context->{'indent'}" . join (' ', @{$self->{'val'}}) . "\n") if defined ($self->{'val'});
-    $fh->print("$depth</delta>\n");
-}
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+package Font::TTF::Delta;
+
+=head1 TITLE
+
+SIL::TTF::Delta - Opentype Device tables
+
+=head1 DESCRIPTION
+
+Each device table corresponds to a set of deltas for a particular point over
+a range of ppem values.
+
+=item first
+
+The first ppem value in the range
+
+=item last
+
+The last ppem value in the range
+
+=item val
+
+This is an array of deltas corresponding to each ppem in the range between
+first and last inclusive.
+
+=item fmt
+
+This is the fmt used (log2 of number bits per value) when the device table was
+read. It is recalculated on output.
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use Font::TTF::Utils;
+
+=head2 new
+
+Creates a new device table
+
+=cut
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+
+    bless $self, $class;
+}
+
+
+=head2 read
+
+Reads a device table from the given IO object at the current location
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat, $fmt, $num, $i, $j, $mask);
+
+    $fh->read($dat, 6);
+    ($self->{'first'}, $self->{'last'}, $fmt) = TTF_Unpack("S3", $dat);
+    $self->{'fmt'} = $fmt;
+
+    $fmt = 1 << $fmt;
+    $num = ((($self->{'last'} - $self->{'first'} + 1) * $fmt) + 15) >> 8;
+    $fh->read($dat, $num);
+
+    $mask = (0xffff << (16 - $fmt)) & 0xffff;
+    $j = 0;
+    for ($i = $self->{'first'}; $i <= $self->{'last'}; $i++)
+    {
+        if ($j == 0)
+        {
+            $num = TTF_Unpack("S", substr($dat, 0, 2));
+            substr($dat, 0, 2) = '';
+        }
+        push (@{$self->{'val'}}, ($num & $mask) >> (16 - $fmt));
+        $num <<= $fmt;
+        $j += $fmt;
+        $j = 0 if ($j >= 16);
+    }
+    $self;
+}
+
+
+=head2 out($fh, $style)
+
+Outputs a device table to the given IO object at the current location, or just
+returns the data to be output if $style != 0
+
+=cut
+
+sub out
+{
+    my ($self, $fh, $style) = @_;
+    my ($dat, $fmt, $num, $mask, $j, $f, $out);
+
+    foreach $f (@{$self->{'val'}})
+    {
+        my ($tfmt) = $f > 0 ? $f + 1 : -$f;
+        $fmt = $tfmt if $tfmt > $fmt;
+    }
+
+    if ($fmt > 8)
+    { $fmt = 3; }
+    elsif ($fmt > 2)
+    { $fmt = 2; }
+    else
+    { $fmt = 1; }
+
+    $out = TTF_Pack("S3", $self->{'first'}, $self->{'last'}, $fmt);
+
+    $fmt = 1 << $fmt;
+    $mask = 0xffff >> (16 - $fmt);
+    $j = 0; $dat = 0;
+    foreach $f (@{$self->{'val'}})
+    {
+        $dat |= ($f & $mask) << (16 - $fmt - $j);
+        $j += $fmt;
+        if ($j >= 16)
+        {
+            $j = 0;
+            $out .= TTF_Pack("S", $dat);
+            $dat = 0;
+        }
+    }
+    $out .= pack('n', $dat) if ($j > 0);
+    $fh->print($out) unless $style;
+    $out;
+}
+
+
+=head2 $d->out_xml($context)
+
+Outputs a delta in XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+
+    $fh->printf("%s<delta first='%s' last='%s'>\n", $depth, $self->{'first'}, $self->{'last'});
+    $fh->print("$depth$context->{'indent'}" . join (' ', @{$self->{'val'}}) . "\n") if defined ($self->{'val'});
+    $fh->print("$depth</delta>\n");
+}
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fdsc.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fdsc.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fdsc.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,125 +1,125 @@
-package Font::TTF::Fdsc;
-
-=head1 NAME
-
-Font::TTF::AAT::Fdsc - Font Descriptors table in a font
-
-=head1 DESCRIPTION
-
-=head1 INSTANCE VARIABLES
-
-=item version
-
-=item descriptors
-
-Hash keyed by descriptor tags
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields);
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $fh, $numDescs, $tag, $descs);
-
-    $self->SUPER::read or return $self;
-
-    $fh = $self->{' INFILE'};
-    $fh->read($dat, 4);
-    $self->{'version'} = TTF_Unpack("f", $dat);
-
-    $fh->read($dat, 4);
-
-    foreach (1 .. unpack("N", $dat)) {
-        $fh->read($tag, 4);
-        $fh->read($dat, 4);
-        $descs->{$tag} = ($tag eq 'nalf') ? unpack("N", $dat) : TTF_Unpack("f", $dat);
-    }
-
-    $self->{'descriptors'} = $descs;
-
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($descs);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-    
-    $fh->print(TTF_Pack("f", $self->{'version'}));
-    
-    $descs = $self->{'descriptors'} or {};
-    
-    $fh->print(pack("N", scalar keys %$descs));    
-    foreach (sort keys %$descs) {
-        $fh->print($_);
-        $fh->print(($_ eq 'nalf') ? pack("N", $descs->{$_}) : TTF_Pack("f", $descs->{$_}));
-    }
-
-    $self;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    my ($descs, $k);
-
-    $self->read;
-
-    $fh = 'STDOUT' unless defined $fh;
-
-    $descs = $self->{'descriptors'};
-    foreach $k (sort keys %$descs) {
-        if ($k eq 'nalf') {
-            $fh->printf("Descriptor '%s' = %d\n", $k, $descs->{$k});
-        }
-        else {
-            $fh->printf("Descriptor '%s' = %f\n", $k, $descs->{$k});
-        }
-    }
-    
-    $self;
-}
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Fdsc;
+
+=head1 NAME
+
+Font::TTF::AAT::Fdsc - Font Descriptors table in a font
+
+=head1 DESCRIPTION
+
+=head1 INSTANCE VARIABLES
+
+=item version
+
+=item descriptors
+
+Hash keyed by descriptor tags
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields);
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $fh, $numDescs, $tag, $descs);
+
+    $self->SUPER::read or return $self;
+
+    $fh = $self->{' INFILE'};
+    $fh->read($dat, 4);
+    $self->{'version'} = TTF_Unpack("f", $dat);
+
+    $fh->read($dat, 4);
+
+    foreach (1 .. unpack("N", $dat)) {
+        $fh->read($tag, 4);
+        $fh->read($dat, 4);
+        $descs->{$tag} = ($tag eq 'nalf') ? unpack("N", $dat) : TTF_Unpack("f", $dat);
+    }
+
+    $self->{'descriptors'} = $descs;
+
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($descs);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+    
+    $fh->print(TTF_Pack("f", $self->{'version'}));
+    
+    $descs = $self->{'descriptors'} or {};
+    
+    $fh->print(pack("N", scalar keys %$descs));    
+    foreach (sort keys %$descs) {
+        $fh->print($_);
+        $fh->print(($_ eq 'nalf') ? pack("N", $descs->{$_}) : TTF_Pack("f", $descs->{$_}));
+    }
+
+    $self;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    my ($descs, $k);
+
+    $self->read;
+
+    $fh = 'STDOUT' unless defined $fh;
+
+    $descs = $self->{'descriptors'};
+    foreach $k (sort keys %$descs) {
+        if ($k eq 'nalf') {
+            $fh->printf("Descriptor '%s' = %d\n", $k, $descs->{$k});
+        }
+        else {
+            $fh->printf("Descriptor '%s' = %f\n", $k, $descs->{$k});
+        }
+    }
+    
+    $self;
+}
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Feat.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Feat.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Feat.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,191 +1,191 @@
-package Font::TTF::Feat;
-
-=head1 NAME
-
-Font::TTF::Feat - Font Features
-
-=head1 DESCRIPTION
-
-=head1 INSTANCE VARIABLES
-
-=over 4
-
-=item version
-
-=item features
-
-An array of hashes of the following form
-
-=over 8
-
-=item feature
-
-feature id number
-
-=item name
-
-name index in name table
-
-=item exclusive
-
-exclusive flag
-
-=item settings
-
-hash of setting number against name string index
-
-=back
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-
-use Font::TTF::Utils;
-
-require Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the features from the TTF file into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($featureCount, $features);
-
-    $self->SUPER::read_dat or return $self;
-
-    ($self->{'version'}, $featureCount) = TTF_Unpack("fS", $self->{' dat'});
-
-    $features = [];
-    foreach (1 .. $featureCount) {
-        my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex)
-                = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12));
-        push @$features,
-            {
-                'feature'    => $feature,
-                'name'        => $nameIndex,
-                'exclusive'    => (($featureFlags & 0x8000) != 0),
-                'settings'    => { TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)) }
-            };
-    }
-    $self->{'features'} = $features;
-    
-    delete $self->{' dat'}; # no longer needed, and may become obsolete
-    
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the features to a TTF file
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($features, $numFeatures, $settings, $featuresData, $settingsData);
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $features = $self->{'features'};
-    $numFeatures = @$features;
-
-    foreach (@$features) {
-        $settings = $_->{'settings'};
-        $featuresData .= TTF_Pack("SSLSS",
-                                    $_->{'feature'},
-                                    scalar keys %$settings,
-                                    12 + 12 * $numFeatures + length $settingsData,
-                                    ($_->{'exclusive'} ? 0x8000 : 0x0000),
-                                    $_->{'name'});
-        foreach (sort {$a <=> $b} keys %$settings) {
-            $settingsData .= TTF_Pack("SS", $_, $settings->{$_});
-        }
-    }
-
-    $fh->print(TTF_Pack("fSSL", $self->{'version'}, $numFeatures, 0, 0));
-    $fh->print($featuresData);
-    $fh->print($settingsData);
-
-    $self;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    my ($names, $features, $settings);
-
-    $self->read;
-
-    $names = $self->{' PARENT'}->{'name'};
-    $names->read;
-
-    $fh = 'STDOUT' unless defined $fh;
-
-    $features = $self->{'features'};
-    foreach (@$features) {
-        $fh->printf("Feature %d, %s, name %d # '%s'\n",
-                    $_->{'feature'},
-                    ($_->{'exclusive'} ? "exclusive" : "additive"),
-                    $_->{'name'},
-                    $names->{'strings'}[$_->{'name'}][1][0]{0});
-        $settings = $_->{'settings'};
-        foreach (sort { $a <=> $b } keys %$settings) {
-            $fh->printf("\tSetting %d, name %d # '%s'\n",
-                        $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][1][0]{0});
-        }
-    }
-    
-    $self;
-}
-
-sub settingName
-{
-    my ($self, $feature, $setting) = @_;
-
-    $self->read;
-
-    my $names = $self->{' PARENT'}->{'name'};
-    $names->read;
-    
-    my $features = $self->{'features'};
-    my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features;
-    my $featureName = $names->{'strings'}[$featureEntry->{'name'}][1][0]{0};
-    my $settingName = $featureEntry->{'exclusive'}
-            ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][1][0]{0}
-            : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][1][0]{0}
-                . (($setting & 1) == 0 ? " On" : " Off");
-
-    ($featureName, $settingName);
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Feat;
+
+=head1 NAME
+
+Font::TTF::Feat - Font Features
+
+=head1 DESCRIPTION
+
+=head1 INSTANCE VARIABLES
+
+=over 4
+
+=item version
+
+=item features
+
+An array of hashes of the following form
+
+=over 8
+
+=item feature
+
+feature id number
+
+=item name
+
+name index in name table
+
+=item exclusive
+
+exclusive flag
+
+=item settings
+
+hash of setting number against name string index
+
+=back
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+
+use Font::TTF::Utils;
+
+require Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the features from the TTF file into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($featureCount, $features);
+
+    $self->SUPER::read_dat or return $self;
+
+    ($self->{'version'}, $featureCount) = TTF_Unpack("fS", $self->{' dat'});
+
+    $features = [];
+    foreach (1 .. $featureCount) {
+        my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex)
+                = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12));
+        push @$features,
+            {
+                'feature'    => $feature,
+                'name'        => $nameIndex,
+                'exclusive'    => (($featureFlags & 0x8000) != 0),
+                'settings'    => { TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)) }
+            };
+    }
+    $self->{'features'} = $features;
+    
+    delete $self->{' dat'}; # no longer needed, and may become obsolete
+    
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the features to a TTF file
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($features, $numFeatures, $settings, $featuresData, $settingsData);
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $features = $self->{'features'};
+    $numFeatures = @$features;
+
+    foreach (@$features) {
+        $settings = $_->{'settings'};
+        $featuresData .= TTF_Pack("SSLSS",
+                                    $_->{'feature'},
+                                    scalar keys %$settings,
+                                    12 + 12 * $numFeatures + length $settingsData,
+                                    ($_->{'exclusive'} ? 0x8000 : 0x0000),
+                                    $_->{'name'});
+        foreach (sort {$a <=> $b} keys %$settings) {
+            $settingsData .= TTF_Pack("SS", $_, $settings->{$_});
+        }
+    }
+
+    $fh->print(TTF_Pack("fSSL", $self->{'version'}, $numFeatures, 0, 0));
+    $fh->print($featuresData);
+    $fh->print($settingsData);
+
+    $self;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    my ($names, $features, $settings);
+
+    $self->read;
+
+    $names = $self->{' PARENT'}->{'name'};
+    $names->read;
+
+    $fh = 'STDOUT' unless defined $fh;
+
+    $features = $self->{'features'};
+    foreach (@$features) {
+        $fh->printf("Feature %d, %s, name %d # '%s'\n",
+                    $_->{'feature'},
+                    ($_->{'exclusive'} ? "exclusive" : "additive"),
+                    $_->{'name'},
+                    $names->{'strings'}[$_->{'name'}][1][0]{0});
+        $settings = $_->{'settings'};
+        foreach (sort { $a <=> $b } keys %$settings) {
+            $fh->printf("\tSetting %d, name %d # '%s'\n",
+                        $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][1][0]{0});
+        }
+    }
+    
+    $self;
+}
+
+sub settingName
+{
+    my ($self, $feature, $setting) = @_;
+
+    $self->read;
+
+    my $names = $self->{' PARENT'}->{'name'};
+    $names->read;
+    
+    my $features = $self->{'features'};
+    my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features;
+    my $featureName = $names->{'strings'}[$featureEntry->{'name'}][1][0]{0};
+    my $settingName = $featureEntry->{'exclusive'}
+            ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][1][0]{0}
+            : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][1][0]{0}
+                . (($setting & 1) == 0 ? " On" : " Off");
+
+    ($featureName, $settingName);
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fmtx.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fmtx.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fmtx.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,108 +1,108 @@
-package Font::TTF::Fmtx;
-
-=head1 NAME
-
-Font::TTF::Fmtx - Font Metrics table
-
-=head1 DESCRIPTION
-
-This is a simple table with just standards specified instance variables
-
-=head1 INSTANCE VARIABLES
-
-    version
-    glyphIndex
-    horizontalBefore
-    horizontalAfter
-    horizontalCaretHead
-    horizontalCaretBase
-    verticalBefore
-    verticalAfter
-    verticalCaretHead
-    verticalCaretBase
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-
-require Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'version' => 'f',
-    'glyphIndex' => 'L',
-    'horizontalBefore' => 'c',
-    'horizontalAfter' => 'c',
-    'horizontalCaretHead' => 'c',
-    'horizontalCaretBase' => 'c',
-    'verticalBefore' => 'c',
-    'verticalAfter' => 'c',
-    'verticalCaretHead' => 'c',
-    'verticalCaretBase' => 'c');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory as instance variables
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read or return $self;
-    init unless defined $fields{'glyphIndex'};
-    $self->{' INFILE'}->read($dat, 16);
-
-    TTF_Read_Fields($self, $dat, \%fields);
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $fh->print(TTF_Out_Fields($self, \%fields, 16));
-    $self;
-}
-
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
+package Font::TTF::Fmtx;
+
+=head1 NAME
+
+Font::TTF::Fmtx - Font Metrics table
+
+=head1 DESCRIPTION
+
+This is a simple table with just standards specified instance variables
+
+=head1 INSTANCE VARIABLES
+
+    version
+    glyphIndex
+    horizontalBefore
+    horizontalAfter
+    horizontalCaretHead
+    horizontalCaretBase
+    verticalBefore
+    verticalAfter
+    verticalCaretHead
+    verticalCaretBase
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+
+require Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'version' => 'f',
+    'glyphIndex' => 'L',
+    'horizontalBefore' => 'c',
+    'horizontalAfter' => 'c',
+    'horizontalCaretHead' => 'c',
+    'horizontalCaretBase' => 'c',
+    'verticalBefore' => 'c',
+    'verticalAfter' => 'c',
+    'verticalCaretHead' => 'c',
+    'verticalCaretBase' => 'c');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory as instance variables
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read or return $self;
+    init unless defined $fields{'glyphIndex'};
+    $self->{' INFILE'}->read($dat, 16);
+
+    TTF_Read_Fields($self, $dat, \%fields);
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $fh->print(TTF_Out_Fields($self, \%fields, 16));
+    $self;
+}
+
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Font.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Font.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Font.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,747 +1,748 @@
-package Font::TTF::Font;
-
-=head1 NAME
-
-Font::TTF::Font - Memory representation of a font
-
-=head1 SYNOPSIS
-
-Here is the regression test (you provide your own font). Run it once and then
-again on the output of the first run. There should be no differences between
-the outputs of the two runs.
-
-    $f = Font::TTF::Font->open($ARGV[0]);
-
-    # force a read of all the tables
-    $f->tables_do(sub { $_[0]->read; });
-
-    # force read of all glyphs (use read_dat to use lots of memory!)
-    # $f->{'loca'}->glyphs_do(sub { $_[0]->read; });
-    $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; });
-    # NB. no need to $g->update since $f->{'glyf'}->out will do it for us
-
-    $f->out($ARGV[1]);
-    $f->release;            # clear up memory forcefully!
-
-=head1 DESCRIPTION
-
-A Truetype font consists of a header containing a directory of tables which
-constitute the rest of the file. This class holds that header and directory and
-also creates objects of the appropriate type for each table within the font.
-Note that it does not read each table into memory, but creates a short reference
-which can be read using the form:
-
-    $f->{$tablename}->read;
-
-Classes are included that support many of the different TrueType tables. For
-those for which no special code exists, the table type C<table> is used, which
-defaults to L<Font::TTF::Table>. The current tables which are supported are:
-
-    table       Font::TTF::Table      - for unknown tables
-    GDEF        Font::TTF::GDEF
-    GPOS        Font::TTF::GPOS
-    GSUB        Font::TTF::GSUB
-    LTSH        Font::TTF::LTSH
-    OS/2        Font::TTF::OS_2
-    PCLT        Font::TTF::PCLT
-    bsln        Font::TTF::Bsln
-    cmap        Font::TTF::Cmap       - see also Font::TTF::OldCmap
-    cvt         Font::TTF::Cvt_
-    fdsc        Font::TTF::Fdsc
-    feat        Font::TTF::Feat
-    fmtx        Font::TTF::Fmtx
-    fpgm        Font::TTF::Fpgm
-    glyf        Font::TTF::Glyf       - see also Font::TTF::Glyph
-    hdmx        Font::TTF::Hdmx
-    head        Font::TTF::Head
-    hhea        Font::TTF::Hhea
-    hmtx        Font::TTF::Hmtx
-    kern        Font::TTF::Kern       - see alternative Font::TTF::AATKern
-    loca        Font::TTF::Loca
-    maxp        Font::TTF::Maxp
-    mort        Font::TTF::Mort       - see also Font::TTF::OldMort
-    name        Font::TTF::Name
-    post        Font::TTF::Post
-    prep        Font::TTF::Prep
-    prop        Font::TTF::Prop
-    vhea        Font::TTF::Vhea
-    vmtx        Font::TTF::Vmtx
-
-Links are:
-
-L<Font::TTF::Table> L<Font::TTF::GDEF> L<Font::TTF::GPOS> L<Font::TTF::GSUB> L<Font::TTF::LTSH>
-L<Font::TTF::OS_2> L<Font::TTF::PCLT> L<Font::TTF::Bsln> L<Font::TTF::Cmap> L<Font::TTF::Cvt_>
-L<Font::TTF::Fdsc> L<Font::TTF::Feat> L<Font::TTF::Fmtx> L<Font::TTF::Fpgm> L<Font::TTF::Glyf>
-L<Font::TTF::Hdmx> L<Font::TTF::Head> L<Font::TTF::Hhea> L<Font::TTF::Hmtx> L<Font::TTF::Kern>
-L<Font::TTF::Loca> L<Font::TTF::Maxp> L<Font::TTF::Mort> L<Font::TTF::Name> L<Font::TTF::Post>
-L<Font::TTF::Prep> L<Font::TTF::Prop> L<Font::TTF::Vhea> L<Font::TTF::Vmtx> L<Font::TTF::OldCmap>
-L<Font::TTF::Glyph> L<Font::TTF::AATKern> L<Font::TTF::OldMort>
-
-
-=head1 INSTANCE VARIABLES
-
-Instance variables begin with a space (and have lengths greater than the 4
-characters which make up table names).
-
-=over
-
-=item nocsum
-
-This is used during output to disable the creation of the file checksum in the
-head table. For example, during DSIG table creation, this flag will be set to
-ensure that the file checksum is left at zero.
-
-=item fname (R)
-
-Contains the filename of the font which this object was read from.
-
-=item INFILE (P)
-
-The file handle which reflects the source file for this font.
-
-=item OFFSET (P)
-
-Contains the offset from the beginning of the read file of this particular
-font directory, thus providing support for TrueType Collections.
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use IO::File;
-
-use strict;
-use vars qw(%tables $VERSION $dumper);
-use Symbol();
-
-require 5.004;
-
-$VERSION = 0.34;    # MJPH      22-MAY-2003     Update PSNames to latest AGL
-# $VERSION = 0.33;    # MJPH       9-OCT-2002     Support CFF OpenType (just by version=='OTTO'?!)
-# $VERSION = 0.32;    # MJPH       2-OCT-2002     Bug fixes to TTFBuilder, new methods and some
-#                                                 extension table support in Ttopen and Coverage
-# $VERSION = 0.31;    # MJPH       1-JUL-2002     fix read format 12 cmap (bart at cs.pdx.edu) 
-#                                                 improve surrogate support in ttfremap
-#                                                 fix return warn to return warn,undef
-#                                                 ensure correct indexToLocFormat
-# $VERSION = 0.30;    # MJPH      28-MAY-2002     add updated release
-# $VERSION = 0.29;    # MJPH       9-APR-2002     update ttfbuilder, sort out surrogates
-# $VERSION = 0.28;    # MJPH      13-MAR-2002     update ttfbuilder, add Font::TTF::Cmap::ms_enc()
-# $VERSION = 0.27;    # MJPH       6-FEB-2002     update ttfbuilder, support no fpgm, no more __DATA__
-# $VERSION = 0.26;    # MJPH      19-SEP-2001     Update ttfbuilder
-# $VERSION = 0.25;    # MJPH      18-SEP-2001     problems in update of head
-# $VERSION = 0.24;    # MJPH       1-AUG-2001     Sort out update
-# $VERSION = 0.23;    # GST       30-MAY-2001     Memory leak fixed
-# $VERSION = 0.22;    # MJPH      09-APR-2001     Ensure all of AAT stuff included
-# $VERSION = 0.21;    # MJPH      23-MAR-2001     Improve Opentype support
-# $VERSION = 0.20;    # MJPH      13-JAN-2001     Add XML output and some of XML input, AAT & OT tables
-# $VERSION = 0.19;    # MJPH      29-SEP-2000     Add cmap::is_unicode, debug makefile.pl
-# $VERSION = 0.18;    # MJPH      21-JUL-2000     Debug Utils::TTF_bininfo
-# $VERSION = 0.17;    # MJPH      16-JUN-2000     Add utf8 support to names
-# $VERSION = 0.16;    # MJPH      26-APR-2000     Mark read tables as read, tidy up POD
-# $VERSION = 0.15;    # MJPH       5-FEB-2000     Ensure right versions released
-# $VERSION = 0.14;    # MJPH      11-SEP-1999     Sort out Unixisms, agian!
-# $VERSION = 0.13;    # MJPH       9-SEP-1999     Add empty, debug update_bbox
-# $VERSION = 0.12;    # MJPH      22-JUL-1999     Add update_bbox
-# $VERSION = 0.11;    # MJPH       7-JUL-1999     Don't store empties in cmaps
-# $VERSION = 0.10;    # MJPH      21-JUN-1999     Use IO::File
-# $VERSION = 0.09;    # MJPH       9-JUN-1999     Add 5.004 require, minor tweeks in cmap
-# $VERSION = 0.08;    # MJPH      19-MAY-1999     Sort out line endings for Unix
-# $VERSION = 0.07;    # MJPH      28-APR-1999     Get the regression tests to work
-# $VERSION = 0.06;    # MJPH      26-APR-1999     Start to add to CVS, correct MANIFEST.SKIP
-# $VERSION = 0.05;    # MJPH      13-APR-1999     See changes for 0.05
-# $VERSION = 0.04;    # MJPH      13-MAR-1999     Tidy up Tarball
-# $VERSION = 0.03;    # MJPH       9-MAR-1999     Move to Font::TTF for CPAN
-# $VERSION = 0.02;    # MJPH      12-FEB-1999     Add support for ' nocsum' for DSIGS
-# $VERSION = 0.0001;
-
-%tables = (
-        'table' => 'Font::TTF::Table',
-        'GDEF' => 'Font::TTF::GDEF',
-        'GPOS' => 'Font::TTF::GPOS',
-        'GSUB' => 'Font::TTF::GSUB',
-        'LTSH' => 'Font::TTF::LTSH',
-        'OS/2' => 'Font::TTF::OS_2',
-        'PCLT' => 'Font::TTF::PCLT',
-        'bsln' => 'Font::TTF::Bsln',
-        'cmap' => 'Font::TTF::Cmap',
-        'cvt ' => 'Font::TTF::Cvt_',
-        'fdsc' => 'Font::TTF::Fdsc',
-        'feat' => 'Font::TTF::Feat',
-        'fmtx' => 'Font::TTF::Fmtx',
-        'fpgm' => 'Font::TTF::Fpgm',
-        'glyf' => 'Font::TTF::Glyf',
-        'hdmx' => 'Font::TTF::Hdmx',
-        'head' => 'Font::TTF::Head',
-        'hhea' => 'Font::TTF::Hhea',
-        'hmtx' => 'Font::TTF::Hmtx',
-        'kern' => 'Font::TTF::Kern',
-        'loca' => 'Font::TTF::Loca',
-        'maxp' => 'Font::TTF::Maxp',
-        'mort' => 'Font::TTF::Mort',
-        'name' => 'Font::TTF::Name',
-        'post' => 'Font::TTF::Post',
-        'prep' => 'Font::TTF::Prep',
-        'prop' => 'Font::TTF::Prop',
-        'vhea' => 'Font::TTF::Vhea',
-        'vmtx' => 'Font::TTF::Vmtx',
-          );
-
-# This is special code because I am fed up of every time I x a table in the debugger
-# I get the whole font printed. Thus substitutes my 3 line change to dumpvar into
-# the debugger. Clunky, but nice. You are welcome to a copy if you want one.
-          
-BEGIN {
-    my ($p);
-
-    foreach $p (@INC)
-    {
-        if (-f "$p/mydumpvar.pl")
-        {
-            $dumper = 'mydumpvar.pl';
-            last;
-        }
-    }
-    $dumper ||= 'dumpvar.pl';
-}
-
-sub main::dumpValue
-{ do $dumper; &main::dumpValue; }
-    
-
-=head2 Font::TTF::Font->AddTable($tablename, $class)
-
-Adds the given class to be used when representing the given table name. It also
-'requires' the class for you.
-
-=cut
-
-sub AddTable
-{
-    my ($class, $table, $useclass) = @_;
-
-    $tables{$table} = $useclass;
-#    $useclass =~ s|::|/|oig;
-#    require "$useclass.pm";
-}
-
-
-=head2 Font::TTF::Font->Init
-
-For those people who like making fonts without reading them. This subroutine
-will require all the table code for the various table types for you. Not
-needed if using Font::TTF::Font::read before using a table.
-
-=cut
-
-sub Init
-{
-    my ($class) = @_;
-    my ($t);
-
-    foreach $t (keys %tables)
-    {
-        $t =~ s|::|/|oig;
-        require "$t.pm";
-    }
-}
-
-=head2 Font::TTF::Font->new(%props)
-
-Creates a new font object and initialises with the given properties. This is
-primarily for use when a TTF is embedded somewhere. Notice that the properties
-are automatically preceded by a space when inserted into the object. This is in
-order that fields do not clash with tables.
-
-=cut
-
-sub new
-{
-    my ($class, %props) = @_;
-    my ($self) = {};
-
-    bless $self, $class;
-
-    foreach (keys %props)
-    { $self->{" $_"} = $props{$_}; }
-    $self;
-}
-
-
-=head2 Font::TTF::Font->open($fname)
-
-Reads the header and directory for the given font file and creates appropriate
-objects for each table in the font.
-
-=cut
-
-sub open
-{
-    my ($class, $fname) = @_;
-    my ($fh);
-    my ($self) = {};
-    
-    unless (ref($fname))
-    {
-        $fh = IO::File->new($fname) or return undef;
-        binmode $fh;
-    } else
-    { $fh = $fname; }
-
-    $self->{' INFILE'} = $fh;
-    $self->{' fname'} = $fname;
-    $self->{' OFFSET'} = 0;
-    bless $self, $class;
-    
-    $self->read;
-}
-
-=head2 $f->read
-
-Reads a Truetype font directory starting from the current location in the file.
-This has been separated from the C<open> function to allow support for embedded
-TTFs for example in TTCs. Also reads the C<head> and C<maxp> tables immediately.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t);
-
-    $fh->seek($self->{' OFFSET'}, 0);
-    $fh->read($dat, 12);
-    ($ver, $dir_num) = unpack("Nn", $dat);
-    $ver == 1 << 16 || $ver == unpack('N', 'OTTO') || $ver == 0x74727565 or return undef;  # support Mac sfnts
-    
-    for ($i = 0; $i < $dir_num; $i++)
-    {
-        $fh->read($dat, 16) || die "Reading table entry";
-        ($name, $check, $off, $len) = unpack("a4NNN", $dat);
-        $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) && next
-                if (defined $self->{' PARENT'});
-        $type = $tables{$name} || 'Font::TTF::Table';
-        $t = $type;
-        if ($^O eq "MacOS")
-        { $t =~ s/^|::/:/oig; }
-        else
-        { $t =~ s|::|/|oig; }
-        require "$t.pm";
-        $self->{$name} = $type->new(PARENT  => $self,
-                                    NAME    => $name,
-                                    INFILE  => $fh,
-                                    OFFSET  => $off,
-                                    LENGTH  => $len,
-                                    CSUM    => $check);
-    }
-    
-    foreach $t ('head', 'maxp')
-    { $self->{$t}->read if defined $self->{$t}; }
-
-    $self;
-}
-
-
-=head2 $f->out($fname [, @tablelist])
-
-Writes a TTF file consisting of the tables in tablelist. The list is checked to
-ensure that only tables that exist are output. (This means that you can't have
-non table information stored in the font object with key length of exactly 4)
-
-In many cases the user simply wants to output all the tables in alphabetical order.
-This can be done by not including a @tablelist, in which case the subroutine will
-output all the defined tables in the font in alphabetical order.
-
-Returns $f on success and undef on failure, including warnings.
-
-All output files must include the C<head> table.
-
-=cut
-
-sub out
-{
-    my ($self, $fname, @tlist) = @_;
-    my ($fh);
-    my ($dat, $numTables, $sRange, $eSel);
-    my (%dir, $k, $mloc, $count);
-    my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift);
-
-    unless (ref($fname))
-    {
-        $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef;
-        binmode $fh;
-    } else
-    { $fh = $fname; }
-    
-    $self->{' oname'} = $fname;
-    $self->{' outfile'} = $fh;
-
-    if ($self->{' wantsig'})
-    {
-        $self->{' nocsum'} = 1;
-#        $self->{'head'}{'checkSumAdjustment'} = 0;
-        $self->{' tempDSIG'} = $self->{'DSIG'};
-        $self->{' tempcsum'} = $self->{'head'}{' CSUM'};
-        delete $self->{'DSIG'};
-        @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}}
-            grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0);
-    }
-    elsif ($#tlist < 0)
-    { @tlist = sort keys %$self; }
-    
-    @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
-    $numTables = $#tlist + 1;
-    $numTables++ if ($self->{' wantsig'});
-    
-    ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16);
-    $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift);
-    $fh->print($dat);
-    $msum = unpack("%32N*", $dat);
-
-# reserve place holders for each directory entry
-    foreach $k (@tlist)
-    {
-        $dir{$k} = pack("A4NNN", $k, 0, 0, 0);
-        $fh->print($dir{$k});
-    }
-
-    $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
-
-    $loc = $fh->tell();
-    if ($loc & 3)
-    {
-        $fh->print(substr("\000" x 4, $loc & 3));
-        $loc += 4 - ($loc & 3);
-    }
-
-    foreach $k (@tlist)
-    {
-        $oldloc = $loc;
-        $self->{$k}->out($fh);
-        $loc = $fh->tell();
-        $len = $loc - $oldloc;
-        if ($loc & 3)
-        {
-            $fh->print(substr("\000" x 4, $loc & 3));
-            $loc += 4 - ($loc & 3);
-        }
-        $fh->seek($oldloc, 0);
-        $csum = 0; $mloc = $loc;
-        while ($mloc > $oldloc)
-        {
-            $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc;
-            $fh->read($dat, $count);
-            $csum += unpack("%32N*", $dat);
-# this line ensures $csum stays within 32 bit bounds, clipping as necessary
-            if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
-            $mloc -= $count;
-        }
-        $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len);
-        $msum += $csum + unpack("%32N*", $dir{$k});
-        if ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; }
-        $fh->seek($loc, 0);
-    }
-
-    unless ($self->{' nocsum'})             # assuming we want a file checksum
-    {
-# Now we need to sort out the head table's checksum
-        if (!defined $dir{'head'})
-        {                                   # you have to have a head table
-            $fh->close();
-            return warn("No 'head' table to output in $fname"), undef;
-        }
-        ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
-        $fh->seek($loc + 8, 0);
-        $fh->read($dat, 4);
-        $lsum = unpack("N", $dat);
-        if ($lsum != 0)
-        {
-            $csum -= $lsum;
-            if ($csum < 0) { $csum += 0xffffffff; $csum++; }
-            $msum -= $lsum * 2;                     # twice (in head and in csum)
-            while ($msum < 0) { $msum += 0xffffffff; $msum++; }
-        }
-        $lsum = 0xB1B0AFBA - $msum;
-        $fh->seek($loc + 8, 0);
-        $fh->print(pack("N", $lsum));
-        $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len);
-    } elsif ($self->{' wantsig'})
-    {
-        if (!defined $dir{'head'})
-        {                                   # you have to have a head table
-            $fh->close();
-            return warn("No 'head' table to output in $fname"), undef;
-        }
-        ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
-        $fh->seek($loc + 8, 0);
-        $fh->print(pack("N", 0));
-#        $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len);
-    }
-
-# Now we can output the directory again
-    if ($self->{' wantsig'})
-    { @tlist = sort @tlist; }
-    $fh->seek(12, 0);
-    foreach $k (@tlist)
-    { $fh->print($dir{$k}); }
-    $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
-    $fh->close();
-    $self;
-}
-
-
-=head2 $f->out_xml($filename [, @tables])
-
-Outputs the font in XML format
-
-=cut
-
-sub out_xml
-{
-    my ($self, $fname, @tlist) = @_;
-    my ($fh, $context, $numTables, $k);
-
-    $context->{'indent'} = ' ' x 4;
-
-    unless (ref($fname))
-    {
-        $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef;
-        binmode $fh;
-    } else
-    { $fh = $fname; }
-
-    unless (scalar @tlist > 0)
-    {
-        @tlist = sort keys %$self;
-        @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
-    }
-    $numTables = $#tlist + 1;
-
-    $context->{'fh'} = $fh;
-    $fh->print("<?xml version='1.0' encoding='UTF-8'?>\n");
-    $fh->print("<font tables='$numTables'>\n\n");
-    
-    foreach $k (@tlist)
-    {
-        $fh->print("<table name='$k'>\n");
-        $self->{$k}->out_xml($context, $context->{'indent'});
-        $fh->print("</table>\n");
-    }
-
-    $fh->print("</font>\n");
-    $fh->close;
-    $self;
-}
-
-
-=head2 $f->XML_start($context, $tag, %attrs)
-
-Handles start messages from the XML parser. Of particular interest to us are <font> and
-<table>.
-
-=cut
-
-sub XML_start
-{
-    my ($self, $context, $tag, %attrs) = @_;
-    my ($name, $type, $t);
-
-    if ($tag eq 'font')
-    { $context->{'tree'}[-1] = $self; }
-    elsif ($tag eq 'table')
-    {
-        $name = $attrs{'name'};
-        unless (defined $self->{$name})
-        {
-            $type = $tables{$name} || 'Font::TTF::Table';
-            $t = $type;
-            if ($^O eq "MacOS")
-            { $t =~ s/^|::/:/oig; }
-            else
-            { $t =~ s|::|/|oig; }
-            require "$t.pm";
-            $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1);
-        }
-        $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name});
-    }
-    $context;
-}
-
-
-sub XML_end
-{
-    my ($self) = @_;
-    my ($context, $tag, %attrs) = @_;
-    my ($i);
-
-    return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca');
-    if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'})
-    {
-        for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++)
-        { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; }
-        $context->{'glyphs'} = $self->{'loca'}{'glyphs'};
-    }
-    return undef;
-}
-
-=head2 $f->update
-
-Sends update to all the tables in the font and then resets all the isDirty
-flags on each table. The data structure in now consistent as a font (we hope).
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    
-    $self->tables_do(sub { $_[0]->update; });
-
-    $self;
-}
-
-=head2 $f->dirty
-
-Dirties all the tables in the font
-
-=cut
-
-sub dirty
-{ $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; }
-
-=head2 $f->tables_do(&func)
-
-Calls &func for each table in the font. Calls the table in alphabetical sort
-order as per the order in the directory:
-
-    &func($table, $name);
-
-=cut
-
-sub tables_do
-{
-    my ($self, $func) = @_;
-    my ($t);
-
-    foreach $t (sort grep {length($_) == 4} keys %$self)
-    { &$func($self->{$t}, $t); }
-    $self;
-}
-
-
-=head2 $f->release
-
-Releases ALL of the memory used by the TTF font and all of its component
-objects.  After calling this method, do B<NOT> expect to have anything left in
-the C<Font::TTF::Font> object.
-
-B<NOTE>, that it is important that you call this method on any
-C<Font::TTF::Font> object when you wish to destruct it and free up its memory.
-Internally, we track things in a structure that can result in circular
-references, and without calling 'C<release()>' these will not properly get
-cleaned up by Perl.  Once you've called this method, though, don't expect to be
-able to do anything else with the C<Font::TTF::Font> object; it'll have B<no>
-internal state whatsoever.
-
-B<Developer note:> As part of the brute-force cleanup done here, this method
-will throw a warning message whenever unexpected key values are found within
-the C<Font::TTF::Font> object.  This is done to help ensure that any unexpected
-and unfreed values are brought to your attention so that you can bug us to keep
-the module updated properly; otherwise the potential for memory leaks due to
-dangling circular references will exist.  
-
-=cut
-
-sub release
-{
-    my ($self) = @_;
-
-# delete stuff that we know we can, here
-
-    my @tofree = map { delete $self->{$_} } keys %{$self};
-
-    while (my $item = shift @tofree)
-    {
-        my $ref = ref($item);
-        if (UNIVERSAL::can($item, 'release'))
-        { $item->release(); }
-        elsif ($ref eq 'ARRAY')
-        { push( @tofree, @{$item} ); }
-        elsif (UNIVERSAL::isa($ref, 'HASH'))
-        { release($item); }
-    }
-
-# check that everything has gone - it better had!
-    foreach my $key (keys %{$self})
-    { warn ref($self) . " still has '$key' key left after release.\n"; }
-}
-
-1;
-
-=head1 BUGS
-
-Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope.
-The parts of the code which haven't been implemented yet are:
-
-=over 4
-
-=item Post
-
-Version 4 format types are not supported yet.
-
-=item Cmap
-
-Format type 2 (MBCS) has not been implemented yet and therefore may cause
-somewhat spurious results for this table type.
-
-=item Kern
-
-Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come).
-
-=item TTC
-
-The current Font::TTF::Font::out method does not support the writing of TrueType
-Collections.
-
-=back
-
-In addition there are weaknesses or features of this module library
-
-=over 4
-
-=item *
-
-There is very little (or no) error reporting. This means that if you have
-garbled data or garbled data structures, then you are liable to generate duff
-fonts.
-
-=item *
-
-The exposing of the internal data structures everywhere means that doing
-radical re-structuring is almost impossible. But it stop the code from becoming
-ridiculously large.
-
-=back
-
-Apart from these, I try to keep the code in a state of "no known bugs", which
-given the amount of testing this code has had, is not a guarantee of high
-quality, yet.
-
-For more details see the appropriate class files.
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org
-
-Copyright Martin Hosken 1998.
-
-No warranty or expression of effectiveness, least of all regarding anyone's
-safety, is implied in this software or documentation.
-
-=head2 Licensing
-
-The Perl TTF module is licensed under the Perl Artistic License.
-
+package Font::TTF::Font;
+
+=head1 NAME
+
+Font::TTF::Font - Memory representation of a font
+
+=head1 SYNOPSIS
+
+Here is the regression test (you provide your own font). Run it once and then
+again on the output of the first run. There should be no differences between
+the outputs of the two runs.
+
+    $f = Font::TTF::Font->open($ARGV[0]);
+
+    # force a read of all the tables
+    $f->tables_do(sub { $_[0]->read; });
+
+    # force read of all glyphs (use read_dat to use lots of memory!)
+    # $f->{'loca'}->glyphs_do(sub { $_[0]->read; });
+    $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; });
+    # NB. no need to $g->update since $f->{'glyf'}->out will do it for us
+
+    $f->out($ARGV[1]);
+    $f->release;            # clear up memory forcefully!
+
+=head1 DESCRIPTION
+
+A Truetype font consists of a header containing a directory of tables which
+constitute the rest of the file. This class holds that header and directory and
+also creates objects of the appropriate type for each table within the font.
+Note that it does not read each table into memory, but creates a short reference
+which can be read using the form:
+
+    $f->{$tablename}->read;
+
+Classes are included that support many of the different TrueType tables. For
+those for which no special code exists, the table type C<table> is used, which
+defaults to L<Font::TTF::Table>. The current tables which are supported are:
+
+    table       Font::TTF::Table      - for unknown tables
+    GDEF        Font::TTF::GDEF
+    GPOS        Font::TTF::GPOS
+    GSUB        Font::TTF::GSUB
+    LTSH        Font::TTF::LTSH
+    OS/2        Font::TTF::OS_2
+    PCLT        Font::TTF::PCLT
+    bsln        Font::TTF::Bsln
+    cmap        Font::TTF::Cmap       - see also Font::TTF::OldCmap
+    cvt         Font::TTF::Cvt_
+    fdsc        Font::TTF::Fdsc
+    feat        Font::TTF::Feat
+    fmtx        Font::TTF::Fmtx
+    fpgm        Font::TTF::Fpgm
+    glyf        Font::TTF::Glyf       - see also Font::TTF::Glyph
+    hdmx        Font::TTF::Hdmx
+    head        Font::TTF::Head
+    hhea        Font::TTF::Hhea
+    hmtx        Font::TTF::Hmtx
+    kern        Font::TTF::Kern       - see alternative Font::TTF::AATKern
+    loca        Font::TTF::Loca
+    maxp        Font::TTF::Maxp
+    mort        Font::TTF::Mort       - see also Font::TTF::OldMort
+    name        Font::TTF::Name
+    post        Font::TTF::Post
+    prep        Font::TTF::Prep
+    prop        Font::TTF::Prop
+    vhea        Font::TTF::Vhea
+    vmtx        Font::TTF::Vmtx
+
+Links are:
+
+L<Font::TTF::Table> L<Font::TTF::GDEF> L<Font::TTF::GPOS> L<Font::TTF::GSUB> L<Font::TTF::LTSH>
+L<Font::TTF::OS_2> L<Font::TTF::PCLT> L<Font::TTF::Bsln> L<Font::TTF::Cmap> L<Font::TTF::Cvt_>
+L<Font::TTF::Fdsc> L<Font::TTF::Feat> L<Font::TTF::Fmtx> L<Font::TTF::Fpgm> L<Font::TTF::Glyf>
+L<Font::TTF::Hdmx> L<Font::TTF::Head> L<Font::TTF::Hhea> L<Font::TTF::Hmtx> L<Font::TTF::Kern>
+L<Font::TTF::Loca> L<Font::TTF::Maxp> L<Font::TTF::Mort> L<Font::TTF::Name> L<Font::TTF::Post>
+L<Font::TTF::Prep> L<Font::TTF::Prop> L<Font::TTF::Vhea> L<Font::TTF::Vmtx> L<Font::TTF::OldCmap>
+L<Font::TTF::Glyph> L<Font::TTF::AATKern> L<Font::TTF::OldMort>
+
+
+=head1 INSTANCE VARIABLES
+
+Instance variables begin with a space (and have lengths greater than the 4
+characters which make up table names).
+
+=over
+
+=item nocsum
+
+This is used during output to disable the creation of the file checksum in the
+head table. For example, during DSIG table creation, this flag will be set to
+ensure that the file checksum is left at zero.
+
+=item fname (R)
+
+Contains the filename of the font which this object was read from.
+
+=item INFILE (P)
+
+The file handle which reflects the source file for this font.
+
+=item OFFSET (P)
+
+Contains the offset from the beginning of the read file of this particular
+font directory, thus providing support for TrueType Collections.
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use IO::File;
+
+use strict;
+use vars qw(%tables $VERSION $dumper);
+use Symbol();
+
+require 5.004;
+
+$VERSION = 0.35;    # MJPH       4-MAY-2004     Various fixes to OpenType stuff, separate off scripts
+# $VERSION = 0.34;    # MJPH      22-MAY-2003     Update PSNames to latest AGL
+# $VERSION = 0.33;    # MJPH       9-OCT-2002     Support CFF OpenType (just by version=='OTTO'?!)
+# $VERSION = 0.32;    # MJPH       2-OCT-2002     Bug fixes to TTFBuilder, new methods and some
+#                                                 extension table support in Ttopen and Coverage
+# $VERSION = 0.31;    # MJPH       1-JUL-2002     fix read format 12 cmap (bart at cs.pdx.edu) 
+#                                                 improve surrogate support in ttfremap
+#                                                 fix return warn to return warn,undef
+#                                                 ensure correct indexToLocFormat
+# $VERSION = 0.30;    # MJPH      28-MAY-2002     add updated release
+# $VERSION = 0.29;    # MJPH       9-APR-2002     update ttfbuilder, sort out surrogates
+# $VERSION = 0.28;    # MJPH      13-MAR-2002     update ttfbuilder, add Font::TTF::Cmap::ms_enc()
+# $VERSION = 0.27;    # MJPH       6-FEB-2002     update ttfbuilder, support no fpgm, no more __DATA__
+# $VERSION = 0.26;    # MJPH      19-SEP-2001     Update ttfbuilder
+# $VERSION = 0.25;    # MJPH      18-SEP-2001     problems in update of head
+# $VERSION = 0.24;    # MJPH       1-AUG-2001     Sort out update
+# $VERSION = 0.23;    # GST       30-MAY-2001     Memory leak fixed
+# $VERSION = 0.22;    # MJPH      09-APR-2001     Ensure all of AAT stuff included
+# $VERSION = 0.21;    # MJPH      23-MAR-2001     Improve Opentype support
+# $VERSION = 0.20;    # MJPH      13-JAN-2001     Add XML output and some of XML input, AAT & OT tables
+# $VERSION = 0.19;    # MJPH      29-SEP-2000     Add cmap::is_unicode, debug makefile.pl
+# $VERSION = 0.18;    # MJPH      21-JUL-2000     Debug Utils::TTF_bininfo
+# $VERSION = 0.17;    # MJPH      16-JUN-2000     Add utf8 support to names
+# $VERSION = 0.16;    # MJPH      26-APR-2000     Mark read tables as read, tidy up POD
+# $VERSION = 0.15;    # MJPH       5-FEB-2000     Ensure right versions released
+# $VERSION = 0.14;    # MJPH      11-SEP-1999     Sort out Unixisms, agian!
+# $VERSION = 0.13;    # MJPH       9-SEP-1999     Add empty, debug update_bbox
+# $VERSION = 0.12;    # MJPH      22-JUL-1999     Add update_bbox
+# $VERSION = 0.11;    # MJPH       7-JUL-1999     Don't store empties in cmaps
+# $VERSION = 0.10;    # MJPH      21-JUN-1999     Use IO::File
+# $VERSION = 0.09;    # MJPH       9-JUN-1999     Add 5.004 require, minor tweeks in cmap
+# $VERSION = 0.08;    # MJPH      19-MAY-1999     Sort out line endings for Unix
+# $VERSION = 0.07;    # MJPH      28-APR-1999     Get the regression tests to work
+# $VERSION = 0.06;    # MJPH      26-APR-1999     Start to add to CVS, correct MANIFEST.SKIP
+# $VERSION = 0.05;    # MJPH      13-APR-1999     See changes for 0.05
+# $VERSION = 0.04;    # MJPH      13-MAR-1999     Tidy up Tarball
+# $VERSION = 0.03;    # MJPH       9-MAR-1999     Move to Font::TTF for CPAN
+# $VERSION = 0.02;    # MJPH      12-FEB-1999     Add support for ' nocsum' for DSIGS
+# $VERSION = 0.0001;
+
+%tables = (
+        'table' => 'Font::TTF::Table',
+        'GDEF' => 'Font::TTF::GDEF',
+        'GPOS' => 'Font::TTF::GPOS',
+        'GSUB' => 'Font::TTF::GSUB',
+        'LTSH' => 'Font::TTF::LTSH',
+        'OS/2' => 'Font::TTF::OS_2',
+        'PCLT' => 'Font::TTF::PCLT',
+        'bsln' => 'Font::TTF::Bsln',
+        'cmap' => 'Font::TTF::Cmap',
+        'cvt ' => 'Font::TTF::Cvt_',
+        'fdsc' => 'Font::TTF::Fdsc',
+        'feat' => 'Font::TTF::Feat',
+        'fmtx' => 'Font::TTF::Fmtx',
+        'fpgm' => 'Font::TTF::Fpgm',
+        'glyf' => 'Font::TTF::Glyf',
+        'hdmx' => 'Font::TTF::Hdmx',
+        'head' => 'Font::TTF::Head',
+        'hhea' => 'Font::TTF::Hhea',
+        'hmtx' => 'Font::TTF::Hmtx',
+        'kern' => 'Font::TTF::Kern',
+        'loca' => 'Font::TTF::Loca',
+        'maxp' => 'Font::TTF::Maxp',
+        'mort' => 'Font::TTF::Mort',
+        'name' => 'Font::TTF::Name',
+        'post' => 'Font::TTF::Post',
+        'prep' => 'Font::TTF::Prep',
+        'prop' => 'Font::TTF::Prop',
+        'vhea' => 'Font::TTF::Vhea',
+        'vmtx' => 'Font::TTF::Vmtx',
+          );
+
+# This is special code because I am fed up of every time I x a table in the debugger
+# I get the whole font printed. Thus substitutes my 3 line change to dumpvar into
+# the debugger. Clunky, but nice. You are welcome to a copy if you want one.
+          
+BEGIN {
+    my ($p);
+
+    foreach $p (@INC)
+    {
+        if (-f "$p/mydumpvar.pl")
+        {
+            $dumper = 'mydumpvar.pl';
+            last;
+        }
+    }
+    $dumper ||= 'dumpvar.pl';
+}
+
+sub main::dumpValue
+{ do $dumper; &main::dumpValue; }
+    
+
+=head2 Font::TTF::Font->AddTable($tablename, $class)
+
+Adds the given class to be used when representing the given table name. It also
+'requires' the class for you.
+
+=cut
+
+sub AddTable
+{
+    my ($class, $table, $useclass) = @_;
+
+    $tables{$table} = $useclass;
+#    $useclass =~ s|::|/|oig;
+#    require "$useclass.pm";
+}
+
+
+=head2 Font::TTF::Font->Init
+
+For those people who like making fonts without reading them. This subroutine
+will require all the table code for the various table types for you. Not
+needed if using Font::TTF::Font::read before using a table.
+
+=cut
+
+sub Init
+{
+    my ($class) = @_;
+    my ($t);
+
+    foreach $t (keys %tables)
+    {
+        $t =~ s|::|/|oig;
+        require "$t.pm";
+    }
+}
+
+=head2 Font::TTF::Font->new(%props)
+
+Creates a new font object and initialises with the given properties. This is
+primarily for use when a TTF is embedded somewhere. Notice that the properties
+are automatically preceded by a space when inserted into the object. This is in
+order that fields do not clash with tables.
+
+=cut
+
+sub new
+{
+    my ($class, %props) = @_;
+    my ($self) = {};
+
+    bless $self, $class;
+
+    foreach (keys %props)
+    { $self->{" $_"} = $props{$_}; }
+    $self;
+}
+
+
+=head2 Font::TTF::Font->open($fname)
+
+Reads the header and directory for the given font file and creates appropriate
+objects for each table in the font.
+
+=cut
+
+sub open
+{
+    my ($class, $fname) = @_;
+    my ($fh);
+    my ($self) = {};
+    
+    unless (ref($fname))
+    {
+        $fh = IO::File->new($fname) or return undef;
+        binmode $fh;
+    } else
+    { $fh = $fname; }
+
+    $self->{' INFILE'} = $fh;
+    $self->{' fname'} = $fname;
+    $self->{' OFFSET'} = 0;
+    bless $self, $class;
+    
+    $self->read;
+}
+
+=head2 $f->read
+
+Reads a Truetype font directory starting from the current location in the file.
+This has been separated from the C<open> function to allow support for embedded
+TTFs for example in TTCs. Also reads the C<head> and C<maxp> tables immediately.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t);
+
+    $fh->seek($self->{' OFFSET'}, 0);
+    $fh->read($dat, 12);
+    ($ver, $dir_num) = unpack("Nn", $dat);
+    $ver == 1 << 16 || $ver == unpack('N', 'OTTO') || $ver == 0x74727565 or return undef;  # support Mac sfnts
+    
+    for ($i = 0; $i < $dir_num; $i++)
+    {
+        $fh->read($dat, 16) || die "Reading table entry";
+        ($name, $check, $off, $len) = unpack("a4NNN", $dat);
+        $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) && next
+                if (defined $self->{' PARENT'});
+        $type = $tables{$name} || 'Font::TTF::Table';
+        $t = $type;
+        if ($^O eq "MacOS")
+        { $t =~ s/^|::/:/oig; }
+        else
+        { $t =~ s|::|/|oig; }
+        require "$t.pm";
+        $self->{$name} = $type->new(PARENT  => $self,
+                                    NAME    => $name,
+                                    INFILE  => $fh,
+                                    OFFSET  => $off,
+                                    LENGTH  => $len,
+                                    CSUM    => $check);
+    }
+    
+    foreach $t ('head', 'maxp')
+    { $self->{$t}->read if defined $self->{$t}; }
+
+    $self;
+}
+
+
+=head2 $f->out($fname [, @tablelist])
+
+Writes a TTF file consisting of the tables in tablelist. The list is checked to
+ensure that only tables that exist are output. (This means that you can't have
+non table information stored in the font object with key length of exactly 4)
+
+In many cases the user simply wants to output all the tables in alphabetical order.
+This can be done by not including a @tablelist, in which case the subroutine will
+output all the defined tables in the font in alphabetical order.
+
+Returns $f on success and undef on failure, including warnings.
+
+All output files must include the C<head> table.
+
+=cut
+
+sub out
+{
+    my ($self, $fname, @tlist) = @_;
+    my ($fh);
+    my ($dat, $numTables, $sRange, $eSel);
+    my (%dir, $k, $mloc, $count);
+    my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift);
+
+    unless (ref($fname))
+    {
+        $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef;
+        binmode $fh;
+    } else
+    { $fh = $fname; }
+    
+    $self->{' oname'} = $fname;
+    $self->{' outfile'} = $fh;
+
+    if ($self->{' wantsig'})
+    {
+        $self->{' nocsum'} = 1;
+#        $self->{'head'}{'checkSumAdjustment'} = 0;
+        $self->{' tempDSIG'} = $self->{'DSIG'};
+        $self->{' tempcsum'} = $self->{'head'}{' CSUM'};
+        delete $self->{'DSIG'};
+        @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}}
+            grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0);
+    }
+    elsif ($#tlist < 0)
+    { @tlist = sort keys %$self; }
+    
+    @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
+    $numTables = $#tlist + 1;
+    $numTables++ if ($self->{' wantsig'});
+    
+    ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16);
+    $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift);
+    $fh->print($dat);
+    $msum = unpack("%32N*", $dat);
+
+# reserve place holders for each directory entry
+    foreach $k (@tlist)
+    {
+        $dir{$k} = pack("A4NNN", $k, 0, 0, 0);
+        $fh->print($dir{$k});
+    }
+
+    $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
+
+    $loc = $fh->tell();
+    if ($loc & 3)
+    {
+        $fh->print(substr("\000" x 4, $loc & 3));
+        $loc += 4 - ($loc & 3);
+    }
+
+    foreach $k (@tlist)
+    {
+        $oldloc = $loc;
+        $self->{$k}->out($fh);
+        $loc = $fh->tell();
+        $len = $loc - $oldloc;
+        if ($loc & 3)
+        {
+            $fh->print(substr("\000" x 4, $loc & 3));
+            $loc += 4 - ($loc & 3);
+        }
+        $fh->seek($oldloc, 0);
+        $csum = 0; $mloc = $loc;
+        while ($mloc > $oldloc)
+        {
+            $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc;
+            $fh->read($dat, $count);
+            $csum += unpack("%32N*", $dat);
+# this line ensures $csum stays within 32 bit bounds, clipping as necessary
+            if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
+            $mloc -= $count;
+        }
+        $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len);
+        $msum += $csum + unpack("%32N*", $dir{$k});
+        while ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; }
+        $fh->seek($loc, 0);
+    }
+
+    unless ($self->{' nocsum'})             # assuming we want a file checksum
+    {
+# Now we need to sort out the head table's checksum
+        if (!defined $dir{'head'})
+        {                                   # you have to have a head table
+            $fh->close();
+            return warn("No 'head' table to output in $fname"), undef;
+        }
+        ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
+        $fh->seek($loc + 8, 0);
+        $fh->read($dat, 4);
+        $lsum = unpack("N", $dat);
+        if ($lsum != 0)
+        {
+            $csum -= $lsum;
+            if ($csum < 0) { $csum += 0xffffffff; $csum++; }
+            $msum -= $lsum * 2;                     # twice (in head and in csum)
+            while ($msum < 0) { $msum += 0xffffffff; $msum++; }
+        }
+        $lsum = 0xB1B0AFBA - $msum;
+        $fh->seek($loc + 8, 0);
+        $fh->print(pack("N", $lsum));
+        $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len);
+    } elsif ($self->{' wantsig'})
+    {
+        if (!defined $dir{'head'})
+        {                                   # you have to have a head table
+            $fh->close();
+            return warn("No 'head' table to output in $fname"), undef;
+        }
+        ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'});
+        $fh->seek($loc + 8, 0);
+        $fh->print(pack("N", 0));
+#        $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len);
+    }
+
+# Now we can output the directory again
+    if ($self->{' wantsig'})
+    { @tlist = sort @tlist; }
+    $fh->seek(12, 0);
+    foreach $k (@tlist)
+    { $fh->print($dir{$k}); }
+    $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'});
+    $fh->close();
+    $self;
+}
+
+
+=head2 $f->out_xml($filename [, @tables])
+
+Outputs the font in XML format
+
+=cut
+
+sub out_xml
+{
+    my ($self, $fname, @tlist) = @_;
+    my ($fh, $context, $numTables, $k);
+
+    $context->{'indent'} = ' ' x 4;
+
+    unless (ref($fname))
+    {
+        $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef;
+        binmode $fh;
+    } else
+    { $fh = $fname; }
+
+    unless (scalar @tlist > 0)
+    {
+        @tlist = sort keys %$self;
+        @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist);
+    }
+    $numTables = $#tlist + 1;
+
+    $context->{'fh'} = $fh;
+    $fh->print("<?xml version='1.0' encoding='UTF-8'?>\n");
+    $fh->print("<font tables='$numTables'>\n\n");
+    
+    foreach $k (@tlist)
+    {
+        $fh->print("<table name='$k'>\n");
+        $self->{$k}->out_xml($context, $context->{'indent'});
+        $fh->print("</table>\n");
+    }
+
+    $fh->print("</font>\n");
+    $fh->close;
+    $self;
+}
+
+
+=head2 $f->XML_start($context, $tag, %attrs)
+
+Handles start messages from the XML parser. Of particular interest to us are <font> and
+<table>.
+
+=cut
+
+sub XML_start
+{
+    my ($self, $context, $tag, %attrs) = @_;
+    my ($name, $type, $t);
+
+    if ($tag eq 'font')
+    { $context->{'tree'}[-1] = $self; }
+    elsif ($tag eq 'table')
+    {
+        $name = $attrs{'name'};
+        unless (defined $self->{$name})
+        {
+            $type = $tables{$name} || 'Font::TTF::Table';
+            $t = $type;
+            if ($^O eq "MacOS")
+            { $t =~ s/^|::/:/oig; }
+            else
+            { $t =~ s|::|/|oig; }
+            require "$t.pm";
+            $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1);
+        }
+        $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name});
+    }
+    $context;
+}
+
+
+sub XML_end
+{
+    my ($self) = @_;
+    my ($context, $tag, %attrs) = @_;
+    my ($i);
+
+    return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca');
+    if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'})
+    {
+        for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++)
+        { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; }
+        $context->{'glyphs'} = $self->{'loca'}{'glyphs'};
+    }
+    return undef;
+}
+
+=head2 $f->update
+
+Sends update to all the tables in the font and then resets all the isDirty
+flags on each table. The data structure in now consistent as a font (we hope).
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    
+    $self->tables_do(sub { $_[0]->update; });
+
+    $self;
+}
+
+=head2 $f->dirty
+
+Dirties all the tables in the font
+
+=cut
+
+sub dirty
+{ $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; }
+
+=head2 $f->tables_do(&func)
+
+Calls &func for each table in the font. Calls the table in alphabetical sort
+order as per the order in the directory:
+
+    &func($table, $name);
+
+=cut
+
+sub tables_do
+{
+    my ($self, $func) = @_;
+    my ($t);
+
+    foreach $t (sort grep {length($_) == 4} keys %$self)
+    { &$func($self->{$t}, $t); }
+    $self;
+}
+
+
+=head2 $f->release
+
+Releases ALL of the memory used by the TTF font and all of its component
+objects.  After calling this method, do B<NOT> expect to have anything left in
+the C<Font::TTF::Font> object.
+
+B<NOTE>, that it is important that you call this method on any
+C<Font::TTF::Font> object when you wish to destruct it and free up its memory.
+Internally, we track things in a structure that can result in circular
+references, and without calling 'C<release()>' these will not properly get
+cleaned up by Perl.  Once you've called this method, though, don't expect to be
+able to do anything else with the C<Font::TTF::Font> object; it'll have B<no>
+internal state whatsoever.
+
+B<Developer note:> As part of the brute-force cleanup done here, this method
+will throw a warning message whenever unexpected key values are found within
+the C<Font::TTF::Font> object.  This is done to help ensure that any unexpected
+and unfreed values are brought to your attention so that you can bug us to keep
+the module updated properly; otherwise the potential for memory leaks due to
+dangling circular references will exist.  
+
+=cut
+
+sub release
+{
+    my ($self) = @_;
+
+# delete stuff that we know we can, here
+
+    my @tofree = map { delete $self->{$_} } keys %{$self};
+
+    while (my $item = shift @tofree)
+    {
+        my $ref = ref($item);
+        if (UNIVERSAL::can($item, 'release'))
+        { $item->release(); }
+        elsif ($ref eq 'ARRAY')
+        { push( @tofree, @{$item} ); }
+        elsif (UNIVERSAL::isa($ref, 'HASH'))
+        { release($item); }
+    }
+
+# check that everything has gone - it better had!
+    foreach my $key (keys %{$self})
+    { warn ref($self) . " still has '$key' key left after release.\n"; }
+}
+
+1;
+
+=head1 BUGS
+
+Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope.
+The parts of the code which haven't been implemented yet are:
+
+=over 4
+
+=item Post
+
+Version 4 format types are not supported yet.
+
+=item Cmap
+
+Format type 2 (MBCS) has not been implemented yet and therefore may cause
+somewhat spurious results for this table type.
+
+=item Kern
+
+Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come).
+
+=item TTC
+
+The current Font::TTF::Font::out method does not support the writing of TrueType
+Collections.
+
+=back
+
+In addition there are weaknesses or features of this module library
+
+=over 4
+
+=item *
+
+There is very little (or no) error reporting. This means that if you have
+garbled data or garbled data structures, then you are liable to generate duff
+fonts.
+
+=item *
+
+The exposing of the internal data structures everywhere means that doing
+radical re-structuring is almost impossible. But it stop the code from becoming
+ridiculously large.
+
+=back
+
+Apart from these, I try to keep the code in a state of "no known bugs", which
+given the amount of testing this code has had, is not a guarantee of high
+quality, yet.
+
+For more details see the appropriate class files.
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org
+
+Copyright Martin Hosken 1998.
+
+No warranty or expression of effectiveness, least of all regarding anyone's
+safety, is implied in this software or documentation.
+
+=head2 Licensing
+
+The Perl TTF module is licensed under the Perl Artistic License.
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fpgm.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fpgm.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Fpgm.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,87 +1,87 @@
-package Font::TTF::Fpgm;
-
-=head1 NAME
-
-Font::TTF::Fpgm - Font program in a TrueType font. Called when a font is loaded
-
-=head1 DESCRIPTION
-
-This is a minimal class adding nothing beyond a table, but is a repository
-for fpgm type information for those processes brave enough to address hinting.
-
-=cut
-
-use strict;
-use vars qw(@ISA $VERSION);
-
- at ISA = qw(Font::TTF::Table);
-
-$VERSION = 0.0001;
-
-=head2 $t->read
-
-Reading this table is simply a process of reading all the data into the RAM
-copy. Nothing more is done with it.
-
-=cut
-
-sub read
-{
-    $_[0]->read_dat;
-    $_[0]->{' read'} = 1;
-}
-
-=head2 $t->out_xml($context, $depth)
-
-Outputs Fpgm program as XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($dat);
-
-    $self->read;
-    $dat = Font::TTF::Utils::XML_binhint($self->{' dat'});
-    $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg;
-    $fh->print("$depth<code>\n");
-    $fh->print("$depth$context->{'indent'}$dat");
-    $fh->print("$depth</code>\n");
-    $self;
-}
-
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Parse all that hinting code
-
-=cut
-
-sub XML_end
-{
-    my ($self) = shift;
-    my ($context, $tag, %attrs) = @_;
-
-    if ($tag eq 'code')
-    {
-        $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'});
-        return $context;
-    } else
-    { return $self->SUPER::XML_end(@_); }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Fpgm;
+
+=head1 NAME
+
+Font::TTF::Fpgm - Font program in a TrueType font. Called when a font is loaded
+
+=head1 DESCRIPTION
+
+This is a minimal class adding nothing beyond a table, but is a repository
+for fpgm type information for those processes brave enough to address hinting.
+
+=cut
+
+use strict;
+use vars qw(@ISA $VERSION);
+
+ at ISA = qw(Font::TTF::Table);
+
+$VERSION = 0.0001;
+
+=head2 $t->read
+
+Reading this table is simply a process of reading all the data into the RAM
+copy. Nothing more is done with it.
+
+=cut
+
+sub read
+{
+    $_[0]->read_dat;
+    $_[0]->{' read'} = 1;
+}
+
+=head2 $t->out_xml($context, $depth)
+
+Outputs Fpgm program as XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($dat);
+
+    $self->read;
+    $dat = Font::TTF::Utils::XML_binhint($self->{' dat'});
+    $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg;
+    $fh->print("$depth<code>\n");
+    $fh->print("$depth$context->{'indent'}$dat");
+    $fh->print("$depth</code>\n");
+    $self;
+}
+
+
+=head2 $t->XML_end($context, $tag, %attrs)
+
+Parse all that hinting code
+
+=cut
+
+sub XML_end
+{
+    my ($self) = shift;
+    my ($context, $tag, %attrs) = @_;
+
+    if ($tag eq 'code')
+    {
+        $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'});
+        return $context;
+    } else
+    { return $self->SUPER::XML_end(@_); }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/GDEF.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/GDEF.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/GDEF.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,310 +1,310 @@
-package Font::TTF::GDEF;
-
-=head1 NAME
-
-Font::TTF::Gdef - Opentype GDEF table support
-
-=head1 DESCRIPTION
-
-The GDEF table contains various global lists of information which are apparantly
-used in other places in an OpenType renderer. But precisely where is open to
-speculation...
-
-=head1 INSTANCE VARIABLES
-
-There are 4 tables in the GDEF table, each with their own structure:
-
-=over 4
-
-=item GLYPH
-
-This is an L<Font::TTF::Coverage> Class Definition table containing information
-as to what type each glyph is.
-
-=item ATTACH
-
-The attach table consists of a coverage table and then attachment points for
-each glyph in the coverage table:
-
-=over 8
-
-=item COVERAGE
-
-This is a coverage table
-
-=item POINTS
-
-This is an array of point elements. Each element is an array of curve points
-corresponding to the attachment points on that glyph. The order of the curve points
-in the array corresponds to the attachment point number specified in the MARKS
-coverage table (see below).
-
-=back
-
-=item LIG
-
-This contains the ligature caret positioning information for ligature glyphs
-
-=over 8
-
-=item COVERAGE
-
-A coverage table to say which glyphs are ligatures
-
-=item LIGS
-
-An array of elements for each ligature. Each element is an array of information
-for each caret position in the ligature (there being number of components - 1 of
-these, generally)
-
-=over 12
-
-=item FMT
-
-This is the format of the information and is important to provide the semantics
-for the value. This value must be set correctly before output
-
-=item VAL
-
-The value which has meaning according to FMT
-
-=item DEVICE
-
-For FMT = 3, a device table is also referenced which is stored here
-
-=back
-
-=back
-
-=item MARKS
-
-Due to confusion in the GDEF specification, this field is currently withdrawn until
-the confusion is resolved. That way, perhaps this stuff will work!
-
-This class definition table stores the mark attachment point numbers for each
-attachment mark, to indicate which attachment point the mark attaches to on its
-base glyph.
-
-=back
-
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use Font::TTF::Table;
-use Font::TTF::Utils;
-use Font::TTF::Ttopen;
-use vars qw(@ISA $new_gdef);
-
- at ISA = qw(Font::TTF::Table);
-$new_gdef = 1;
-
-=head2 $t->read
-
-Reads the table into the data structure
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($boff) = $self->{' OFFSET'};
-    my ($dat, $goff, $loff, $aoff, $moff, $r, $s, $bloc);
-
-    $self->SUPER::read or return $self;
-    $bloc = $fh->tell();
-    $fh->read($dat, 10);
-    ($self->{'Version'}, $goff, $aoff, $loff) = TTF_Unpack('fS3', $dat);
-    if ($new_gdef)
-    {
-        $fh->read($dat, 12);
-        ($self->{'Version'}, $goff, $aoff, $loff, $moff) = TTF_Unpack('fS4', $dat);
-    }
-
-    if ($goff > 0)
-    {
-        $fh->seek($goff + $boff, 0);
-        $self->{'GLYPH'} = Font::TTF::Coverage->new(0)->read($fh);
-    }
-
-    if ($new_gdef && $moff > 0)
-    {
-        $fh->seek($moff + $boff, 0);
-        $self->{'MARKS'} = Font::TTF::Coverage->new(0)->read($fh);
-    }
-
-    if ($aoff > 0)
-    {
-        my ($off, $gcount, $pcount);
-        
-        $fh->seek($aoff + $boff, 0);
-        $fh->read($dat, 4);
-        ($off, $gcount) = TTF_Unpack('SS', $dat);
-        $fh->read($dat, $gcount << 1);
-
-        $fh->seek($aoff + $boff +  $off, 0);
-        $self->{'ATTACH'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
-
-        foreach $r (TTF_Unpack('S*', $dat))
-        {
-            unless ($r)
-            {
-                push (@{$self->{'ATTACH'}{'POINTS'}}, []);
-                next;
-            }
-            $fh->seek($aoff + $boff + $r, 0);
-            $fh->read($dat, 2);
-            $pcount = TTF_Unpack('S', $dat);
-            $fh->read($dat, $pcount << 1);
-            push (@{$self->{'ATTACH'}{'POINTS'}}, [TTF_Unpack('S*', $dat)]);
-        }
-    }
-
-    if ($loff > 0)
-    {
-        my ($lcount, $off, $ccount, $srec, $comp);
-
-        $fh->seek($loff + $boff, 0);
-        $fh->read($dat, 4);
-        ($off, $lcount) = TTF_Unpack('SS', $dat);
-        $fh->read($dat, $lcount << 1);
-
-        $fh->seek($off + $loff + $boff, 0);
-        $self->{'LIG'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
-
-        foreach $r (TTF_Unpack('S*', $dat))
-        {
-            $fh->seek($r + $loff + $boff, 0);
-            $fh->read($dat, 2);
-            $ccount = TTF_Unpack('S', $dat);
-            $fh->read($dat, $ccount << 1);
-
-            $srec = [];
-            foreach $s (TTF_Unpack('S*', $dat))
-            {
-                $comp = {};
-                $fh->seek($s + $r + $loff + $boff, 0);
-                $fh->read($dat, 4);
-                ($comp->{'FMT'}, $comp->{'VAL'}) = TTF_Unpack('S*', $dat);
-                if ($comp->{'FMT'} == 3)
-                {
-                    $fh->read($dat, 2);
-                    $off = TTF_Unpack('S', $dat);
-                    if (defined $self->{' CACHE'}{$off + $s + $r})
-                    { $comp->{'DEVICE'} = $self->{' CACHE'}{$off + $s + $r}; }
-                    else
-                    {
-                        $fh->seek($off + $s + $r + $loff + $boff, 0);
-                        $comp->{'DEVICE'} = Font::TTF::Delta->new->read($fh);
-                        $self->{' CACHE'}{$off + $s + $r} = $comp->{'DEVICE'};
-                    }
-                }
-                push (@$srec, $comp);
-            }
-            push (@{$self->{'LIG'}{'LIGS'}}, $srec);
-        }
-    }
-
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes out this table.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($goff, $aoff, $loff, $moff, @offs, $loc1, $coff, $loc);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $loc = $fh->tell();
-    if ($new_gdef)
-    { $fh->print(TTF_Pack('fSSSS', $self->{'Version'}, 0, 0, 0, 0)); }
-    else
-    { $fh->print(TTF_Pack('fSSS', $self->{'Version'}, 0, 0, 0)); }
-
-    if (defined $self->{'GLYPH'})
-    {
-        $goff = $fh->tell() - $loc;
-        $self->{'GLYPH'}->out($fh);
-    }
-
-    if (defined $self->{'ATTACH'})
-    {
-        my ($r);
-        
-        $aoff = $fh->tell() - $loc;
-        $fh->print(pack('n*', (0) x ($#{$self->{'ATTACH'}{'POINTS'}} + 3)));
-        foreach $r (@{$self->{'ATTACH'}{'POINTS'}})
-        {
-            push (@offs, $fh->tell() - $loc - $aoff);
-            $fh->print(pack('n*', $#{$r} + 1, @$r));
-        }
-        $coff = $fh->tell() - $loc - $aoff;
-        $self->{'ATTACH'}{'COVERAGE'}->out($fh);
-        $loc1 = $fh->tell();
-        $fh->seek($aoff + $loc, 0);
-        $fh->print(pack('n*', $coff, $#offs + 1, @offs));
-        $fh->seek($loc1, 0);
-    }
-
-    if (defined $self->{'LIG'})
-    {
-        my (@reftables, $ltables, $i, $j, $out, $r, $s);
-
-        $ltables = {};
-        $loff = $fh->tell() - $loc;
-        $out = pack('n*',
-                        Font::TTF::Ttopen->ref_cache($self->{'LIG'}{'COVERAGE'}, $ltables, 0),
-                        0, $#{$self->{'LIG'}{'LIGS'}} + 1,
-                        (0) x ($#{$self->{'LIG'}{'LIGS'}} + 1));
-        push (@reftables, [$ltables, 0]);
-        $i = 0;
-        foreach $r (@{$self->{'LIG'}{'LIGS'}})
-        {
-            $ltables = {};
-            $loc1 = length($out);
-            substr($out, ($i << 1) + 4, 2) = TTF_Pack('S', $loc1);
-            $out .= pack('n*', $#{$r} + 1, (0) x ($#{$r} + 1));
-            @offs = (); $j = 0;
-            foreach $s (@$r)
-            {
-                substr($out, ($j << 1) + 2 + $loc1, 2) =
-                        TTF_Pack('S', length($out) - $loc1);
-                $out .= TTF_Pack('SS', $s->{'FMT'}, $s->{'VAL'});
-                $out .= pack('n', Font::TTF::Ttopen->ref_cache($s->{'DEVICE'},
-                        $ltables, length($out))) if ($s->{'FMT'} == 3);
-                $j++;
-            }
-            push (@reftables, [$ltables, $loc1]);
-            $i++;
-        }
-        Font::TTF::Ttopen::out_final($fh, $out, \@reftables);
-    }
-
-    if ($new_gdef && defined $self->{'MARKS'})
-    {
-        $moff = $fh->tell() - $loc;
-        $self->{'MARKS'}->out($fh);
-    }
-
-    $loc1 = $fh->tell();
-    $fh->seek($loc + 4, 0);
-    if ($new_gdef)
-    { $fh->print(TTF_Pack('S4', $goff, $aoff, $loff, $moff)); }
-    else
-    { $fh->print(TTF_Pack('S3', $goff, $aoff, $loff)); }
-    $fh->seek($loc1, 0);
-    $self;
-}
-
-1;
-
+package Font::TTF::GDEF;
+
+=head1 NAME
+
+Font::TTF::Gdef - Opentype GDEF table support
+
+=head1 DESCRIPTION
+
+The GDEF table contains various global lists of information which are apparantly
+used in other places in an OpenType renderer. But precisely where is open to
+speculation...
+
+=head1 INSTANCE VARIABLES
+
+There are 4 tables in the GDEF table, each with their own structure:
+
+=over 4
+
+=item GLYPH
+
+This is an L<Font::TTF::Coverage> Class Definition table containing information
+as to what type each glyph is.
+
+=item ATTACH
+
+The attach table consists of a coverage table and then attachment points for
+each glyph in the coverage table:
+
+=over 8
+
+=item COVERAGE
+
+This is a coverage table
+
+=item POINTS
+
+This is an array of point elements. Each element is an array of curve points
+corresponding to the attachment points on that glyph. The order of the curve points
+in the array corresponds to the attachment point number specified in the MARKS
+coverage table (see below).
+
+=back
+
+=item LIG
+
+This contains the ligature caret positioning information for ligature glyphs
+
+=over 8
+
+=item COVERAGE
+
+A coverage table to say which glyphs are ligatures
+
+=item LIGS
+
+An array of elements for each ligature. Each element is an array of information
+for each caret position in the ligature (there being number of components - 1 of
+these, generally)
+
+=over 12
+
+=item FMT
+
+This is the format of the information and is important to provide the semantics
+for the value. This value must be set correctly before output
+
+=item VAL
+
+The value which has meaning according to FMT
+
+=item DEVICE
+
+For FMT = 3, a device table is also referenced which is stored here
+
+=back
+
+=back
+
+=item MARKS
+
+Due to confusion in the GDEF specification, this field is currently withdrawn until
+the confusion is resolved. That way, perhaps this stuff will work!
+
+This class definition table stores the mark attachment point numbers for each
+attachment mark, to indicate which attachment point the mark attaches to on its
+base glyph.
+
+=back
+
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use Font::TTF::Table;
+use Font::TTF::Utils;
+use Font::TTF::Ttopen;
+use vars qw(@ISA $new_gdef);
+
+ at ISA = qw(Font::TTF::Table);
+$new_gdef = 1;
+
+=head2 $t->read
+
+Reads the table into the data structure
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($boff) = $self->{' OFFSET'};
+    my ($dat, $goff, $loff, $aoff, $moff, $r, $s, $bloc);
+
+    $self->SUPER::read or return $self;
+    $bloc = $fh->tell();
+    $fh->read($dat, 10);
+    ($self->{'Version'}, $goff, $aoff, $loff) = TTF_Unpack('fS3', $dat);
+    if ($new_gdef)
+    {
+        $fh->read($dat, 12);
+        ($self->{'Version'}, $goff, $aoff, $loff, $moff) = TTF_Unpack('fS4', $dat);
+    }
+
+    if ($goff > 0)
+    {
+        $fh->seek($goff + $boff, 0);
+        $self->{'GLYPH'} = Font::TTF::Coverage->new(0)->read($fh);
+    }
+
+    if ($new_gdef && $moff > 0)
+    {
+        $fh->seek($moff + $boff, 0);
+        $self->{'MARKS'} = Font::TTF::Coverage->new(0)->read($fh);
+    }
+
+    if ($aoff > 0)
+    {
+        my ($off, $gcount, $pcount);
+        
+        $fh->seek($aoff + $boff, 0);
+        $fh->read($dat, 4);
+        ($off, $gcount) = TTF_Unpack('SS', $dat);
+        $fh->read($dat, $gcount << 1);
+
+        $fh->seek($aoff + $boff +  $off, 0);
+        $self->{'ATTACH'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
+
+        foreach $r (TTF_Unpack('S*', $dat))
+        {
+            unless ($r)
+            {
+                push (@{$self->{'ATTACH'}{'POINTS'}}, []);
+                next;
+            }
+            $fh->seek($aoff + $boff + $r, 0);
+            $fh->read($dat, 2);
+            $pcount = TTF_Unpack('S', $dat);
+            $fh->read($dat, $pcount << 1);
+            push (@{$self->{'ATTACH'}{'POINTS'}}, [TTF_Unpack('S*', $dat)]);
+        }
+    }
+
+    if ($loff > 0)
+    {
+        my ($lcount, $off, $ccount, $srec, $comp);
+
+        $fh->seek($loff + $boff, 0);
+        $fh->read($dat, 4);
+        ($off, $lcount) = TTF_Unpack('SS', $dat);
+        $fh->read($dat, $lcount << 1);
+
+        $fh->seek($off + $loff + $boff, 0);
+        $self->{'LIG'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh);
+
+        foreach $r (TTF_Unpack('S*', $dat))
+        {
+            $fh->seek($r + $loff + $boff, 0);
+            $fh->read($dat, 2);
+            $ccount = TTF_Unpack('S', $dat);
+            $fh->read($dat, $ccount << 1);
+
+            $srec = [];
+            foreach $s (TTF_Unpack('S*', $dat))
+            {
+                $comp = {};
+                $fh->seek($s + $r + $loff + $boff, 0);
+                $fh->read($dat, 4);
+                ($comp->{'FMT'}, $comp->{'VAL'}) = TTF_Unpack('S*', $dat);
+                if ($comp->{'FMT'} == 3)
+                {
+                    $fh->read($dat, 2);
+                    $off = TTF_Unpack('S', $dat);
+                    if (defined $self->{' CACHE'}{$off + $s + $r})
+                    { $comp->{'DEVICE'} = $self->{' CACHE'}{$off + $s + $r}; }
+                    else
+                    {
+                        $fh->seek($off + $s + $r + $loff + $boff, 0);
+                        $comp->{'DEVICE'} = Font::TTF::Delta->new->read($fh);
+                        $self->{' CACHE'}{$off + $s + $r} = $comp->{'DEVICE'};
+                    }
+                }
+                push (@$srec, $comp);
+            }
+            push (@{$self->{'LIG'}{'LIGS'}}, $srec);
+        }
+    }
+
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes out this table.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($goff, $aoff, $loff, $moff, @offs, $loc1, $coff, $loc);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $loc = $fh->tell();
+    if ($new_gdef)
+    { $fh->print(TTF_Pack('fSSSS', $self->{'Version'}, 0, 0, 0, 0)); }
+    else
+    { $fh->print(TTF_Pack('fSSS', $self->{'Version'}, 0, 0, 0)); }
+
+    if (defined $self->{'GLYPH'})
+    {
+        $goff = $fh->tell() - $loc;
+        $self->{'GLYPH'}->out($fh);
+    }
+
+    if (defined $self->{'ATTACH'})
+    {
+        my ($r);
+        
+        $aoff = $fh->tell() - $loc;
+        $fh->print(pack('n*', (0) x ($#{$self->{'ATTACH'}{'POINTS'}} + 3)));
+        foreach $r (@{$self->{'ATTACH'}{'POINTS'}})
+        {
+            push (@offs, $fh->tell() - $loc - $aoff);
+            $fh->print(pack('n*', $#{$r} + 1, @$r));
+        }
+        $coff = $fh->tell() - $loc - $aoff;
+        $self->{'ATTACH'}{'COVERAGE'}->out($fh);
+        $loc1 = $fh->tell();
+        $fh->seek($aoff + $loc, 0);
+        $fh->print(pack('n*', $coff, $#offs + 1, @offs));
+        $fh->seek($loc1, 0);
+    }
+
+    if (defined $self->{'LIG'})
+    {
+        my (@reftables, $ltables, $i, $j, $out, $r, $s);
+
+        $ltables = {};
+        $loff = $fh->tell() - $loc;
+        $out = pack('n*',
+                        Font::TTF::Ttopen->ref_cache($self->{'LIG'}{'COVERAGE'}, $ltables, 0),
+                        0, $#{$self->{'LIG'}{'LIGS'}} + 1,
+                        (0) x ($#{$self->{'LIG'}{'LIGS'}} + 1));
+        push (@reftables, [$ltables, 0]);
+        $i = 0;
+        foreach $r (@{$self->{'LIG'}{'LIGS'}})
+        {
+            $ltables = {};
+            $loc1 = length($out);
+            substr($out, ($i << 1) + 4, 2) = TTF_Pack('S', $loc1);
+            $out .= pack('n*', $#{$r} + 1, (0) x ($#{$r} + 1));
+            @offs = (); $j = 0;
+            foreach $s (@$r)
+            {
+                substr($out, ($j << 1) + 2 + $loc1, 2) =
+                        TTF_Pack('S', length($out) - $loc1);
+                $out .= TTF_Pack('SS', $s->{'FMT'}, $s->{'VAL'});
+                $out .= pack('n', Font::TTF::Ttopen->ref_cache($s->{'DEVICE'},
+                        $ltables, length($out))) if ($s->{'FMT'} == 3);
+                $j++;
+            }
+            push (@reftables, [$ltables, $loc1]);
+            $i++;
+        }
+        Font::TTF::Ttopen::out_final($fh, $out, \@reftables);
+    }
+
+    if ($new_gdef && defined $self->{'MARKS'})
+    {
+        $moff = $fh->tell() - $loc;
+        $self->{'MARKS'}->out($fh);
+    }
+
+    $loc1 = $fh->tell();
+    $fh->seek($loc + 4, 0);
+    if ($new_gdef)
+    { $fh->print(TTF_Pack('S4', $goff, $aoff, $loff, $moff)); }
+    else
+    { $fh->print(TTF_Pack('S3', $goff, $aoff, $loff)); }
+    $fh->seek($loc1, 0);
+    $self;
+}
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/GPOS.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/GPOS.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/GPOS.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,667 +1,667 @@
-package Font::TTF::GPOS;
-
-=head1 NAME
-
-Font::TTF::GPOS - Support for Opentype GPOS tables in conjunction with TTOpen
-
-=head1 DESCRIPTION
-
-The GPOS table is one of the most complicated tables in the TTF spec and the
-corresponding data structure abstraction is also not trivial. While much of the
-structure of a GPOS is shared with a GSUB table via the L<Font::TTF::Ttopen>
-
-=head1 INSTANCE VARIABLES
-
-Here we describe the additions and lookup specific information for GPOS tables.
-Unfortunately there is no one abstraction which seems to work comfortable for
-all GPOS tables, so we will also examine how the variables are used for different
-lookup types.
-
-The following are the values allowed in the ACTION_TYPE and MATCH_TYPE variables:
-
-=over 4
-
-=item ACTION_TYPE
-
-This can take any of the following values
-
-=over 8
-
-=item a
-
-The ACTION is an array of anchor tables
-
-=item o
-
-Offset. There is no RULE array. The ADJUST variable contains a value record (see
-later in this description)
-
-=item v
-
-The ACTION is a value record.
-
-=item p
-
-Pair adjustment. The ACTION contains an array of two value records for the matched
-two glyphs.
-
-=item e
-
-Exit and Entry records. The ACTION contains an array of two anchors corresponding
-to the exit and entry anchors for the glyph.
-
-=item l
-
-Indicates a lookup based contextual rule as per the GSUB table.
-
-=back
-
-=item MATCH_TYPE
-
-This can take any of the following values
-
-=over 8
-
-=item g
-
-A glyph array
-
-=item c
-
-An array of class values
-
-=item o
-
-An array of coverage tables
-
-=back
-
-=back
-
-The following variables are added for Attachment Positioning Subtables:
-
-=over 4
-
-=item MATCH
-
-This contains an array of glyphs to match against for all RULES. It is much like
-having the same MATCH string in all RULES. In the cases it is used so far, it only
-ever contains one element.
-
-=item MARKS
-
-This contains a Mark array consisting of each element being a subarray of two
-elements:
-
-=over 8
-
-=item CLASS
-
-The class that this mark uses on its base
-
-=item ANCHOR
-
-The anchor with which to attach this mark glyph
-
-=back
-
-The base table for mark to base, ligature or mark attachment positioning is
-structured with the ACTION containing an array of anchors corresponding to each
-attachment class. For ligatures, there is more than one RULE in the RULE array
-corresponding to each glyph in the coverage table.
-
-=back
-
-Other variables which are provided for informational purposes are:
-
-=over 4
-
-=item VFMT
-
-Value format for the adjustment of the glyph matched by the coverage table.
-
-=item VFMT2
-
-Value format used in pair adjustment for the second glyph in the pair
-
-=back
-
-=head2 Value Records
-
-There is a subtype used in GPOS tables called a value record. It is used to adjust
-the position of a glyph from its default position. The value record is variable
-length with a bitfield at the beginning to indicate which of the following
-entries are included. The bitfield is not stored since it is recalculated at
-write time.
-
-=over 4
-
-=item XPlacement
-
-Horizontal adjustment for placement (not affecting other unattached glyphs)
-
-=item YPlacement
-
-Vertical adjustment for placement (not affecting other unattached glyphs)
-
-=item XAdvance
-
-Adjust the advance width glyph (used only in horizontal writing systems)
-
-=item YAdvance
-
-Adjust the vertical advance (used only in vertical writing systems)
-
-=item XPlaDevice
-
-Device table for device specific adjustment of horizontal placement
-
-=item YPlaDevice
-
-Device table for device specific adjustment of vertical placement
-
-=item XAdvDevice
-
-Device table for device specific adjustment of horizontal advance
-
-=item YAdDevice
-
-Device table for device specific adjustment of vertical advance
-
-=item XIdPlacement
-
-Horizontal placement metric id (for Multiple Master fonts - but that's all I know!)
-
-=item YIdPlacement
-
-Vertical placement metric id
-
-=item XIdAdvance
-
-Horizontal advance metric id
-
-=item YIdAdvance
-
-Vertical advance metric id
-
-=back
-
-=head1 CORRESPONDANCE TO LAYOUT TYPES
-
-Here is what is stored in the ACTION_TYPE and MATCH_TYPE for each of the known
-GPOS subtable types:
-
-                1.1 1.2 2.1 2.2 3   4   5   6   7.1 7.2 7.3 8.1 8.2 8.3
-  ACTION_TYPE    o   v   p   p  e   a   a   a    l   l   l   l   l   l
-  MATCH_TYPE             g   c                   g   c   o   g   c   o
-
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use Font::TTF::Ttopen;
-use Font::TTF::Delta;
-use Font::TTF::Anchor;
-use Font::TTF::Utils;
-use vars qw(@ISA);
-
- at ISA = qw(Font::TTF::Ttopen);
-
-
-=head2 read_sub
-
-Reads the subtable into the data structures
-
-=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, $mcount, $scount, $i, $j, $count, $fmt, $fmt2, $cover, $srec, $subst);
-    my ($c1, $c2, $s, $moff, $boff);
-
-
-    if ($type == 8)
-    {
-        $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 == 7 || $type == 8))
-    { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); }
-
-    $lookup->{'FORMAT'} = $fmt;
-    if ($type == 1 && $fmt == 1)
-    {
-        $lookup->{'VFMT'} = $count;
-        $lookup->{'ADJUST'} = $self->read_value($count, $loc, $lookup, $fh);
-        $lookup->{'ACTION_TYPE'} = 'o';
-    } elsif ($type == 1 && $fmt == 2)
-    {
-        $lookup->{'VFMT'} = $count;
-        $fh->read($dat, 2);
-        $mcount = unpack('n', $dat);
-        for ($i = 0; $i < $mcount; $i++)
-        { push (@{$lookup->{'RULES'}}, [{'ACTION'} =>
-                                    [$self->read_value($count, $loc, $lookup, $fh)]]); }
-        $self->{'ACTION_TYPE'} = 'v';
-    } elsif ($type == 2 && $fmt == 1)
-    {
-        $lookup->{'VFMT'} = $count;
-        $fh->read($dat, 4);
-        ($fmt2, $mcount) = unpack('n2', $dat);
-        $lookup->{'VFMT2'} = $fmt2;
-        $fh->read($dat, $mcount << 1);
-        foreach $s (unpack('n*', $dat))
-        {
-            $fh->seek($loc + $s, 0);
-            $fh->read($dat, 2);
-            $scount = TTF_Unpack('S', $dat);
-            $subst = [];
-            for ($i = 0; $i < $scount; $i++)
-            {
-                $srec = {};
-                $fh->read($dat, 2);
-                $srec->{'MATCH'} = [TTF_Unpack('S', $dat)];
-                $srec->{'ACTION'} = [$self->read_value($count, $loc, $lookup, $fh),
-                                     $self->read_value($fmt2, $loc, $lookup, $fh)];
-                push (@$subst, $srec);
-            }
-            push (@{$lookup->{'RULES'}}, $subst);
-        }
-        $lookup->{'ACTION_TYPE'} = 'p';
-        $lookup->{'MATCH_TYPE'} = 'g';
-    } elsif ($type == 2 && $fmt == 2)
-    {
-        $fh->read($dat, 10);
-        ($lookup->{'VFMT2'}, $c1, $c2, $mcount, $scount) = TTF_Unpack('S*', $dat);
-        $lookup->{'CLASS'} = $self->read_cover($c1, $loc, $lookup, $fh, 0);
-        $lookup->{'MATCH'} = [$self->read_cover($c2, $loc, $lookup, $fh, 0)];
-        $lookup->{'VFMT'} = $count;
-        for ($i = 0; $i < $mcount; $i++)
-        {
-            $subst = [];
-            for ($j = 0; $j < $scount; $j++)
-            {
-                $srec = {};
-                $srec->{'ACTION'} = [$self->read_value($lookup->{'VFMT'}, $loc, $lookup, $fh),
-                                     $self->read_value($lookup->{'VFMT2'}, $loc, $lookup, $fh)];
-                push (@$subst, $srec);
-            }
-            push (@{$lookup->{'RULES'}}, $subst);
-        }
-        $lookup->{'ACTION_TYPE'} = 'p';
-        $lookup->{'MATCH_TYPE'} = 'c';
-    } elsif ($type == 3 && $fmt == 1)
-    {
-        $fh->read($dat, $count << 2);
-        for ($i = 0; $i < $count; $i++)
-        { push (@{$lookup->{'RULES'}}, [{'ACTION' =>
-                [$self->read_anchor(TTF_Unpack('S', substr($dat, $i << 2, 2)),
-                        $loc, $lookup, $fh),
-                 $self->read_anchor(TTF_Unpack('S', substr($dat, ($i << 2) + 2, 2)),
-                        $loc, $lookup, $fh)]}]); }
-        $lookup->{'ACTION_TYPE'} = 'e';
-    } elsif ($type == 4 || $type == 5 || $type == 6)
-    {
-        my (@offs, $mloc, $thisloc, $ncomp, $k);
-        
-        $lookup->{'MATCH'} = [$lookup->{'COVERAGE'}];
-        $lookup->{'COVERAGE'} = $self->read_cover($count, $loc, $lookup, $fh, 1);
-        $fh->read($dat, 6);
-        ($mcount, $moff, $boff) = TTF_Unpack('S*', $dat);
-        $fh->seek($loc + $moff, 0);
-        $fh->read($dat, 2);
-        $count = TTF_Unpack('S', $dat);
-        for ($i = 0; $i < $count; $i++)
-        {
-            $fh->read($dat, 4);
-            push (@{$lookup->{'MARKS'}}, [TTF_Unpack('S', $dat),
-                    $self->read_anchor(TTF_Unpack('S', substr($dat, 2, 2)) + $moff,
-                            $loc, $lookup, $fh)]);
-        }
-        $fh->seek($loc + $boff, 0);
-        $fh->read($dat, 2);
-        $count = TTF_Unpack('S', $dat);
-        $mloc = $fh->tell() - 2;
-        $thisloc = $mloc;
-        if ($type == 5)
-        {
-            $fh->read($dat, $count << 1);
-            @offs = TTF_Unpack('S*', $dat);
-        }
-        for ($i = 0; $i < $count; $i++)
-        {
-            if ($type == 5)
-            {
-                $thisloc = $mloc + $offs[$i];
-                $fh->seek($thisloc, 0);
-                $fh->read($dat, 2);
-                $ncomp = TTF_Unpack('S', $dat);
-            } else
-            { $ncomp = 1; }
-            for ($j = 0; $j < $ncomp; $j++)
-            {
-                $subst = [];
-                $fh->read($dat, $mcount << 1);
-                for ($k = 0; $k < $mcount; $k++)
-                { push (@$subst, $self->read_anchor(TTF_Unpack('S', substr($dat, $k << 1, 2)) + $thisloc - $loc,
-                        $loc, $lookup, $fh)); }
-
-                push (@{$lookup->{'RULES'}[$i]}, {'ACTION' => $subst});
-            }
-        }
-        $lookup->{'ACTION_TYPE'} = 'a';
-    } elsif ($type == 7 || $type == 8)
-    { $self->read_context($lookup, $fh, $type - 2, $fmt, $cover, $count, $loc); }        
-    $lookup;
-}
-
-
-=head2 $t->extension
-
-Returns the table type number for the extension table
-
-=cut
-
-sub extension
-{ return 9; }
-
-
-=head2 $t->out_sub
-
-Outputs the subtable to the given filehandle
-
-=cut
-
-sub out_sub
-{
-    my ($self, $fh, $main_lookup, $index) = @_;
-    my ($type) = $main_lookup->{'TYPE'};
-    my ($lookup) = $main_lookup->{'SUB'}[$index];
-    my ($fmt) = $lookup->{'FORMAT'};
-    my ($out, $r, $s, $t, $i, $j, $vfmt, $vfmt2, $loc1);
-    my ($num) = $#{$lookup->{'RULES'}} + 1;
-    my ($ctables) = {};
-    my ($mtables) = {};
-    my (@reftables);
-    
-    if ($type == 1 && $fmt == 1)
-    {
-        $out = pack('n2', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2));
-        $vfmt = $self->fmt_value($lookup->{'ADJUST'});
-        $out .= pack('n', $vfmt) . $self->out_value($lookup->{'ADJUST'}, $vfmt, $ctables, 6);
-    } elsif ($type == 1 && $fmt == 2)
-    {
-        $vfmt = 0;
-        foreach $r (@{$lookup->{'RULES'}})
-        { $vfmt |= $self->fmt_value($r->[0]{'ACTION'}[0]); }
-        $out = pack('n4', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            $vfmt, $#{$lookup->{'RULES'}} + 1);
-        foreach $r (@{$lookup->{'RULES'}})
-        { $out .= $self->out_value($r->[0]{'ACTION'}[0], $vfmt, $ctables, length($out)); }
-    } elsif ($type == 2 && $fmt < 3)
-    {
-        $vfmt = 0;
-        $vfmt2 = 0;
-        foreach $r (@{$lookup->{'RULES'}})
-        {
-            foreach $t (@$r)
-            {
-                $vfmt |= $self->fmt_value($t->{'ACTION'}[0]);
-                $vfmt2 |= $self->fmt_value($t->{'ACTION'}[1]);
-            }
-        }
-        if ($fmt == 1)
-        {
-            $out = pack('n5', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            $vfmt, $vfmt2, $#{$lookup->{'RULES'}} + 1);
-        } else
-        {
-            $out = pack('n8', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            $vfmt, $vfmt2,
-                            Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 1),
-                            Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 1),
-                            $#{$lookup->{'RULES'}} + 1, $#{$lookup->{'RULES'}[0]} + 1);
-        }
-        foreach $r (@{$lookup->{'RULES'}})
-        {
-            $out .= $#{$r} + 1 if ($fmt == 1);
-            foreach $t (@$r)
-            {
-                $out .= pack('n', $t->{'MATCH'}[0]) if ($fmt == 1);
-                $out .= $self->out_value($t->{'ACTION'}[0], $vfmt, $ctables, length($out))
-                     .  $self->out_value($t->{'ACTION'}[1], $vfmt2, $ctables, length($out) + 2);
-            }
-        }
-    } elsif ($type == 3 && $fmt == 1)
-    {
-        $out = pack('n3', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            $#{$lookup->{'RULES'}} + 1);
-        foreach $r (@{$lookup->{'RULES'}})
-        {
-            $out .= pack('n2', Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[0], $ctables, length($out)),
-                            Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[1], $ctables, length($out) + 2));
-        }
-    } elsif ($type == 4 || $type == 5 || $type == 6)
-    {
-        my ($loc_off, $loc_t, $ltables);
-        
-        $out = pack('n7', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 2),
-                            Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 4),
-                            $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1, 12, ($#{$lookup->{'MARKS'}} + 4) << 2,
-                            $#{$lookup->{'MARKS'}} + 1);
-        foreach $r (@{$lookup->{'MARKS'}})
-        { $out .= pack('n2', $r->[0], Font::TTF::Ttopen::ref_cache($r->[1], $mtables, length($out) + 2)); }
-        push (@reftables, [$mtables, 12]);
-
-        $loc_t = length($out);
-        substr($out, 10, 2) = pack('n', $loc_t);
-        $out .= pack('n', $#{$lookup->{'RULES'}} + 1);
-        if ($type == 5)
-        {
-            $loc1 = length($out);
-            $out .= pack('n*', (0) x ($#{$lookup->{'RULES'}} + 1));
-        }
-        $ltables = {};
-        for ($i = 0; $i <= $#{$lookup->{'RULES'}}; $i++)
-        {
-            if ($type == 5)
-            {
-                $ltables = {};
-                $loc_t = length($out);
-                substr($out, $loc1 + ($i << 1), 2) = TTF_Pack('S', $loc_t - $loc1 + 2);
-            }
-
-            $r = $lookup->{'RULES'}[$i];
-            $out .= pack('n', $#{$r} + 1) if ($type == 5);
-            foreach $t (@$r)
-            {
-                foreach $s (@{$t->{'ACTION'}})
-                { $out .= pack('n', Font::TTF::Ttopen::ref_cache($s, $ltables, length($out))); }
-            }
-            push (@reftables, [$ltables, $loc_t]) if ($type == 5);
-        }
-        push (@reftables, [$ltables, $loc_t]) unless ($type == 5);
-    } elsif ($type == 7 || $type == 8)
-    { $out = $self->out_context($lookup, $fh, $type - 2, $fmt, $ctables, $out, $num); }
-    push (@reftables, [$ctables, 0]);
-    Font::TTF::Ttopen::out_final($fh, $out, \@reftables);
-    $lookup;
-}
-            
-
-=head2 $t->read_value($format, $base, $lookup, $fh)
-
-Reads a value record from the current location in the file, according to the
-format given.
-
-=cut
-
-sub read_value
-{
-    my ($self, $fmt, $base, $lookup, $fh) = @_;
-    my ($flag) = 1;
-    my ($res) = {};
-    my ($s, $i, $dat);
-
-    $s = 0;
-    for ($i = 0; $i < 12; $i++)
-    {
-        $s++ if ($flag & $fmt);
-        $flag <<= 1;
-    }
-
-    $fh->read($dat, $s << 1);
-    $flag = 1; $i = 0;
-    foreach $s (qw(XPlacement YPlacement XAdvance YAdvance))
-    {
-        $res->{$s} = TTF_Unpack('s', substr($dat, $i++ << 1, 2)) if ($fmt & $flag);
-        $flag <<= 1;
-    }
-
-    foreach $s (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice))
-    {
-        if ($fmt & $flag)
-        { $res->{$s} = $self->read_delta(TTF_Unpack('S', substr($i++ << 1, 2)),
-                            $base, $lookup, $fh); }
-        $flag <<= 1;
-    }
-
-    foreach $s (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance))
-    {
-        $res->{$s} = TTF_Unpack('S', substr($dat, $i++ << 1, 2)) if ($fmt & $flag);
-        $flag <<= 1;
-    }
-    $res;
-}
-
-
-=head2 $t->read_delta($offset, $base, $lookup, $fh)
-
-Reads a delta (device table) at the given offset if it hasn't already been read.
-Store the offset and item in the lookup cache ($lookup->{' CACHE'})
-
-=cut
-
-sub read_delta
-{
-    my ($self, $offset, $base, $lookup, $fh) = @_;
-    my ($loc) = $fh->tell();
-    my ($res, $str);
-
-    return undef unless $offset;
-    $str = sprintf("%X", $base + $offset);
-    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
-    $fh->seek($base + $offset, 0);
-    $res = Font::TTF::Delta->new->read($fh);
-    $fh->seek($loc, 0);
-    $lookup->{' CACHE'}{$str} = $res;
-    return $res;
-}
-
-
-=head2 $t->read_anchor($offset, $base, $lookup, $fh)
-
-Reads an Anchor table at the given offset if it hasn't already been read.
-
-=cut
-
-sub read_anchor
-{
-    my ($self, $offset, $base, $lookup, $fh) = @_;
-    my ($loc) = $fh->tell();
-    my ($res, $str);
-
-    return undef unless $offset;
-    $str = sprintf("%X", $base + $offset);
-    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
-    $fh->seek($base + $offset, 0);
-    $res = Font::TTF::Anchor->new->read($fh);
-    $fh->seek($loc, 0);
-    $lookup->{' CACHE'}{$str} = $res;
-    return $res;
-}
-
-
-=head2 $t->fmt_value
-
-Returns the value format for a given value record
-
-=cut
-
-sub fmt_value
-{
-    my ($self, $value) = @_;
-    my ($fmt) = 0;
-    my ($n);
-
-    foreach $n (reverse qw(XPlacement YPlacement XAdvance YAdvance XPlaDevice YPlaDevice
-                  XAdvDevice YAdvDevice XIdPlacement YIdPlacement XIdAdvance
-                  YIdAdvance))
-    {
-        $fmt <<= 1;
-        $fmt |= 1 if (defined $value->{$n} && (ref $value->{$n} || $value->{$n}));
-    }
-    $fmt;
-}
-
-
-=head2 $t->out_value
-
-Returns the output string for the outputting of the value for a given format. Also
-updates the offset cache for any device tables referenced.
-
-=cut
-
-sub out_value
-{
-    my ($self, $value, $fmt, $tables, $offset) = @_;
-    my ($n, $flag, $out);
-
-    $flag = 1;
-    foreach $n (qw(XPlacement YPlacement XAdvance YAdvance))
-    {
-        $out .= pack('n', $value->{$n}) if ($flag & $fmt);
-        $flag <<= 1;
-    }
-    foreach $n (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice))
-    {
-        if ($flag & $fmt)
-        {
-            $out .= pack('n', Font::TTF::Ttopen::ref_cache(
-                        $value->{$n}, $tables, $offset + length($out)));
-        }
-        $flag <<= 1;
-    }
-    foreach $n (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance))
-    {
-        $out .= pack('n', $value->{$n}) if ($flag & $fmt);
-        $flag <<= 1;
-    }
-    $out;
-}
-
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+package Font::TTF::GPOS;
+
+=head1 TITLE
+
+Font::TTF::GPOS - Support for Opentype GPOS tables in conjunction with TTOpen
+
+=head1 DESCRIPTION
+
+The GPOS table is one of the most complicated tables in the TTF spec and the
+corresponding data structure abstraction is also not trivial. While much of the
+structure of a GPOS is shared with a GSUB table via the L<Font::TTF::Ttopen>
+
+=head1 INSTANCE VARIABLES
+
+Here we describe the additions and lookup specific information for GPOS tables.
+Unfortunately there is no one abstraction which seems to work comfortable for
+all GPOS tables, so we will also examine how the variables are used for different
+lookup types.
+
+The following are the values allowed in the ACTION_TYPE and MATCH_TYPE variables:
+
+=over 4
+
+=item ACTION_TYPE
+
+This can take any of the following values
+
+=over 8
+
+=item a
+
+The ACTION is an array of anchor tables
+
+=item o
+
+Offset. There is no RULE array. The ADJUST variable contains a value record (see
+later in this description)
+
+=item v
+
+The ACTION is a value record.
+
+=item p
+
+Pair adjustment. The ACTION contains an array of two value records for the matched
+two glyphs.
+
+=item e
+
+Exit and Entry records. The ACTION contains an array of two anchors corresponding
+to the exit and entry anchors for the glyph.
+
+=item l
+
+Indicates a lookup based contextual rule as per the GSUB table.
+
+=back
+
+=item MATCH_TYPE
+
+This can take any of the following values
+
+=over 8
+
+=item g
+
+A glyph array
+
+=item c
+
+An array of class values
+
+=item o
+
+An array of coverage tables
+
+=back
+
+=back
+
+The following variables are added for Attachment Positioning Subtables:
+
+=over 4
+
+=item MATCH
+
+This contains an array of glyphs to match against for all RULES. It is much like
+having the same MATCH string in all RULES. In the cases it is used so far, it only
+ever contains one element.
+
+=item MARKS
+
+This contains a Mark array consisting of each element being a subarray of two
+elements:
+
+=over 8
+
+=item CLASS
+
+The class that this mark uses on its base
+
+=item ANCHOR
+
+The anchor with which to attach this mark glyph
+
+=back
+
+The base table for mark to base, ligature or mark attachment positioning is
+structured with the ACTION containing an array of anchors corresponding to each
+attachment class. For ligatures, there is more than one RULE in the RULE array
+corresponding to each glyph in the coverage table.
+
+=back
+
+Other variables which are provided for informational purposes are:
+
+=over 4
+
+=item VFMT
+
+Value format for the adjustment of the glyph matched by the coverage table.
+
+=item VFMT2
+
+Value format used in pair adjustment for the second glyph in the pair
+
+=back
+
+=head2 Value Records
+
+There is a subtype used in GPOS tables called a value record. It is used to adjust
+the position of a glyph from its default position. The value record is variable
+length with a bitfield at the beginning to indicate which of the following
+entries are included. The bitfield is not stored since it is recalculated at
+write time.
+
+=over 4
+
+=item XPlacement
+
+Horizontal adjustment for placement (not affecting other unattached glyphs)
+
+=item YPlacement
+
+Vertical adjustment for placement (not affecting other unattached glyphs)
+
+=item XAdvance
+
+Adjust the advance width glyph (used only in horizontal writing systems)
+
+=item YAdvance
+
+Adjust the vertical advance (used only in vertical writing systems)
+
+=item XPlaDevice
+
+Device table for device specific adjustment of horizontal placement
+
+=item YPlaDevice
+
+Device table for device specific adjustment of vertical placement
+
+=item XAdvDevice
+
+Device table for device specific adjustment of horizontal advance
+
+=item YAdDevice
+
+Device table for device specific adjustment of vertical advance
+
+=item XIdPlacement
+
+Horizontal placement metric id (for Multiple Master fonts - but that's all I know!)
+
+=item YIdPlacement
+
+Vertical placement metric id
+
+=item XIdAdvance
+
+Horizontal advance metric id
+
+=item YIdAdvance
+
+Vertical advance metric id
+
+=back
+
+=head1 CORRESPONDANCE TO LAYOUT TYPES
+
+Here is what is stored in the ACTION_TYPE and MATCH_TYPE for each of the known
+GPOS subtable types:
+
+                1.1 1.2 2.1 2.2 3   4   5   6   7.1 7.2 7.3 8.1 8.2 8.3
+  ACTION_TYPE    o   v   p   p  e   a   a   a    l   l   l   l   l   l
+  MATCH_TYPE             g   c                   g   c   o   g   c   o
+
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use Font::TTF::Ttopen;
+use Font::TTF::Delta;
+use Font::TTF::Anchor;
+use Font::TTF::Utils;
+use vars qw(@ISA);
+
+ at ISA = qw(Font::TTF::Ttopen);
+
+
+=head2 read_sub
+
+Reads the subtable into the data structures
+
+=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, $mcount, $scount, $i, $j, $count, $fmt, $fmt2, $cover, $srec, $subst);
+    my ($c1, $c2, $s, $moff, $boff);
+
+
+    if ($type == 8)
+    {
+        $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 == 7 || $type == 8))
+    { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); }
+
+    $lookup->{'FORMAT'} = $fmt;
+    if ($type == 1 && $fmt == 1)
+    {
+        $lookup->{'VFMT'} = $count;
+        $lookup->{'ADJUST'} = $self->read_value($count, $loc, $lookup, $fh);
+        $lookup->{'ACTION_TYPE'} = 'o';
+    } elsif ($type == 1 && $fmt == 2)
+    {
+        $lookup->{'VFMT'} = $count;
+        $fh->read($dat, 2);
+        $mcount = unpack('n', $dat);
+        for ($i = 0; $i < $mcount; $i++)
+        { push (@{$lookup->{'RULES'}}, [{'ACTION'} =>
+                                    [$self->read_value($count, $loc, $lookup, $fh)]]); }
+        $self->{'ACTION_TYPE'} = 'v';
+    } elsif ($type == 2 && $fmt == 1)
+    {
+        $lookup->{'VFMT'} = $count;
+        $fh->read($dat, 4);
+        ($fmt2, $mcount) = unpack('n2', $dat);
+        $lookup->{'VFMT2'} = $fmt2;
+        $fh->read($dat, $mcount << 1);
+        foreach $s (unpack('n*', $dat))
+        {
+            $fh->seek($loc + $s, 0);
+            $fh->read($dat, 2);
+            $scount = TTF_Unpack('S', $dat);
+            $subst = [];
+            for ($i = 0; $i < $scount; $i++)
+            {
+                $srec = {};
+                $fh->read($dat, 2);
+                $srec->{'MATCH'} = [TTF_Unpack('S', $dat)];
+                $srec->{'ACTION'} = [$self->read_value($count, $loc, $lookup, $fh),
+                                     $self->read_value($fmt2, $loc, $lookup, $fh)];
+                push (@$subst, $srec);
+            }
+            push (@{$lookup->{'RULES'}}, $subst);
+        }
+        $lookup->{'ACTION_TYPE'} = 'p';
+        $lookup->{'MATCH_TYPE'} = 'g';
+    } elsif ($type == 2 && $fmt == 2)
+    {
+        $fh->read($dat, 10);
+        ($lookup->{'VFMT2'}, $c1, $c2, $mcount, $scount) = TTF_Unpack('S*', $dat);
+        $lookup->{'CLASS'} = $self->read_cover($c1, $loc, $lookup, $fh, 0);
+        $lookup->{'MATCH'} = [$self->read_cover($c2, $loc, $lookup, $fh, 0)];
+        $lookup->{'VFMT'} = $count;
+        for ($i = 0; $i < $mcount; $i++)
+        {
+            $subst = [];
+            for ($j = 0; $j < $scount; $j++)
+            {
+                $srec = {};
+                $srec->{'ACTION'} = [$self->read_value($lookup->{'VFMT'}, $loc, $lookup, $fh),
+                                     $self->read_value($lookup->{'VFMT2'}, $loc, $lookup, $fh)];
+                push (@$subst, $srec);
+            }
+            push (@{$lookup->{'RULES'}}, $subst);
+        }
+        $lookup->{'ACTION_TYPE'} = 'p';
+        $lookup->{'MATCH_TYPE'} = 'c';
+    } elsif ($type == 3 && $fmt == 1)
+    {
+        $fh->read($dat, $count << 2);
+        for ($i = 0; $i < $count; $i++)
+        { push (@{$lookup->{'RULES'}}, [{'ACTION' =>
+                [$self->read_anchor(TTF_Unpack('S', substr($dat, $i << 2, 2)),
+                        $loc, $lookup, $fh),
+                 $self->read_anchor(TTF_Unpack('S', substr($dat, ($i << 2) + 2, 2)),
+                        $loc, $lookup, $fh)]}]); }
+        $lookup->{'ACTION_TYPE'} = 'e';
+    } elsif ($type == 4 || $type == 5 || $type == 6)
+    {
+        my (@offs, $mloc, $thisloc, $ncomp, $k);
+        
+        $lookup->{'MATCH'} = [$lookup->{'COVERAGE'}];
+        $lookup->{'COVERAGE'} = $self->read_cover($count, $loc, $lookup, $fh, 1);
+        $fh->read($dat, 6);
+        ($mcount, $moff, $boff) = TTF_Unpack('S*', $dat);
+        $fh->seek($loc + $moff, 0);
+        $fh->read($dat, 2);
+        $count = TTF_Unpack('S', $dat);
+        for ($i = 0; $i < $count; $i++)
+        {
+            $fh->read($dat, 4);
+            push (@{$lookup->{'MARKS'}}, [TTF_Unpack('S', $dat),
+                    $self->read_anchor(TTF_Unpack('S', substr($dat, 2, 2)) + $moff,
+                            $loc, $lookup, $fh)]);
+        }
+        $fh->seek($loc + $boff, 0);
+        $fh->read($dat, 2);
+        $count = TTF_Unpack('S', $dat);
+        $mloc = $fh->tell() - 2;
+        $thisloc = $mloc;
+        if ($type == 5)
+        {
+            $fh->read($dat, $count << 1);
+            @offs = TTF_Unpack('S*', $dat);
+        }
+        for ($i = 0; $i < $count; $i++)
+        {
+            if ($type == 5)
+            {
+                $thisloc = $mloc + $offs[$i];
+                $fh->seek($thisloc, 0);
+                $fh->read($dat, 2);
+                $ncomp = TTF_Unpack('S', $dat);
+            } else
+            { $ncomp = 1; }
+            for ($j = 0; $j < $ncomp; $j++)
+            {
+                $subst = [];
+                $fh->read($dat, $mcount << 1);
+                for ($k = 0; $k < $mcount; $k++)
+                { push (@$subst, $self->read_anchor(TTF_Unpack('S', substr($dat, $k << 1, 2)) + $thisloc - $loc,
+                        $loc, $lookup, $fh)); }
+
+                push (@{$lookup->{'RULES'}[$i]}, {'ACTION' => $subst});
+            }
+        }
+        $lookup->{'ACTION_TYPE'} = 'a';
+    } elsif ($type == 7 || $type == 8)
+    { $self->read_context($lookup, $fh, $type - 2, $fmt, $cover, $count, $loc); }        
+    $lookup;
+}
+
+
+=head2 $t->extension
+
+Returns the table type number for the extension table
+
+=cut
+
+sub extension
+{ return 9; }
+
+
+=head2 $t->out_sub
+
+Outputs the subtable to the given filehandle
+
+=cut
+
+sub out_sub
+{
+    my ($self, $fh, $main_lookup, $index) = @_;
+    my ($type) = $main_lookup->{'TYPE'};
+    my ($lookup) = $main_lookup->{'SUB'}[$index];
+    my ($fmt) = $lookup->{'FORMAT'};
+    my ($out, $r, $s, $t, $i, $j, $vfmt, $vfmt2, $loc1);
+    my ($num) = $#{$lookup->{'RULES'}} + 1;
+    my ($ctables) = {};
+    my ($mtables) = {};
+    my (@reftables);
+    
+    if ($type == 1 && $fmt == 1)
+    {
+        $out = pack('n2', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2));
+        $vfmt = $self->fmt_value($lookup->{'ADJUST'});
+        $out .= pack('n', $vfmt) . $self->out_value($lookup->{'ADJUST'}, $vfmt, $ctables, 6);
+    } elsif ($type == 1 && $fmt == 2)
+    {
+        $vfmt = 0;
+        foreach $r (@{$lookup->{'RULES'}})
+        { $vfmt |= $self->fmt_value($r->[0]{'ACTION'}[0]); }
+        $out = pack('n4', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            $vfmt, $#{$lookup->{'RULES'}} + 1);
+        foreach $r (@{$lookup->{'RULES'}})
+        { $out .= $self->out_value($r->[0]{'ACTION'}[0], $vfmt, $ctables, length($out)); }
+    } elsif ($type == 2 && $fmt < 3)
+    {
+        $vfmt = 0;
+        $vfmt2 = 0;
+        foreach $r (@{$lookup->{'RULES'}})
+        {
+            foreach $t (@$r)
+            {
+                $vfmt |= $self->fmt_value($t->{'ACTION'}[0]);
+                $vfmt2 |= $self->fmt_value($t->{'ACTION'}[1]);
+            }
+        }
+        if ($fmt == 1)
+        {
+            $out = pack('n5', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            $vfmt, $vfmt2, $#{$lookup->{'RULES'}} + 1);
+        } else
+        {
+            $out = pack('n8', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            $vfmt, $vfmt2,
+                            Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 1),
+                            Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 1),
+                            $#{$lookup->{'RULES'}} + 1, $#{$lookup->{'RULES'}[0]} + 1);
+        }
+        foreach $r (@{$lookup->{'RULES'}})
+        {
+            $out .= $#{$r} + 1 if ($fmt == 1);
+            foreach $t (@$r)
+            {
+                $out .= pack('n', $t->{'MATCH'}[0]) if ($fmt == 1);
+                $out .= $self->out_value($t->{'ACTION'}[0], $vfmt, $ctables, length($out))
+                     .  $self->out_value($t->{'ACTION'}[1], $vfmt2, $ctables, length($out) + 2);
+            }
+        }
+    } elsif ($type == 3 && $fmt == 1)
+    {
+        $out = pack('n3', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            $#{$lookup->{'RULES'}} + 1);
+        foreach $r (@{$lookup->{'RULES'}})
+        {
+            $out .= pack('n2', Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[0], $ctables, length($out)),
+                            Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[1], $ctables, length($out) + 2));
+        }
+    } elsif ($type == 4 || $type == 5 || $type == 6)
+    {
+        my ($loc_off, $loc_t, $ltables);
+        
+        $out = pack('n7', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 2),
+                            Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 4),
+                            $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1, 12, ($#{$lookup->{'MARKS'}} + 4) << 2,
+                            $#{$lookup->{'MARKS'}} + 1);
+        foreach $r (@{$lookup->{'MARKS'}})
+        { $out .= pack('n2', $r->[0], Font::TTF::Ttopen::ref_cache($r->[1], $mtables, length($out) + 2)); }
+        push (@reftables, [$mtables, 12]);
+
+        $loc_t = length($out);
+        substr($out, 10, 2) = pack('n', $loc_t);
+        $out .= pack('n', $#{$lookup->{'RULES'}} + 1);
+        if ($type == 5)
+        {
+            $loc1 = length($out);
+            $out .= pack('n*', (0) x ($#{$lookup->{'RULES'}} + 1));
+        }
+        $ltables = {};
+        for ($i = 0; $i <= $#{$lookup->{'RULES'}}; $i++)
+        {
+            if ($type == 5)
+            {
+                $ltables = {};
+                $loc_t = length($out);
+                substr($out, $loc1 + ($i << 1), 2) = TTF_Pack('S', $loc_t - $loc1 + 2);
+            }
+
+            $r = $lookup->{'RULES'}[$i];
+            $out .= pack('n', $#{$r} + 1) if ($type == 5);
+            foreach $t (@$r)
+            {
+                foreach $s (@{$t->{'ACTION'}})
+                { $out .= pack('n', Font::TTF::Ttopen::ref_cache($s, $ltables, length($out))); }
+            }
+            push (@reftables, [$ltables, $loc_t]) if ($type == 5);
+        }
+        push (@reftables, [$ltables, $loc_t]) unless ($type == 5);
+    } elsif ($type == 7 || $type == 8)
+    { $out = $self->out_context($lookup, $fh, $type - 2, $fmt, $ctables, $out, $num); }
+    push (@reftables, [$ctables, 0]);
+    Font::TTF::Ttopen::out_final($fh, $out, \@reftables);
+    $lookup;
+}
+            
+
+=head2 $t->read_value($format, $base, $lookup, $fh)
+
+Reads a value record from the current location in the file, according to the
+format given.
+
+=cut
+
+sub read_value
+{
+    my ($self, $fmt, $base, $lookup, $fh) = @_;
+    my ($flag) = 1;
+    my ($res) = {};
+    my ($s, $i, $dat);
+
+    $s = 0;
+    for ($i = 0; $i < 12; $i++)
+    {
+        $s++ if ($flag & $fmt);
+        $flag <<= 1;
+    }
+
+    $fh->read($dat, $s << 1);
+    $flag = 1; $i = 0;
+    foreach $s (qw(XPlacement YPlacement XAdvance YAdvance))
+    {
+        $res->{$s} = TTF_Unpack('s', substr($dat, $i++ << 1, 2)) if ($fmt & $flag);
+        $flag <<= 1;
+    }
+
+    foreach $s (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice))
+    {
+        if ($fmt & $flag)
+        { $res->{$s} = $self->read_delta(TTF_Unpack('S', substr($i++ << 1, 2)),
+                            $base, $lookup, $fh); }
+        $flag <<= 1;
+    }
+
+    foreach $s (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance))
+    {
+        $res->{$s} = TTF_Unpack('S', substr($dat, $i++ << 1, 2)) if ($fmt & $flag);
+        $flag <<= 1;
+    }
+    $res;
+}
+
+
+=head2 $t->read_delta($offset, $base, $lookup, $fh)
+
+Reads a delta (device table) at the given offset if it hasn't already been read.
+Store the offset and item in the lookup cache ($lookup->{' CACHE'})
+
+=cut
+
+sub read_delta
+{
+    my ($self, $offset, $base, $lookup, $fh) = @_;
+    my ($loc) = $fh->tell();
+    my ($res, $str);
+
+    return undef unless $offset;
+    $str = sprintf("%X", $base + $offset);
+    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
+    $fh->seek($base + $offset, 0);
+    $res = Font::TTF::Delta->new->read($fh);
+    $fh->seek($loc, 0);
+    $lookup->{' CACHE'}{$str} = $res;
+    return $res;
+}
+
+
+=head2 $t->read_anchor($offset, $base, $lookup, $fh)
+
+Reads an Anchor table at the given offset if it hasn't already been read.
+
+=cut
+
+sub read_anchor
+{
+    my ($self, $offset, $base, $lookup, $fh) = @_;
+    my ($loc) = $fh->tell();
+    my ($res, $str);
+
+    return undef unless $offset;
+    $str = sprintf("%X", $base + $offset);
+    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
+    $fh->seek($base + $offset, 0);
+    $res = Font::TTF::Anchor->new->read($fh);
+    $fh->seek($loc, 0);
+    $lookup->{' CACHE'}{$str} = $res;
+    return $res;
+}
+
+
+=head2 $t->fmt_value
+
+Returns the value format for a given value record
+
+=cut
+
+sub fmt_value
+{
+    my ($self, $value) = @_;
+    my ($fmt) = 0;
+    my ($n);
+
+    foreach $n (reverse qw(XPlacement YPlacement XAdvance YAdvance XPlaDevice YPlaDevice
+                  XAdvDevice YAdvDevice XIdPlacement YIdPlacement XIdAdvance
+                  YIdAdvance))
+    {
+        $fmt <<= 1;
+        $fmt |= 1 if (defined $value->{$n} && (ref $value->{$n} || $value->{$n}));
+    }
+    $fmt;
+}
+
+
+=head2 $t->out_value
+
+Returns the output string for the outputting of the value for a given format. Also
+updates the offset cache for any device tables referenced.
+
+=cut
+
+sub out_value
+{
+    my ($self, $value, $fmt, $tables, $offset) = @_;
+    my ($n, $flag, $out);
+
+    $flag = 1;
+    foreach $n (qw(XPlacement YPlacement XAdvance YAdvance))
+    {
+        $out .= pack('n', $value->{$n}) if ($flag & $fmt);
+        $flag <<= 1;
+    }
+    foreach $n (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice))
+    {
+        if ($flag & $fmt)
+        {
+            $out .= pack('n', Font::TTF::Ttopen::ref_cache(
+                        $value->{$n}, $tables, $offset + length($out)));
+        }
+        $flag <<= 1;
+    }
+    foreach $n (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance))
+    {
+        $out .= pack('n', $value->{$n}) if ($flag & $fmt);
+        $flag <<= 1;
+    }
+    $out;
+}
+
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/GSUB.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/GSUB.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/GSUB.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,246 +1,246 @@
-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;
-
- at 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)
-    {
-        $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) = @_;
-    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;
-    my ($ctables) = {};
-
-    if ($type == 1)
-    {
-        $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2));
-        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),
-                            $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); }
-    Font::TTF::Ttopen::out_final($fh, $out, [[$ctables, 0]]);
-    $lookup;
-}
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+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;
+
+ at 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)
+    {
+        $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) = @_;
+    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;
+    my ($ctables) = {};
+
+    if ($type == 1)
+    {
+        $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2));
+        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),
+                            $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); }
+    Font::TTF::Ttopen::out_final($fh, $out, [[$ctables, 0]]);
+    $lookup;
+}
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyf.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyf.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyf.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,158 +1,158 @@
-package Font::TTF::Glyf;
-
-=head1 NAME
-
-Font::TTF::Glyf - The Glyf data table
-
-=head1 DESCRIPTION
-
-This is a stub table. The real data is held in the loca table. If you want to get a glyf
-look it up in the loca table as C<$f->{'loca'}{'glyphs'}[$num]>. It won't be here!
-
-The difference between reading this table as opposed to the loca table is that
-reading this table will cause updated glyphs to be written out rather than just
-copying the glyph information from the input file. This causes font writing to be
-slower. So read the glyf as opposed to the loca table if you want to change glyf
-data. Read the loca table only if you are just wanting to read the glyf information.
-
-This class is used when writing the glyphs though.
-
-=head1 METHODS
-
-=cut
-
-
-use strict;
-use vars qw(@ISA);
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the C<loca> table instead!
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    
-    $self->{' PARENT'}{'loca'}->read;
-    $self->{' read'} = 1;
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes out all the glyphs in the parent's location table, calculating a new
-output location for each one.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($i, $loca, $offset, $numGlyphs);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $loca = $self->{' PARENT'}{'loca'}{'glyphs'};
-    $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-
-    $offset = 0;
-    for ($i = 0; $i < $numGlyphs; $i++)
-    {
-        next unless defined $loca->[$i];
-        $loca->[$i]->update;
-        $loca->[$i]{' OUTLOC'} = $offset;
-        $loca->[$i]->out($fh);
-        $offset += $loca->[$i]{' OUTLEN'};
-    }
-    $self->{' PARENT'}{'head'}{'indexToLocFormat'} = ($offset >= 0x20000);
-    $self;
-}
-
-
-=head2 $t->out_xml($context, $depth)
-
-Outputs all the glyphs in the glyph table just where they are supposed to be output!
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($loca, $i, $numGlyphs);
-
-    $loca = $self->{' PARENT'}{'loca'}{'glyphs'};
-    $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    
-    for ($i = 0; $i < $numGlyphs; $i++)
-    {
-        $context->{'gid'} = $i;
-        $loca->[$i]->out_xml($context, $depth) if (defined $loca->[$i]);
-    }
-
-    $self;
-}
-
-
-=head2 $t->XML_start($context, $tag, %attrs)
-
-Pass control to glyphs as they occur
-
-=cut
-
-sub XML_start
-{
-    my ($self) = shift;
-    my ($context, $tag, %attrs) = @_;
-
-    if ($tag eq 'glyph')
-    {
-        $context->{'tree'}[-1] = Font::TTF::Glyph->new(read => 2, PARENT => $self->{' PARENT'});
-        $context->{'receiver'} = $context->{'tree'}[-1];
-    }
-}
-
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Collect up glyphs and put them into the loca table
-
-=cut
-
-sub XML_end
-{
-    my ($self) = shift;
-    my ($context, $tag, %attrs) = @_;
-
-    if ($tag eq 'glyph')
-    {
-        unless (defined $context->{'glyphs'})
-        {
-            if (defined $self->{' PARENT'}{'loca'})
-            { $context->{'glyphs'} = $self->{' PARENT'}{'loca'}{'glyphs'}; }
-            else
-            { $context->{'glyphs'} = []; }
-        }
-        $context->{'glyphs'}[$attrs{'gid'}] = $context->{'tree'}[-1];
-        return $context;
-    } else
-    { return $self->SUPER::XML_end(@_); }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Glyf;
+
+=head1 NAME
+
+Font::TTF::Glyf - The Glyf data table
+
+=head1 DESCRIPTION
+
+This is a stub table. The real data is held in the loca table. If you want to get a glyf
+look it up in the loca table as C<$f->{'loca'}{'glyphs'}[$num]>. It won't be here!
+
+The difference between reading this table as opposed to the loca table is that
+reading this table will cause updated glyphs to be written out rather than just
+copying the glyph information from the input file. This causes font writing to be
+slower. So read the glyf as opposed to the loca table if you want to change glyf
+data. Read the loca table only if you are just wanting to read the glyf information.
+
+This class is used when writing the glyphs though.
+
+=head1 METHODS
+
+=cut
+
+
+use strict;
+use vars qw(@ISA);
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the C<loca> table instead!
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    
+    $self->{' PARENT'}{'loca'}->read;
+    $self->{' read'} = 1;
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes out all the glyphs in the parent's location table, calculating a new
+output location for each one.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($i, $loca, $offset, $numGlyphs);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $loca = $self->{' PARENT'}{'loca'}{'glyphs'};
+    $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+
+    $offset = 0;
+    for ($i = 0; $i < $numGlyphs; $i++)
+    {
+        next unless defined $loca->[$i];
+        $loca->[$i]->update;
+        $loca->[$i]{' OUTLOC'} = $offset;
+        $loca->[$i]->out($fh);
+        $offset += $loca->[$i]{' OUTLEN'};
+    }
+    $self->{' PARENT'}{'head'}{'indexToLocFormat'} = ($offset >= 0x20000);
+    $self;
+}
+
+
+=head2 $t->out_xml($context, $depth)
+
+Outputs all the glyphs in the glyph table just where they are supposed to be output!
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($loca, $i, $numGlyphs);
+
+    $loca = $self->{' PARENT'}{'loca'}{'glyphs'};
+    $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    
+    for ($i = 0; $i < $numGlyphs; $i++)
+    {
+        $context->{'gid'} = $i;
+        $loca->[$i]->out_xml($context, $depth) if (defined $loca->[$i]);
+    }
+
+    $self;
+}
+
+
+=head2 $t->XML_start($context, $tag, %attrs)
+
+Pass control to glyphs as they occur
+
+=cut
+
+sub XML_start
+{
+    my ($self) = shift;
+    my ($context, $tag, %attrs) = @_;
+
+    if ($tag eq 'glyph')
+    {
+        $context->{'tree'}[-1] = Font::TTF::Glyph->new(read => 2, PARENT => $self->{' PARENT'});
+        $context->{'receiver'} = $context->{'tree'}[-1];
+    }
+}
+
+
+=head2 $t->XML_end($context, $tag, %attrs)
+
+Collect up glyphs and put them into the loca table
+
+=cut
+
+sub XML_end
+{
+    my ($self) = shift;
+    my ($context, $tag, %attrs) = @_;
+
+    if ($tag eq 'glyph')
+    {
+        unless (defined $context->{'glyphs'})
+        {
+            if (defined $self->{' PARENT'}{'loca'})
+            { $context->{'glyphs'} = $self->{' PARENT'}{'loca'}{'glyphs'}; }
+            else
+            { $context->{'glyphs'} = []; }
+        }
+        $context->{'glyphs'}[$attrs{'gid'}] = $context->{'tree'}[-1];
+        return $context;
+    } else
+    { return $self->SUPER::XML_end(@_); }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyph.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyph.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Glyph.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,815 +1,815 @@
-package Font::TTF::Glyph;
-
-=head1 NAME
-
-Font::TTF::Glyph - Holds a single glyph's information
-
-=head1 DESCRIPTION
-
-This is a single glyph description as held in a TT font. On creation only its
-header is read. Thus you can get the bounding box of each glyph without having
-to read all the other information.
-
-=head1 INSTANCE VARIABLES
-
-In addition to the named variables in a glyph header (C<xMin> etc.), there are
-also all capital instance variables for holding working information, mostly
-from the location table.
-
-The standard attributes each glyph has are:
-
- numberOfContours
- xMin
- yMin
- xMax
- yMax
-
-There are also other, derived, instance variables for each glyph which are read
-when the whole glyph is read (via C<read_dat>):
-
-=over 4
-
-=item instLen
-
-Number of bytes in the hinting instructions (Warning this variable is deprecated,
-use C<length($g->{'hints'})> instead).
-
-=item hints
-
-The string containing the hinting code for the glyph
-
-=back
-
-In addition there are other attribute like instance variables for simple glyphs:
-
-=over 4
-
-For each contour there is:
-
-=over 4
-
-=item endPoints
-
-An array of endpoints for each contour in the glyph. There are
-C<numberOfContours> contours in a glyph. The number of points in a glyph is
-equal to the highest endpoint of a contour.
-
-=back
-
-There are also a number of arrays indexed by point number
-
-=over 4
-
-=item flags
-
-The flags associated with reading this point. The flags for a point are
-recalculated for a point when it is C<update>d. Thus the flags are not very
-useful. The only important bit is bit 0 which indicates whether the point is
-an 'on' curve point, or an 'off' curve point.
-
-=item x
-
-The absolute x co-ordinate of the point.
-
-=item y
-
-The absolute y co-ordinate of the point
-
-=back
-
-=back
-
-For composite glyphs there are other variables
-
-=over 4
-
-=item metric
-
-This holds the component number (not its glyph number) of the component from
-which the metrics for this glyph should be taken.
-
-=item comps
-
-This is an array of hashes for each component. Each hash has a number of
-elements:
-
-=over 4
-
-=item glyph
-
-The glyph number of the glyph which comprises this component of the composite.
-
-=item args
-
-An array of two arguments which may be an x, y co-ordinate or two attachment
-points (one on the base glyph the other on the component). See flags for details.
-
-=item flag
-
-The flag for this component
-
-=item scale
-
-A 4 number array for component scaling. This allows stretching, rotating, etc.
-Note that scaling applies to placement co-ordinates (rather than attachment points)
-before locating rather than after.
-
-=back
-
-=item numPoints
-
-This is a generated value which contains the number of components read in for this
-compound glyph.
-
-=back
-
-The private instance variables are:
-
-=over 4
-
-=item INFILE (P)
-
-The input file form which to read any information
-
-=item LOC (P)
-
-Location relative to the start of the glyf table in the read file
-
-=item BASE (P)
-
-The location of the glyf table in the read file
-
-=item LEN (P)
-
-This is the number of bytes required by the glyph. It should be kept up to date
-by calling the C<update> method whenever any of the glyph content changes.
-
-=item OUTLOC (P)
-
-Location relative to the start of the glyf table. This variable is only active
-whilst the output process is going on. It is used to inform the location table
-where the glyph's location is, since the glyf table is output before the loca
-table due to alphabetical ordering.
-
-=item OUTLEN (P)
-
-This indicates the length of the glyph data when it is output. This more
-accurately reflects the internal memory form than the C<LEN> variable which
-only reflects the read file length. The C<OUTLEN> variable is only set after
-calling C<out> or C<out_dat>.
-
-=back
-
-=head2 Editing
-
-If you want to edit a glyph in some way, then you should read_dat the glyph, then
-make your changes and then update the glyph or set the $g->{' isdirty'} variable.
-It is the application's duty to ensure that the following instance variables are
-correct, from which update will calculate the rest, including the bounding box
-information.
-
-    numPoints
-    numberOfContours
-    endPoints
-    x, y, flags         (only flags bit 0)
-    instLen
-    hints
-
-For components, the numPoints, x, y, endPoints & flags are not required but
-the following information is required for each component.
-
-    flag                (bits 2, 10, 11, 12)
-    glyph
-    args
-    scale
-    metric              (glyph instance variable)
-    
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(%fields @field_info);
-use Font::TTF::Utils;
-use Font::TTF::Table;
-
- at field_info = (
-    'numberOfContours' => 's', 
-    'xMin' => 's', 
-    'yMin' => 's',
-    'xMax' => 's',
-    'yMax' => 's');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head1 Font::TTF::Glyph->new(%parms)
-
-Creates a new glyph setting various instance variables
-
-=cut
-
-sub new
-{
-    my ($class, %parms) = @_;
-    my ($self) = {};
-    my ($p);
-
-    bless $self, $class;
-    foreach $p (keys %parms)
-    { $self->{" $p"} = $parms{$p}; }
-    init unless defined $fields{'xMin'};
-    $self;
-}
-
-
-=head2 $g->read
-
-Reads the header component of the glyph (bounding box, etc.) and also the
-glyph content, but into a data field rather than breaking it down into
-its constituent structures. Use read_dat for this.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($dat);
-
-    return $self if $self->{' read'};
-    $self->{' read'} = 1;
-    $fh->seek($self->{' LOC'} + $self->{' BASE'}, 0);
-    $fh->read($self->{' DAT'}, $self->{' LEN'});
-    TTF_Read_Fields($self, $self->{' DAT'}, \%fields);
-    $self;
-}
-
-
-=head2 $g->read_dat
-
-Reads the contents of the glyph (components and curves, etc.) from the memory
-store C<DAT> into structures within the object. Then, to indicate where the
-master form of the data is, it deletes the C<DAT> instance variable.
-
-=cut
-
-sub read_dat
-{
-    my ($self) = @_;
-    my ($dat, $num, $max, $i, $flag, $len, $val, $val1, $fp);
-
-    return $self if $self->{' read'} > 1;
-    $self->read unless $self->{' read'};
-    $dat = $self->{' DAT'};
-    $fp = 10;
-    $num = $self->{'numberOfContours'};
-    if ($num > 0)
-    {
-        $self->{'endPoints'} = [unpack("n*", substr($dat, $fp, $num << 1))];
-        $fp += $num << 1;
-        $max = 0;
-        foreach (@{$self->{'endPoints'}})
-        { $max = $_ if $_ > $max; }
-        $max++;
-        $self->{'numPoints'} = $max;
-        $self->{'instLen'} = unpack("n", substr($dat, $fp));
-        $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'});
-        $fp += 2 + $self->{'instLen'};
-# read the flags array
-        for ($i = 0; $i < $max; $i++)                   
-        {
-            $flag = unpack("C", substr($dat, $fp++));
-            $self->{'flags'}[$i] = $flag;
-            if ($flag & 8)
-            {
-                $len = unpack("C", substr($dat, $fp++));
-                while ($len-- > 0)
-                {
-                    $i++;
-                    $self->{'flags'}[$i] = $flag;
-                }
-            }
-        }
-#read the x array
-        for ($i = 0; $i < $max; $i++)
-        {
-            $flag = $self->{'flags'}[$i];
-            if ($flag & 2)
-            {
-                $val = unpack("C", substr($dat, $fp++));
-                $val = -$val unless ($flag & 16);
-            } elsif ($flag & 16)
-            { $val = 0; }
-            else
-            {
-                $val = TTF_Unpack("s", substr($dat, $fp));
-                $fp += 2;
-            }
-            $self->{'x'}[$i] = $i == 0 ? $val : $self->{'x'}[$i - 1] + $val;
-        }
-#read the y array
-        for ($i = 0; $i < $max; $i++)
-        {
-            $flag = $self->{'flags'}[$i];
-            if ($flag & 4)
-            {
-                $val = unpack("C", substr($dat, $fp++));
-                $val = -$val unless ($flag & 32);
-            } elsif ($flag & 32)
-            { $val = 0; }
-            else
-            {
-                $val = TTF_Unpack("s", substr($dat, $fp));
-                $fp += 2;
-            }
-            $self->{'y'}[$i] = $i == 0 ? $val : $self->{'y'}[$i - 1] + $val;
-        }
-    }
-    
-# compound glyph
-    elsif ($num < 0)
-    {
-        $flag = 1 << 5;             # cheat to get the loop going
-        for ($i = 0; $flag & 32; $i++)
-        {
-            ($flag, $self->{'comps'}[$i]{'glyph'}) = unpack("n2", substr($dat, $fp));
-            $fp += 4;
-            $self->{'comps'}[$i]{'flag'} = $flag;
-            if ($flag & 1)              # ARGS1_AND_2_ARE_WORDS
-            {
-                $self->{'comps'}[$i]{'args'} = [TTF_Unpack("s2", substr($dat, $fp))];
-                $fp += 4;
-            } else
-            {
-                $self->{'comps'}[$i]{'args'} = [unpack("c2", substr($dat, $fp))];
-                $fp += 2;
-            }
-            
-            if ($flag & 8)
-            {
-                $val = TTF_Unpack("F", substr($dat, $fp));
-                $fp += 2;
-                $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val];
-            } elsif ($flag & 64)
-            {
-                ($val, $val1) = TTF_Unpack("F2", substr($dat, $fp));
-                $fp += 4;
-                $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val1];
-            } elsif ($flag & 128)
-            {
-                $self->{'comps'}[$i]{'scale'} = [TTF_Unpack("F4", substr($dat, $fp))];
-                $fp += 8;
-            }
-            $self->{'metric'} = $i if ($flag & 512);
-        }
-        $self->{'numPoints'} = $i;
-        if ($flag & 256)            # HAVE_INSTRUCTIONS
-        {
-            $self->{'instLen'} = unpack("n", substr($dat, $fp));
-            $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'});
-            $fp += 2 + $self->{'instLen'};
-        }
-    }
-    return undef if ($fp > length($dat));
-    $self->{' read'} = 2;
-    $self;
-}
-
-
-=head2 $g->out($fh)
-
-Writes the glyph data to outfile
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    $self->read unless $self->{' read'};
-    $self->update if $self->{' isDirty'};
-    $fh->print($self->{' DAT'});
-    $self->{' OUTLEN'} = length($self->{' DAT'});
-    $self;
-}
-
-
-=head2 $g->out_xml($context, $depth)
-
-Outputs an XML description of the glyph
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($addr) = ($self =~ m/\((.+)\)$/o);
-    my ($k, $ndepth);
-
-    if ($context->{'addresses'}{$addr})
-    {
-        $context->{'fh'}->printf("%s<glyph gid='%s' id_ref='%s'/>\n", $depth, $context->{'gid'}, $addr);
-        return $self;
-    }
-    else
-    {
-        $context->{'fh'}->printf("%s<glyph gid='%s' id='%s'>\n", $depth, $context->{'gid'}, $addr);
-    }
-    
-    $ndepth = $depth . $context->{'indent'};
-    $self->read_dat;
-    foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self})
-    {
-        $self->XML_element($context, $ndepth, $k, $self->{$k});
-    }
-    $context->{'fh'}->print("$depth</glyph>\n");
-    delete $context->{'done_points'};
-    $self;
-}
-    
-
-sub XML_element
-{
-    my ($self, $context, $depth, $key, $val) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($dind) = $depth . $context->{'indent'};
-    my ($i);
-    
-    if ($self->{'numberOfContours'} >= 0 && ($key eq 'x' || $key eq 'y' || $key eq 'flags'))
-    {
-        return $self if ($context->{'done_points'});
-        $context->{'done_points'} = 1;
-
-        $fh->print("$depth<points>\n");
-        for ($i = 0; $i <= $#{$self->{'flags'}}; $i++)
-        { $fh->printf("%s<point x='%s' y='%s' flags='0x%02X'/>\n", $dind,
-                $self->{'x'}[$i], $self->{'y'}[$i], $self->{'flags'}[$i]); }
-        $fh->print("$depth</points>\n");
-    }
-    elsif ($key eq 'hints')
-    {
-        my ($dat);
-        $fh->print("$depth<hints>\n");
-#        Font::TTF::Utils::XML_hexdump($context, $depth . $context->{'indent'}, $self->{'hints'});
-        $dat = Font::TTF::Utils::XML_binhint($self->{'hints'});
-        $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/mg;
-        $fh->print("$depth$context->{'indent'}$dat");
-        $fh->print("$depth</hints>\n");
-    }
-    else
-    { return Font::TTF::Table::XML_element(@_); }
-
-    $self;    
-}
-
-
-=head2 $g->update
-
-Generates a C<$self->{'DAT'}> from the internal structures, if the data has
-been read into structures in the first place. If you are building a glyph
-from scratch you will need to set the instance variable C<' read'> to 2 (or
-something > 1) for the update to work.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($dat, $loc, $len, $flag, $x, $y, $i, $comp, $num);
-
-    return $self unless (defined $self->{' read'} && $self->{' read'} > 1);
-    $self->update_bbox;
-    $self->{' DAT'} = TTF_Out_Fields($self, \%fields, 10);
-    $num = $self->{'numberOfContours'};
-    if ($num > 0)
-    {
-        $self->{' DAT'} .= pack("n*", @{$self->{'endPoints'}});
-        $len = $self->{'instLen'};
-        $self->{' DAT'} .= pack("n", $len);
-        $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)) if ($len > 0);
-        for ($i = 0; $i < $self->{'numPoints'}; $i++)
-        {
-            $flag = $self->{'flags'}[$i] & 1;
-            if ($i == 0)
-            {
-                $x = $self->{'x'}[$i];
-                $y = $self->{'y'}[$i];
-            } else
-            {
-                $x = $self->{'x'}[$i] - $self->{'x'}[$i - 1];
-                $y = $self->{'y'}[$i] - $self->{'y'}[$i - 1];
-            }
-            $flag |= 16 if ($x == 0);
-            $flag |= 32 if ($y == 0);
-            if (($flag & 16) == 0 && $x < 256 && $x > -256)
-            {
-                $flag |= 2;
-                $flag |= 16 if ($x >= 0);
-            }
-            if (($flag & 32) == 0 && $y < 256 && $y > -256)
-            {
-                $flag |= 4;
-                $flag |= 32 if ($y >= 0);
-            }
-            $self->{' DAT'} .= pack("C", $flag);                    # sorry no repeats
-            $self->{'flags'}[$i] = $flag;
-        }
-        for ($i = 0; $i < $self->{'numPoints'}; $i++)
-        {
-            $flag = $self->{'flags'}[$i];
-            $x = $self->{'x'}[$i] - (($i == 0) ? 0 : $self->{'x'}[$i - 1]);
-            if (($flag & 18) == 0)
-            { $self->{' DAT'} .= TTF_Pack("s", $x); }
-            elsif (($flag & 18) == 18)
-            { $self->{' DAT'} .= pack("C", $x); }
-            elsif (($flag & 18) == 2)
-            { $self->{' DAT'} .= pack("C", -$x); }
-        }
-        for ($i = 0; $i < $self->{'numPoints'}; $i++)
-        {
-            $flag = $self->{'flags'}[$i];
-            $y = $self->{'y'}[$i] - (($i == 0) ? 0 : $self->{'y'}[$i - 1]);
-            if (($flag & 36) == 0)
-            { $self->{' DAT'} .= TTF_Pack("s", $y); }
-            elsif (($flag & 36) == 36)
-            { $self->{' DAT'} .= pack("C", $y); }
-            elsif (($flag & 36) == 4)
-            { $self->{' DAT'} .= pack("C", -$y); }
-        }
-    }
-
-    elsif ($num < 0)
-    {
-        for ($i = 0; $i <= $#{$self->{'comps'}}; $i++)
-        {
-            $comp = $self->{'comps'}[$i];
-            $flag = $comp->{'flag'} & 7158;        # bits 2,10,11,12
-            $flag |= 1 unless ($comp->{'args'}[0] > -129 && $comp->{'args'}[0] < 128
-                    && $comp->{'args'}[1] > -129 && $comp->{'args'}[1] < 128);
-            if (defined $comp->{'scale'})
-            {
-                if ($comp->{'scale'}[1] == 0 && $comp->{'scale'}[2] == 0)
-                {
-                    if ($comp->{'scale'}[0] == $comp->{'scale'}[3])
-                    { $flag |= 8 unless ($comp->{'scale'}[0] == 0
-                                    || abs(abs($comp->{'scale'}[0]) - 1.) < .001); }
-                    else
-                    { $flag |= 64; }
-                } else
-                { $flag |= 128; }
-            }
-            
-            $flag |= 512 if (defined $self->{'metric'} && $self->{'metric'} == $i);
-            if ($i == $#{$self->{'comps'}})
-            { $flag |= 256 if (defined $self->{'instLen'} && $self->{'instLen'} > 0); }
-            else
-            { $flag |= 32; }
-            
-            $self->{' DAT'} .= pack("n", $flag);
-            $self->{' DAT'} .= pack("n", $comp->{'glyph'});
-            $comp->{'flag'} = $flag;
-
-            if ($flag & 1)
-            { $self->{' DAT'} .= TTF_Pack("s2", @{$comp->{'args'}}); }
-            else
-            { $self->{' DAT'} .= pack("CC", @{$comp->{'args'}}); }
-
-            if ($flag & 8)
-            { $self->{' DAT'} .= TTF_Pack("F", $comp->{'scale'}[0]); }
-            elsif ($flag & 64)
-            { $self->{' DAT'} .= TTF_Pack("F2", $comp->{'scale'}[0], $comp->{'scale'}[3]); }
-            elsif ($flag & 128)
-            { $self->{' DAT'} .= TTF_Pack("F4", @{$comp->{'scale'}}); }
-        }
-        if (defined $self->{'instLen'} && $self->{'instLen'} > 0)
-        {
-            $len = $self->{'instLen'};
-            $self->{' DAT'} .= pack("n", $len);
-            $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len));
-        }
-    }
-    $self->{' DAT'} .= "\000" if (length($self->{' DAT'}) & 1);
-    $self->{' OUTLEN'} = length($self->{' DAT'});
-    $self->{' read'} = 2;           # changed from 1 to 2 so we don't read_dat() again
-# we leave numPoints and instLen since maxp stats use this
-    $self;
-}
-
-
-=head2 $g->update_bbox
-
-Updates the bounding box for this glyph according to the points in the glyph
-
-=cut
-
-sub update_bbox
-{
-    my ($self) = @_;
-    my ($num, $maxx, $minx, $maxy, $miny, $i, $comp, $x, $y, $compg);
-
-    return $self unless $self->{' read'} > 1;       # only if read_dat done
-    $miny = $minx = 65537; $maxx = $maxy = -65537;
-    $num = $self->{'numberOfContours'};
-    if ($num > 0)
-    {
-        for ($i = 0; $i < $self->{'numPoints'}; $i++)
-        {
-            ($x, $y) = ($self->{'x'}[$i], $self->{'y'}[$i]);
-
-            $maxx = $x if ($x > $maxx);
-            $minx = $x if ($x < $minx);
-            $maxy = $y if ($y > $maxy);
-            $miny = $y if ($y < $miny);
-        }
-    }
-
-    elsif ($num < 0)
-    {
-        foreach $comp (@{$self->{'comps'}})
-        {
-            my ($gnx, $gny, $gxx, $gxy);
-            my ($sxx, $sxy, $syx, $syy);
-            
-            $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]->read->update_bbox;
-            ($gnx, $gny, $gxx, $gxy) = @{$compg}{'xMin', 'yMin', 'xMax', 'yMax'};
-            if (defined $comp->{'scale'})
-            {
-                ($sxx, $sxy, $syx, $syy) = @{$comp->{'scale'}};
-                ($gnx, $gny, $gxx, $gxy) = ($gnx*$sxx+$gny*$syx + $comp->{'args'}[0],
-                                            $gnx*$sxy+$gny*$syy + $comp->{'args'}[1],
-                                            $gxx*$sxx+$gxy*$syx + $comp->{'args'}[0],
-                                            $gxx*$sxy+$gxy*$syy + $comp->{'args'}[1]);
-            } elsif ($comp->{'args'}[0] || $comp->{'args'}[1])
-            {
-                $gnx += $comp->{'args'}[0];
-                $gny += $comp->{'args'}[1];
-                $gxx += $comp->{'args'}[0];
-                $gxy += $comp->{'args'}[1];
-            }
-            $maxx = $gxx if $gxx > $maxx;
-            $minx = $gnx if $gnx < $minx;
-            $maxy = $gxy if $gxy > $maxy;
-            $miny = $gny if $gny < $miny;
-        }
-    }
-    $self->{'xMax'} = $maxx;
-    $self->{'xMin'} = $minx;
-    $self->{'yMax'} = $maxy;
-    $self->{'yMin'} = $miny;
-    $self;
-}
-
-            
-=head2 $g->maxInfo
-
-Returns lots of information about a glyph so that the C<maxp> table can update
-itself.
-
-=cut
-
-sub maxInfo
-{
-    my ($self) = @_;
-    my (@res, $i, @n);
-
-    $self->read_dat;            # make sure we've read some data
-    $res[4] = length($self->{'hints'}) if defined $self->{'hints'};
-    if ($self->{'numberOfContours'} > 0)
-    {
-        $res[2] = $res[0] = $self->{'numPoints'};
-        $res[3] = $res[1] = $self->{'numberOfContours'};
-        $res[6] = 1;
-    } elsif ($self->{'numberOfContours'} < 0)
-    {
-        $res[6] = 1;
-        for ($i = 0; $i <= $#{$self->{'comps'}}; $i++)
-        {
-            @n = $self->{' PARENT'}{'loca'}{'glyphs'}[$self->{'comps'}[$i]{'glyph'}]->maxInfo;
-            $res[2] += $n[2] == 0 ? $n[0] : $n[2];
-            $res[3] += $n[3] == 0 ? $n[1] : $n[3];
-            $res[5]++;
-            $res[6] = $n[6] + 1 if ($n[6] >= $res[6]);
-        }
-    }
-    @res;
-}
-
-=head2 $g->empty
-
-Empties the glyph of all information to the level of not having been read.
-Useful for saving memory in apps with many glyphs being read
-
-=cut
-
-sub empty
-{
-    my ($self) = @_;
-    my (%keep) = map {(" $_" => 1)} ('LOC', 'OUTLOC', 'PARENT', 'INFILE', 'BASE',
-                                'OUTLEN', 'LEN');
-    map {delete $self->{$_} unless $keep{$_}} keys %$self;
-    
-    $self;
-}
-
-
-=head2 $g->get_points
-
-This method creates point information for a compound glyph. The information is
-stored in the same place as if the glyph was not a compound, but since
-numberOfContours is negative, the glyph is still marked as being a compound
-
-=cut
-
-sub get_points
-{
-    my ($self) = @_;
-    my ($comp, $compg, $nump, $e, $i);
-
-    $self->read_dat;
-    return undef unless ($self->{'numberOfContours'} < 0);
-
-    foreach $comp (@{$self->{'comps'}})
-    {
-        $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]->read;
-        $compg->get_points;
-
-        for ($i = 0; $i < $compg->{'numPoints'}; $i++)
-        {
-            my ($x, $y) = ($compg->{'x'}[$i], $compg->{'y'}[$i]);
-            if (defined $comp->{'scale'})
-            {
-                ($x, $y) = ($x * $comp->{'scale'}[0] + $y * $comp->{'scale'}[2],
-                            $x * $comp->{'scale'}[1] + $y * $comp->{'scale'}[3]);
-            }
-            if (defined $comp->{'args'})
-            { ($x, $y) = ($x + $comp->{'args'}[0], $y + $comp->{'args'}[1]); }
-            push (@{$self->{'x'}}, $x);
-            push (@{$self->{'y'}}, $y);
-        }
-        foreach $e (@{$compg->{'endPoints'}})
-        { push (@{$self->{'endPoints'}}, $e + $nump); }
-        $nump += $compg->{'numPoints'};
-    }
-    $self->{'numPoints'} = $nump;
-    $self;
-}
-
-
-=head2 $g->get_refs
-
-Returns an array of all the glyph ids that are used to make up this glyph. That
-is all the compounds and their references and so on. If this glyph is not a
-compound, then returns an empty array
-
-=cut
-
-sub get_refs
-{
-    my ($self) = @_;
-    my (@res, $g);
-
-    $self->read_dat;
-    return unless ($self->{'numberOfContours'} < 0);
-    foreach $g (@{$self->{'comps'}})
-    {
-        my (@list) = $self->{' PARENT'}{'loca'}{'glyphs'}[$g->{'glyph'}]->get_points;
-        push (@res, $g->{'glyph'});
-        push (@res, @list) if ($list[0]);
-    }
-    return @res;
-}
-
-1;
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-The instance variables used here are somewhat clunky and inconsistent with
-the other tables.
-
-=item *
-
-C<update> doesn't re-calculate the bounding box or C<numberOfContours>.
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
+package Font::TTF::Glyph;
+
+=head1 NAME
+
+Font::TTF::Glyph - Holds a single glyph's information
+
+=head1 DESCRIPTION
+
+This is a single glyph description as held in a TT font. On creation only its
+header is read. Thus you can get the bounding box of each glyph without having
+to read all the other information.
+
+=head1 INSTANCE VARIABLES
+
+In addition to the named variables in a glyph header (C<xMin> etc.), there are
+also all capital instance variables for holding working information, mostly
+from the location table.
+
+The standard attributes each glyph has are:
+
+ numberOfContours
+ xMin
+ yMin
+ xMax
+ yMax
+
+There are also other, derived, instance variables for each glyph which are read
+when the whole glyph is read (via C<read_dat>):
+
+=over 4
+
+=item instLen
+
+Number of bytes in the hinting instructions (Warning this variable is deprecated,
+use C<length($g->{'hints'})> instead).
+
+=item hints
+
+The string containing the hinting code for the glyph
+
+=back
+
+In addition there are other attribute like instance variables for simple glyphs:
+
+=over 4
+
+For each contour there is:
+
+=over 4
+
+=item endPoints
+
+An array of endpoints for each contour in the glyph. There are
+C<numberOfContours> contours in a glyph. The number of points in a glyph is
+equal to the highest endpoint of a contour.
+
+=back
+
+There are also a number of arrays indexed by point number
+
+=over 4
+
+=item flags
+
+The flags associated with reading this point. The flags for a point are
+recalculated for a point when it is C<update>d. Thus the flags are not very
+useful. The only important bit is bit 0 which indicates whether the point is
+an 'on' curve point, or an 'off' curve point.
+
+=item x
+
+The absolute x co-ordinate of the point.
+
+=item y
+
+The absolute y co-ordinate of the point
+
+=back
+
+=back
+
+For composite glyphs there are other variables
+
+=over 4
+
+=item metric
+
+This holds the component number (not its glyph number) of the component from
+which the metrics for this glyph should be taken.
+
+=item comps
+
+This is an array of hashes for each component. Each hash has a number of
+elements:
+
+=over 4
+
+=item glyph
+
+The glyph number of the glyph which comprises this component of the composite.
+
+=item args
+
+An array of two arguments which may be an x, y co-ordinate or two attachment
+points (one on the base glyph the other on the component). See flags for details.
+
+=item flag
+
+The flag for this component
+
+=item scale
+
+A 4 number array for component scaling. This allows stretching, rotating, etc.
+Note that scaling applies to placement co-ordinates (rather than attachment points)
+before locating rather than after.
+
+=back
+
+=item numPoints
+
+This is a generated value which contains the number of components read in for this
+compound glyph.
+
+=back
+
+The private instance variables are:
+
+=over 4
+
+=item INFILE (P)
+
+The input file form which to read any information
+
+=item LOC (P)
+
+Location relative to the start of the glyf table in the read file
+
+=item BASE (P)
+
+The location of the glyf table in the read file
+
+=item LEN (P)
+
+This is the number of bytes required by the glyph. It should be kept up to date
+by calling the C<update> method whenever any of the glyph content changes.
+
+=item OUTLOC (P)
+
+Location relative to the start of the glyf table. This variable is only active
+whilst the output process is going on. It is used to inform the location table
+where the glyph's location is, since the glyf table is output before the loca
+table due to alphabetical ordering.
+
+=item OUTLEN (P)
+
+This indicates the length of the glyph data when it is output. This more
+accurately reflects the internal memory form than the C<LEN> variable which
+only reflects the read file length. The C<OUTLEN> variable is only set after
+calling C<out> or C<out_dat>.
+
+=back
+
+=head2 Editing
+
+If you want to edit a glyph in some way, then you should read_dat the glyph, then
+make your changes and then update the glyph or set the $g->{' isdirty'} variable.
+It is the application's duty to ensure that the following instance variables are
+correct, from which update will calculate the rest, including the bounding box
+information.
+
+    numPoints
+    numberOfContours
+    endPoints
+    x, y, flags         (only flags bit 0)
+    instLen
+    hints
+
+For components, the numPoints, x, y, endPoints & flags are not required but
+the following information is required for each component.
+
+    flag                (bits 2, 10, 11, 12)
+    glyph
+    args
+    scale
+    metric              (glyph instance variable)
+    
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(%fields @field_info);
+use Font::TTF::Utils;
+use Font::TTF::Table;
+
+ at field_info = (
+    'numberOfContours' => 's', 
+    'xMin' => 's', 
+    'yMin' => 's',
+    'xMax' => 's',
+    'yMax' => 's');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head1 Font::TTF::Glyph->new(%parms)
+
+Creates a new glyph setting various instance variables
+
+=cut
+
+sub new
+{
+    my ($class, %parms) = @_;
+    my ($self) = {};
+    my ($p);
+
+    bless $self, $class;
+    foreach $p (keys %parms)
+    { $self->{" $p"} = $parms{$p}; }
+    init unless defined $fields{'xMin'};
+    $self;
+}
+
+
+=head2 $g->read
+
+Reads the header component of the glyph (bounding box, etc.) and also the
+glyph content, but into a data field rather than breaking it down into
+its constituent structures. Use read_dat for this.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($dat);
+
+    return $self if $self->{' read'};
+    $self->{' read'} = 1;
+    $fh->seek($self->{' LOC'} + $self->{' BASE'}, 0);
+    $fh->read($self->{' DAT'}, $self->{' LEN'});
+    TTF_Read_Fields($self, $self->{' DAT'}, \%fields);
+    $self;
+}
+
+
+=head2 $g->read_dat
+
+Reads the contents of the glyph (components and curves, etc.) from the memory
+store C<DAT> into structures within the object. Then, to indicate where the
+master form of the data is, it deletes the C<DAT> instance variable.
+
+=cut
+
+sub read_dat
+{
+    my ($self) = @_;
+    my ($dat, $num, $max, $i, $flag, $len, $val, $val1, $fp);
+
+    return $self if $self->{' read'} > 1;
+    $self->read unless $self->{' read'};
+    $dat = $self->{' DAT'};
+    $fp = 10;
+    $num = $self->{'numberOfContours'};
+    if ($num > 0)
+    {
+        $self->{'endPoints'} = [unpack("n*", substr($dat, $fp, $num << 1))];
+        $fp += $num << 1;
+        $max = 0;
+        foreach (@{$self->{'endPoints'}})
+        { $max = $_ if $_ > $max; }
+        $max++;
+        $self->{'numPoints'} = $max;
+        $self->{'instLen'} = unpack("n", substr($dat, $fp));
+        $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'});
+        $fp += 2 + $self->{'instLen'};
+# read the flags array
+        for ($i = 0; $i < $max; $i++)                   
+        {
+            $flag = unpack("C", substr($dat, $fp++));
+            $self->{'flags'}[$i] = $flag;
+            if ($flag & 8)
+            {
+                $len = unpack("C", substr($dat, $fp++));
+                while ($len-- > 0)
+                {
+                    $i++;
+                    $self->{'flags'}[$i] = $flag;
+                }
+            }
+        }
+#read the x array
+        for ($i = 0; $i < $max; $i++)
+        {
+            $flag = $self->{'flags'}[$i];
+            if ($flag & 2)
+            {
+                $val = unpack("C", substr($dat, $fp++));
+                $val = -$val unless ($flag & 16);
+            } elsif ($flag & 16)
+            { $val = 0; }
+            else
+            {
+                $val = TTF_Unpack("s", substr($dat, $fp));
+                $fp += 2;
+            }
+            $self->{'x'}[$i] = $i == 0 ? $val : $self->{'x'}[$i - 1] + $val;
+        }
+#read the y array
+        for ($i = 0; $i < $max; $i++)
+        {
+            $flag = $self->{'flags'}[$i];
+            if ($flag & 4)
+            {
+                $val = unpack("C", substr($dat, $fp++));
+                $val = -$val unless ($flag & 32);
+            } elsif ($flag & 32)
+            { $val = 0; }
+            else
+            {
+                $val = TTF_Unpack("s", substr($dat, $fp));
+                $fp += 2;
+            }
+            $self->{'y'}[$i] = $i == 0 ? $val : $self->{'y'}[$i - 1] + $val;
+        }
+    }
+    
+# compound glyph
+    elsif ($num < 0)
+    {
+        $flag = 1 << 5;             # cheat to get the loop going
+        for ($i = 0; $flag & 32; $i++)
+        {
+            ($flag, $self->{'comps'}[$i]{'glyph'}) = unpack("n2", substr($dat, $fp));
+            $fp += 4;
+            $self->{'comps'}[$i]{'flag'} = $flag;
+            if ($flag & 1)              # ARGS1_AND_2_ARE_WORDS
+            {
+                $self->{'comps'}[$i]{'args'} = [TTF_Unpack("s2", substr($dat, $fp))];
+                $fp += 4;
+            } else
+            {
+                $self->{'comps'}[$i]{'args'} = [unpack("c2", substr($dat, $fp))];
+                $fp += 2;
+            }
+            
+            if ($flag & 8)
+            {
+                $val = TTF_Unpack("F", substr($dat, $fp));
+                $fp += 2;
+                $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val];
+            } elsif ($flag & 64)
+            {
+                ($val, $val1) = TTF_Unpack("F2", substr($dat, $fp));
+                $fp += 4;
+                $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val1];
+            } elsif ($flag & 128)
+            {
+                $self->{'comps'}[$i]{'scale'} = [TTF_Unpack("F4", substr($dat, $fp))];
+                $fp += 8;
+            }
+            $self->{'metric'} = $i if ($flag & 512);
+        }
+        $self->{'numPoints'} = $i;
+        if ($flag & 256)            # HAVE_INSTRUCTIONS
+        {
+            $self->{'instLen'} = unpack("n", substr($dat, $fp));
+            $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'});
+            $fp += 2 + $self->{'instLen'};
+        }
+    }
+    return undef if ($fp > length($dat));
+    $self->{' read'} = 2;
+    $self;
+}
+
+
+=head2 $g->out($fh)
+
+Writes the glyph data to outfile
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    $self->read unless $self->{' read'};
+    $self->update if $self->{' isDirty'};
+    $fh->print($self->{' DAT'});
+    $self->{' OUTLEN'} = length($self->{' DAT'});
+    $self;
+}
+
+
+=head2 $g->out_xml($context, $depth)
+
+Outputs an XML description of the glyph
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($addr) = ($self =~ m/\((.+)\)$/o);
+    my ($k, $ndepth);
+
+    if ($context->{'addresses'}{$addr})
+    {
+        $context->{'fh'}->printf("%s<glyph gid='%s' id_ref='%s'/>\n", $depth, $context->{'gid'}, $addr);
+        return $self;
+    }
+    else
+    {
+        $context->{'fh'}->printf("%s<glyph gid='%s' id='%s'>\n", $depth, $context->{'gid'}, $addr);
+    }
+    
+    $ndepth = $depth . $context->{'indent'};
+    $self->read_dat;
+    foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self})
+    {
+        $self->XML_element($context, $ndepth, $k, $self->{$k});
+    }
+    $context->{'fh'}->print("$depth</glyph>\n");
+    delete $context->{'done_points'};
+    $self;
+}
+    
+
+sub XML_element
+{
+    my ($self, $context, $depth, $key, $val) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($dind) = $depth . $context->{'indent'};
+    my ($i);
+    
+    if ($self->{'numberOfContours'} >= 0 && ($key eq 'x' || $key eq 'y' || $key eq 'flags'))
+    {
+        return $self if ($context->{'done_points'});
+        $context->{'done_points'} = 1;
+
+        $fh->print("$depth<points>\n");
+        for ($i = 0; $i <= $#{$self->{'flags'}}; $i++)
+        { $fh->printf("%s<point x='%s' y='%s' flags='0x%02X'/>\n", $dind,
+                $self->{'x'}[$i], $self->{'y'}[$i], $self->{'flags'}[$i]); }
+        $fh->print("$depth</points>\n");
+    }
+    elsif ($key eq 'hints')
+    {
+        my ($dat);
+        $fh->print("$depth<hints>\n");
+#        Font::TTF::Utils::XML_hexdump($context, $depth . $context->{'indent'}, $self->{'hints'});
+        $dat = Font::TTF::Utils::XML_binhint($self->{'hints'});
+        $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/mg;
+        $fh->print("$depth$context->{'indent'}$dat");
+        $fh->print("$depth</hints>\n");
+    }
+    else
+    { return Font::TTF::Table::XML_element(@_); }
+
+    $self;    
+}
+
+
+=head2 $g->update
+
+Generates a C<$self->{'DAT'}> from the internal structures, if the data has
+been read into structures in the first place. If you are building a glyph
+from scratch you will need to set the instance variable C<' read'> to 2 (or
+something > 1) for the update to work.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($dat, $loc, $len, $flag, $x, $y, $i, $comp, $num);
+
+    return $self unless (defined $self->{' read'} && $self->{' read'} > 1);
+    $self->update_bbox;
+    $self->{' DAT'} = TTF_Out_Fields($self, \%fields, 10);
+    $num = $self->{'numberOfContours'};
+    if ($num > 0)
+    {
+        $self->{' DAT'} .= pack("n*", @{$self->{'endPoints'}});
+        $len = $self->{'instLen'};
+        $self->{' DAT'} .= pack("n", $len);
+        $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)) if ($len > 0);
+        for ($i = 0; $i < $self->{'numPoints'}; $i++)
+        {
+            $flag = $self->{'flags'}[$i] & 1;
+            if ($i == 0)
+            {
+                $x = $self->{'x'}[$i];
+                $y = $self->{'y'}[$i];
+            } else
+            {
+                $x = $self->{'x'}[$i] - $self->{'x'}[$i - 1];
+                $y = $self->{'y'}[$i] - $self->{'y'}[$i - 1];
+            }
+            $flag |= 16 if ($x == 0);
+            $flag |= 32 if ($y == 0);
+            if (($flag & 16) == 0 && $x < 256 && $x > -256)
+            {
+                $flag |= 2;
+                $flag |= 16 if ($x >= 0);
+            }
+            if (($flag & 32) == 0 && $y < 256 && $y > -256)
+            {
+                $flag |= 4;
+                $flag |= 32 if ($y >= 0);
+            }
+            $self->{' DAT'} .= pack("C", $flag);                    # sorry no repeats
+            $self->{'flags'}[$i] = $flag;
+        }
+        for ($i = 0; $i < $self->{'numPoints'}; $i++)
+        {
+            $flag = $self->{'flags'}[$i];
+            $x = $self->{'x'}[$i] - (($i == 0) ? 0 : $self->{'x'}[$i - 1]);
+            if (($flag & 18) == 0)
+            { $self->{' DAT'} .= TTF_Pack("s", $x); }
+            elsif (($flag & 18) == 18)
+            { $self->{' DAT'} .= pack("C", $x); }
+            elsif (($flag & 18) == 2)
+            { $self->{' DAT'} .= pack("C", -$x); }
+        }
+        for ($i = 0; $i < $self->{'numPoints'}; $i++)
+        {
+            $flag = $self->{'flags'}[$i];
+            $y = $self->{'y'}[$i] - (($i == 0) ? 0 : $self->{'y'}[$i - 1]);
+            if (($flag & 36) == 0)
+            { $self->{' DAT'} .= TTF_Pack("s", $y); }
+            elsif (($flag & 36) == 36)
+            { $self->{' DAT'} .= pack("C", $y); }
+            elsif (($flag & 36) == 4)
+            { $self->{' DAT'} .= pack("C", -$y); }
+        }
+    }
+
+    elsif ($num < 0)
+    {
+        for ($i = 0; $i <= $#{$self->{'comps'}}; $i++)
+        {
+            $comp = $self->{'comps'}[$i];
+            $flag = $comp->{'flag'} & 7158;        # bits 2,10,11,12
+            $flag |= 1 unless ($comp->{'args'}[0] > -129 && $comp->{'args'}[0] < 128
+                    && $comp->{'args'}[1] > -129 && $comp->{'args'}[1] < 128);
+            if (defined $comp->{'scale'})
+            {
+                if ($comp->{'scale'}[1] == 0 && $comp->{'scale'}[2] == 0)
+                {
+                    if ($comp->{'scale'}[0] == $comp->{'scale'}[3])
+                    { $flag |= 8 unless ($comp->{'scale'}[0] == 0
+                                    || abs(abs($comp->{'scale'}[0]) - 1.) < .001); }
+                    else
+                    { $flag |= 64; }
+                } else
+                { $flag |= 128; }
+            }
+            
+            $flag |= 512 if (defined $self->{'metric'} && $self->{'metric'} == $i);
+            if ($i == $#{$self->{'comps'}})
+            { $flag |= 256 if (defined $self->{'instLen'} && $self->{'instLen'} > 0); }
+            else
+            { $flag |= 32; }
+            
+            $self->{' DAT'} .= pack("n", $flag);
+            $self->{' DAT'} .= pack("n", $comp->{'glyph'});
+            $comp->{'flag'} = $flag;
+
+            if ($flag & 1)
+            { $self->{' DAT'} .= TTF_Pack("s2", @{$comp->{'args'}}); }
+            else
+            { $self->{' DAT'} .= pack("CC", @{$comp->{'args'}}); }
+
+            if ($flag & 8)
+            { $self->{' DAT'} .= TTF_Pack("F", $comp->{'scale'}[0]); }
+            elsif ($flag & 64)
+            { $self->{' DAT'} .= TTF_Pack("F2", $comp->{'scale'}[0], $comp->{'scale'}[3]); }
+            elsif ($flag & 128)
+            { $self->{' DAT'} .= TTF_Pack("F4", @{$comp->{'scale'}}); }
+        }
+        if (defined $self->{'instLen'} && $self->{'instLen'} > 0)
+        {
+            $len = $self->{'instLen'};
+            $self->{' DAT'} .= pack("n", $len);
+            $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len));
+        }
+    }
+    $self->{' DAT'} .= "\000" if (length($self->{' DAT'}) & 1);
+    $self->{' OUTLEN'} = length($self->{' DAT'});
+    $self->{' read'} = 2;           # changed from 1 to 2 so we don't read_dat() again
+# we leave numPoints and instLen since maxp stats use this
+    $self;
+}
+
+
+=head2 $g->update_bbox
+
+Updates the bounding box for this glyph according to the points in the glyph
+
+=cut
+
+sub update_bbox
+{
+    my ($self) = @_;
+    my ($num, $maxx, $minx, $maxy, $miny, $i, $comp, $x, $y, $compg);
+
+    return $self unless $self->{' read'} > 1;       # only if read_dat done
+    $miny = $minx = 65537; $maxx = $maxy = -65537;
+    $num = $self->{'numberOfContours'};
+    if ($num > 0)
+    {
+        for ($i = 0; $i < $self->{'numPoints'}; $i++)
+        {
+            ($x, $y) = ($self->{'x'}[$i], $self->{'y'}[$i]);
+
+            $maxx = $x if ($x > $maxx);
+            $minx = $x if ($x < $minx);
+            $maxy = $y if ($y > $maxy);
+            $miny = $y if ($y < $miny);
+        }
+    }
+
+    elsif ($num < 0)
+    {
+        foreach $comp (@{$self->{'comps'}})
+        {
+            my ($gnx, $gny, $gxx, $gxy);
+            my ($sxx, $sxy, $syx, $syy);
+            
+            $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]->read->update_bbox;
+            ($gnx, $gny, $gxx, $gxy) = @{$compg}{'xMin', 'yMin', 'xMax', 'yMax'};
+            if (defined $comp->{'scale'})
+            {
+                ($sxx, $sxy, $syx, $syy) = @{$comp->{'scale'}};
+                ($gnx, $gny, $gxx, $gxy) = ($gnx*$sxx+$gny*$syx + $comp->{'args'}[0],
+                                            $gnx*$sxy+$gny*$syy + $comp->{'args'}[1],
+                                            $gxx*$sxx+$gxy*$syx + $comp->{'args'}[0],
+                                            $gxx*$sxy+$gxy*$syy + $comp->{'args'}[1]);
+            } elsif ($comp->{'args'}[0] || $comp->{'args'}[1])
+            {
+                $gnx += $comp->{'args'}[0];
+                $gny += $comp->{'args'}[1];
+                $gxx += $comp->{'args'}[0];
+                $gxy += $comp->{'args'}[1];
+            }
+            $maxx = $gxx if $gxx > $maxx;
+            $minx = $gnx if $gnx < $minx;
+            $maxy = $gxy if $gxy > $maxy;
+            $miny = $gny if $gny < $miny;
+        }
+    }
+    $self->{'xMax'} = $maxx;
+    $self->{'xMin'} = $minx;
+    $self->{'yMax'} = $maxy;
+    $self->{'yMin'} = $miny;
+    $self;
+}
+
+            
+=head2 $g->maxInfo
+
+Returns lots of information about a glyph so that the C<maxp> table can update
+itself.
+
+=cut
+
+sub maxInfo
+{
+    my ($self) = @_;
+    my (@res, $i, @n);
+
+    $self->read_dat;            # make sure we've read some data
+    $res[4] = length($self->{'hints'}) if defined $self->{'hints'};
+    if ($self->{'numberOfContours'} > 0)
+    {
+        $res[2] = $res[0] = $self->{'numPoints'};
+        $res[3] = $res[1] = $self->{'numberOfContours'};
+        $res[6] = 1;
+    } elsif ($self->{'numberOfContours'} < 0)
+    {
+        $res[6] = 1;
+        for ($i = 0; $i <= $#{$self->{'comps'}}; $i++)
+        {
+            @n = $self->{' PARENT'}{'loca'}{'glyphs'}[$self->{'comps'}[$i]{'glyph'}]->maxInfo;
+            $res[2] += $n[2] == 0 ? $n[0] : $n[2];
+            $res[3] += $n[3] == 0 ? $n[1] : $n[3];
+            $res[5]++;
+            $res[6] = $n[6] + 1 if ($n[6] >= $res[6]);
+        }
+    }
+    @res;
+}
+
+=head2 $g->empty
+
+Empties the glyph of all information to the level of not having been read.
+Useful for saving memory in apps with many glyphs being read
+
+=cut
+
+sub empty
+{
+    my ($self) = @_;
+    my (%keep) = map {(" $_" => 1)} ('LOC', 'OUTLOC', 'PARENT', 'INFILE', 'BASE',
+                                'OUTLEN', 'LEN');
+    map {delete $self->{$_} unless $keep{$_}} keys %$self;
+    
+    $self;
+}
+
+
+=head2 $g->get_points
+
+This method creates point information for a compound glyph. The information is
+stored in the same place as if the glyph was not a compound, but since
+numberOfContours is negative, the glyph is still marked as being a compound
+
+=cut
+
+sub get_points
+{
+    my ($self) = @_;
+    my ($comp, $compg, $nump, $e, $i);
+
+    $self->read_dat;
+    return undef unless ($self->{'numberOfContours'} < 0);
+
+    foreach $comp (@{$self->{'comps'}})
+    {
+        $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]->read;
+        $compg->get_points;
+
+        for ($i = 0; $i < $compg->{'numPoints'}; $i++)
+        {
+            my ($x, $y) = ($compg->{'x'}[$i], $compg->{'y'}[$i]);
+            if (defined $comp->{'scale'})
+            {
+                ($x, $y) = ($x * $comp->{'scale'}[0] + $y * $comp->{'scale'}[2],
+                            $x * $comp->{'scale'}[1] + $y * $comp->{'scale'}[3]);
+            }
+            if (defined $comp->{'args'})
+            { ($x, $y) = ($x + $comp->{'args'}[0], $y + $comp->{'args'}[1]); }
+            push (@{$self->{'x'}}, $x);
+            push (@{$self->{'y'}}, $y);
+        }
+        foreach $e (@{$compg->{'endPoints'}})
+        { push (@{$self->{'endPoints'}}, $e + $nump); }
+        $nump += $compg->{'numPoints'};
+    }
+    $self->{'numPoints'} = $nump;
+    $self;
+}
+
+
+=head2 $g->get_refs
+
+Returns an array of all the glyph ids that are used to make up this glyph. That
+is all the compounds and their references and so on. If this glyph is not a
+compound, then returns an empty array
+
+=cut
+
+sub get_refs
+{
+    my ($self) = @_;
+    my (@res, $g);
+
+    $self->read_dat;
+    return unless ($self->{'numberOfContours'} < 0);
+    foreach $g (@{$self->{'comps'}})
+    {
+        my (@list) = $self->{' PARENT'}{'loca'}{'glyphs'}[$g->{'glyph'}]->get_points;
+        push (@res, $g->{'glyph'});
+        push (@res, @list) if ($list[0]);
+    }
+    return @res;
+}
+
+1;
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+The instance variables used here are somewhat clunky and inconsistent with
+the other tables.
+
+=item *
+
+C<update> doesn't re-calculate the bounding box or C<numberOfContours>.
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hdmx.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hdmx.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hdmx.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,149 +1,149 @@
-package Font::TTF::Hdmx;
-
-=head1 NAME
-
-Font::TTF::Hdmx - Horizontal device metrics
-
-=head1 DESCRIPTION
-
-The table consists of an hash of device metric tables indexed by the ppem for
-that subtable. Each subtable consists of an array of advance widths in pixels
-for each glyph at that ppem (horizontally).
-
-=head1 INSTANCE VARIABLES
-
-Individual metrics are accessed using the following referencing:
-
-    $f->{'hdmx'}{$ppem}[$glyph_num]
-
-In addition there is one instance variable:
-
-=over 4
-
-=item Num
-
-Number of device tables.
-
-=back
-
-=head2 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-
- at ISA = qw(Font::TTF::Table);
-
-
-=head2 $t->read
-
-Reads the table into data structures
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($numg, $ppem, $i, $numt, $dat, $len);
-
-    $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    $self->SUPER::read or return $self;
-
-    $fh->read($dat, 8);
-    ($self->{'Version'}, $numt, $len) = unpack("nnN", $dat);
-    $self->{'Num'} = $numt;
-
-    for ($i = 0; $i < $numt; $i++)
-    {
-        $fh->read($dat, $len);
-        $ppem = unpack("C", $dat);
-        $self->{$ppem} = [unpack("C$numg", substr($dat, 2))];
-    }
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Outputs the device metrics for this font
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($numg, $i, $pad, $len, $numt, @ppem, $max);
-
-    return $self->SUPER::out($fh) unless ($self->{' read'});
-
-    $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    @ppem = grep(/^\d+$/, sort {$a <=> $b} keys %$self);
-    $pad = "\000" x (3 - ($numg + 1) % 4);
-    $len = $numg + 2 + length($pad);
-    $fh->print(pack("nnN", 0, $#ppem + 1, $len));
-    for $i (@ppem)
-    {
-        $max = 0;
-        foreach (@{$self->{$i}}[0..($numg - 1)])
-        { $max = $_ if $_ > $max; }
-        $fh->print(pack("C*", $i, $max, @{$self->{$i}}[0..($numg - 1)]) . $pad);
-    }
-    $self;
-}
-
-
-=head2 $t->tables_do(&func)
-
-For each subtable it calls &sub($ref, $ppem)
-
-=cut
-
-sub tables_do
-{
-    my ($self, $func) = @_;
-    my ($i);
-
-    foreach $i (grep(/^\d+$/, %$self))
-    { &$func($self->{$i}, $i); }
-    $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $key, $value)
-
-Outputs device metrics a little more tidily
-
-=cut
-
-sub XML_element
-{
-    my ($self) = shift;
-    my ($context, $depth, $key, $value) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($i);
-
-    return $self->SUPER::XML_element(@_) if (ref($value) ne 'ARRAY');
-    $fh->print("$depth<metrics ppem='$key'>\n");
-    for ($i = 0; $i <= $#{$value}; $i += 25)
-    {
-        $fh->print("$depth$context->{'indent'}". join(' ', @{$value}[$i .. $i + 24]) . "\n");
-    }
-    $fh->print("$depth</metrics>\n");
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Hdmx;
+
+=head1 NAME
+
+Font::TTF::Hdmx - Horizontal device metrics
+
+=head1 DESCRIPTION
+
+The table consists of an hash of device metric tables indexed by the ppem for
+that subtable. Each subtable consists of an array of advance widths in pixels
+for each glyph at that ppem (horizontally).
+
+=head1 INSTANCE VARIABLES
+
+Individual metrics are accessed using the following referencing:
+
+    $f->{'hdmx'}{$ppem}[$glyph_num]
+
+In addition there is one instance variable:
+
+=over 4
+
+=item Num
+
+Number of device tables.
+
+=back
+
+=head2 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+
+ at ISA = qw(Font::TTF::Table);
+
+
+=head2 $t->read
+
+Reads the table into data structures
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($numg, $ppem, $i, $numt, $dat, $len);
+
+    $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    $self->SUPER::read or return $self;
+
+    $fh->read($dat, 8);
+    ($self->{'Version'}, $numt, $len) = unpack("nnN", $dat);
+    $self->{'Num'} = $numt;
+
+    for ($i = 0; $i < $numt; $i++)
+    {
+        $fh->read($dat, $len);
+        $ppem = unpack("C", $dat);
+        $self->{$ppem} = [unpack("C$numg", substr($dat, 2))];
+    }
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Outputs the device metrics for this font
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($numg, $i, $pad, $len, $numt, @ppem, $max);
+
+    return $self->SUPER::out($fh) unless ($self->{' read'});
+
+    $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    @ppem = grep(/^\d+$/, sort {$a <=> $b} keys %$self);
+    $pad = "\000" x (3 - ($numg + 1) % 4);
+    $len = $numg + 2 + length($pad);
+    $fh->print(pack("nnN", 0, $#ppem + 1, $len));
+    for $i (@ppem)
+    {
+        $max = 0;
+        foreach (@{$self->{$i}}[0..($numg - 1)])
+        { $max = $_ if $_ > $max; }
+        $fh->print(pack("C*", $i, $max, @{$self->{$i}}[0..($numg - 1)]) . $pad);
+    }
+    $self;
+}
+
+
+=head2 $t->tables_do(&func)
+
+For each subtable it calls &sub($ref, $ppem)
+
+=cut
+
+sub tables_do
+{
+    my ($self, $func) = @_;
+    my ($i);
+
+    foreach $i (grep(/^\d+$/, %$self))
+    { &$func($self->{$i}, $i); }
+    $self;
+}
+
+
+=head2 $t->XML_element($context, $depth, $key, $value)
+
+Outputs device metrics a little more tidily
+
+=cut
+
+sub XML_element
+{
+    my ($self) = shift;
+    my ($context, $depth, $key, $value) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($i);
+
+    return $self->SUPER::XML_element(@_) if (ref($value) ne 'ARRAY');
+    $fh->print("$depth<metrics ppem='$key'>\n");
+    for ($i = 0; $i <= $#{$value}; $i += 25)
+    {
+        $fh->print("$depth$context->{'indent'}". join(' ', @{$value}[$i .. $i + 24]) . "\n");
+    }
+    $fh->print("$depth</metrics>\n");
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Head.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Head.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Head.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,250 +1,250 @@
-package Font::TTF::Head;
-
-=head1 NAME
-
-Font::TTF::Head - The head table for a TTF Font
-
-=head1 DESCRIPTION
-
-This is a very basic table with just instance variables as described in the
-TTF documentation, using the same names. One of the most commonly used is
-C<unitsPerEm>.
-
-=head1 INSTANCE VARIABLES
-
-The C<head> table has no internal instance variables beyond those common to all
-tables and those specified in the standard:
-
-    version
-    fontRevision
-    checkSumAdjustment
-    magicNumber
-    flags
-    unitsPerEm
-    created
-    modified
-    xMin
-    yMin
-    xMax
-    yMax
-    macStyle
-    lowestRecPPEM
-    fontDirectionHint
-    indexToLocFormat
-    glyphDataFormat
-
-The two dates are held as an array of two unsigned longs (32-bits)
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-
-require Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'version' => 'f',
-    'fontRevision' => 'f',
-    'checkSumAdjustment' => 'L',
-    'magicNumber' => 'L',
-    'flags' => 'S',
-    'unitsPerEm' => 'S',
-    'created' => 'L2',
-    'modified' => 'L2',
-    'xMin' => 's',
-    'yMin' => 's',
-    'xMax' => 's',
-    'yMax' => 's',
-    'macStyle' => 'S',
-    'lowestRecPPEM' => 'S',
-    'fontDirectionHint' => 's',
-    'indexToLocFormat' => 's',
-    'glyphDataFormat' => 's');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory thanks to some utility functions
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read || return $self;
-
-    init unless defined $fields{'Ascender'};
-    $self->{' INFILE'}->read($dat, 54);
-
-    TTF_Read_Fields($self, $dat, \%fields);
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying. If in memory
-(which is usually) the checkSumAdjustment field is set to 0 as per the default
-if the file checksum is not to be considered.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};      # this is never true
-#    $self->{'checkSumAdjustment'} = 0 unless $self->{' PARENT'}{' wantsig'};
-    $fh->print(TTF_Out_Fields($self, \%fields, 54));
-    $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $key, $value)
-
-Handles date process for the XML exporter
-
-=cut
-
-sub XML_element
-{
-    my ($self) = shift;
-    my ($context, $depth, $key, $value) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($output, @time);
-    my (@month) = qw(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC);
-
-    return $self->SUPER::XML_element(@_) unless ($key eq 'created' || $key eq 'modified');
-
-    @time = gmtime($self->getdate($key eq 'created'));
-    $output = sprintf("%d/%s/%d %d:%d:%d", $time[3], $month[$time[4]], $time[5] + 1900,
-            $time[2], $time[1], $time[0]);
-    $fh->print("$depth<$key>$output</$key>\n");
-    $self;
-}
-    
-
-=head2 $t->update
-
-Updates the head table based on the glyph data and the hmtx table
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($num, $i, $loc, $hmtx);
-    my ($xMin, $yMin, $xMax, $yMax, $lsbx);
-
-    return undef unless ($self->SUPER::update);
-
-    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    return undef unless (defined $self->{' PARENT'}{'hmtx'} && defined $self->{' PARENT'}{'loca'});
-    $hmtx = $self->{' PARENT'}{'hmtx'}->read;
-    
-    $self->{' PARENT'}{'loca'}->update;
-    $hmtx->update;              # if we updated, then the flags will be set anyway.
-    $lsbx = 1;
-    for ($i = 0; $i < $num; $i++)
-    {
-        $loc = $self->{' PARENT'}{'loca'}{'glyphs'}[$i];
-        next unless defined $loc;
-        $loc->read->update_bbox;
-        $xMin = $loc->{'xMin'} if ($loc->{'xMin'} < $xMin || $i == 0);
-        $yMin = $loc->{'yMin'} if ($loc->{'yMin'} < $yMin || $i == 0);
-        $xMax = $loc->{'xMax'} if ($loc->{'xMax'} > $xMax);
-        $yMax = $loc->{'yMax'} if ($loc->{'yMax'} > $yMax);
-        $lsbx &= ($loc->{'xMin'} == $hmtx->{'lsb'}[$i]);
-    }
-    $self->{'xMin'} = $xMin;
-    $self->{'yMin'} = $yMin;
-    $self->{'xMax'} = $xMax;
-    $self->{'yMax'} = $yMax;
-    if ($lsbx)
-    { $self->{'flags'} |= 2; }
-    else
-    { $self->{'flags'} &= ~2; }
-    $self;
-}
-
-
-=head2 $t->getdate($is_create)
-
-Converts font modification time (or creation time if $is_create is set) to a 32-bit integer as returned
-from time(). Returns undef if the value is out of range, either before the epoch or after the maximum
-storable time.
-
-=cut
-
-sub getdate
-{
-    my ($self, $is_create) = @_;
-    my ($arr) = $self->{$is_create ? 'created' : 'modified'};
-
-    $arr->[1] -= 2082844800;        # seconds between 1/Jan/1904 and 1/Jan/1970 (midnight)
-    if ($arr->[1] < 0)
-    {
-        $arr->[1] += 0xFFFFFFF; $arr->[1]++;
-        $arr->[0]--;
-    }
-    return undef if $arr->[0] != 0;
-    return $arr->[1];
-}
-
-
-=head2 $t->setdate($time, $is_create)
-
-Sets the time information for modification (or creation time if $is_create is set) according to the 32-bit
-time information.
-
-=cut
-
-sub setdate
-{
-    my ($self, $time, $is_create) = @_;
-    my (@arr);
-
-    $arr[1] = $time;
-    if ($arr[1] >= 0x83DA4F80)
-    {
-        $arr[1] -= 0xFFFFFFFF;
-        $arr[1]--;
-        $arr[0]++;
-    }
-    $arr[1] += 2082844800;
-    $self->{$is_create ? 'created' : 'modified'} = \@arr;
-    $self;
-}
-    
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Head;
+
+=head1 NAME
+
+Font::TTF::Head - The head table for a TTF Font
+
+=head1 DESCRIPTION
+
+This is a very basic table with just instance variables as described in the
+TTF documentation, using the same names. One of the most commonly used is
+C<unitsPerEm>.
+
+=head1 INSTANCE VARIABLES
+
+The C<head> table has no internal instance variables beyond those common to all
+tables and those specified in the standard:
+
+    version
+    fontRevision
+    checkSumAdjustment
+    magicNumber
+    flags
+    unitsPerEm
+    created
+    modified
+    xMin
+    yMin
+    xMax
+    yMax
+    macStyle
+    lowestRecPPEM
+    fontDirectionHint
+    indexToLocFormat
+    glyphDataFormat
+
+The two dates are held as an array of two unsigned longs (32-bits)
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+
+require Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'version' => 'f',
+    'fontRevision' => 'f',
+    'checkSumAdjustment' => 'L',
+    'magicNumber' => 'L',
+    'flags' => 'S',
+    'unitsPerEm' => 'S',
+    'created' => 'L2',
+    'modified' => 'L2',
+    'xMin' => 's',
+    'yMin' => 's',
+    'xMax' => 's',
+    'yMax' => 's',
+    'macStyle' => 'S',
+    'lowestRecPPEM' => 'S',
+    'fontDirectionHint' => 's',
+    'indexToLocFormat' => 's',
+    'glyphDataFormat' => 's');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory thanks to some utility functions
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read || return $self;
+
+    init unless defined $fields{'Ascender'};
+    $self->{' INFILE'}->read($dat, 54);
+
+    TTF_Read_Fields($self, $dat, \%fields);
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying. If in memory
+(which is usually) the checkSumAdjustment field is set to 0 as per the default
+if the file checksum is not to be considered.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};      # this is never true
+#    $self->{'checkSumAdjustment'} = 0 unless $self->{' PARENT'}{' wantsig'};
+    $fh->print(TTF_Out_Fields($self, \%fields, 54));
+    $self;
+}
+
+
+=head2 $t->XML_element($context, $depth, $key, $value)
+
+Handles date process for the XML exporter
+
+=cut
+
+sub XML_element
+{
+    my ($self) = shift;
+    my ($context, $depth, $key, $value) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($output, @time);
+    my (@month) = qw(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC);
+
+    return $self->SUPER::XML_element(@_) unless ($key eq 'created' || $key eq 'modified');
+
+    @time = gmtime($self->getdate($key eq 'created'));
+    $output = sprintf("%d/%s/%d %d:%d:%d", $time[3], $month[$time[4]], $time[5] + 1900,
+            $time[2], $time[1], $time[0]);
+    $fh->print("$depth<$key>$output</$key>\n");
+    $self;
+}
+    
+
+=head2 $t->update
+
+Updates the head table based on the glyph data and the hmtx table
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($num, $i, $loc, $hmtx);
+    my ($xMin, $yMin, $xMax, $yMax, $lsbx);
+
+    return undef unless ($self->SUPER::update);
+
+    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    return undef unless (defined $self->{' PARENT'}{'hmtx'} && defined $self->{' PARENT'}{'loca'});
+    $hmtx = $self->{' PARENT'}{'hmtx'}->read;
+    
+    $self->{' PARENT'}{'loca'}->update;
+    $hmtx->update;              # if we updated, then the flags will be set anyway.
+    $lsbx = 1;
+    for ($i = 0; $i < $num; $i++)
+    {
+        $loc = $self->{' PARENT'}{'loca'}{'glyphs'}[$i];
+        next unless defined $loc;
+        $loc->read->update_bbox;
+        $xMin = $loc->{'xMin'} if ($loc->{'xMin'} < $xMin || $i == 0);
+        $yMin = $loc->{'yMin'} if ($loc->{'yMin'} < $yMin || $i == 0);
+        $xMax = $loc->{'xMax'} if ($loc->{'xMax'} > $xMax);
+        $yMax = $loc->{'yMax'} if ($loc->{'yMax'} > $yMax);
+        $lsbx &= ($loc->{'xMin'} == $hmtx->{'lsb'}[$i]);
+    }
+    $self->{'xMin'} = $xMin;
+    $self->{'yMin'} = $yMin;
+    $self->{'xMax'} = $xMax;
+    $self->{'yMax'} = $yMax;
+    if ($lsbx)
+    { $self->{'flags'} |= 2; }
+    else
+    { $self->{'flags'} &= ~2; }
+    $self;
+}
+
+
+=head2 $t->getdate($is_create)
+
+Converts font modification time (or creation time if $is_create is set) to a 32-bit integer as returned
+from time(). Returns undef if the value is out of range, either before the epoch or after the maximum
+storable time.
+
+=cut
+
+sub getdate
+{
+    my ($self, $is_create) = @_;
+    my ($arr) = $self->{$is_create ? 'created' : 'modified'};
+
+    $arr->[1] -= 2082844800;        # seconds between 1/Jan/1904 and 1/Jan/1970 (midnight)
+    if ($arr->[1] < 0)
+    {
+        $arr->[1] += 0xFFFFFFF; $arr->[1]++;
+        $arr->[0]--;
+    }
+    return undef if $arr->[0] != 0;
+    return $arr->[1];
+}
+
+
+=head2 $t->setdate($time, $is_create)
+
+Sets the time information for modification (or creation time if $is_create is set) according to the 32-bit
+time information.
+
+=cut
+
+sub setdate
+{
+    my ($self, $time, $is_create) = @_;
+    my (@arr);
+
+    $arr[1] = $time;
+    if ($arr[1] >= 0x83DA4F80)
+    {
+        $arr[1] -= 0xFFFFFFFF;
+        $arr[1]--;
+        $arr[0]++;
+    }
+    $arr[1] += 2082844800;
+    $self->{$is_create ? 'created' : 'modified'} = \@arr;
+    $self;
+}
+    
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hhea.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hhea.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hhea.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,162 +1,162 @@
-package Font::TTF::Hhea;
-
-=head1 NAME
-
-TTF:Hhea - Horizontal Header table
-
-=head1 DESCRIPTION
-
-This is a simplte table with just standards specified instance variables
-
-=head1 INSTANCE VARIABLES
-
-    version
-    Ascender
-    Descender
-    LineGap
-    advanceWidthMax
-    minLeftSideBearing
-    minRightSideBearing
-    xMaxExtent
-    caretSlopeRise
-    caretSlopeRun
-    metricDataFormat
-    numberOfHMetrics
-
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-
-require Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'version' => 'f',
-    'Ascender' => 's',
-    'Descender' => 's',
-    'LineGap' => 's',
-    'advanceWidthMax' => 'S',
-    'minLeftSideBearing' => 's',
-    'minRightSideBearing' => 's',
-    'xMaxExtent' => 's',
-    'caretSlopeRise' => 's',
-    'caretSlopeRun' => 's',
-    'metricDataFormat' => '+10s',
-    'numberOfHMetrics' => 'S');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory as instance variables
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read or return $self;
-    init unless defined $fields{'Ascender'};
-    $self->{' INFILE'}->read($dat, 36);
-
-    TTF_Read_Fields($self, $dat, \%fields);
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $self->{'numberOfHMetrics'} = $self->{' PARENT'}{'hmtx'}->numMetrics || $self->{'numberOfHMetrics'};
-    $fh->print(TTF_Out_Fields($self, \%fields, 36));
-    $self;
-}
-
-
-=head2 $t->update
-
-Updates various parameters in the hhea table from the hmtx table, assuming
-the C<hmtx> table is dirty.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($hmtx) = $self->{' PARENT'}{'hmtx'};
-    my ($glyphs);
-    my ($num);
-    my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext);
-
-    return undef unless ($self->SUPER::update);
-    return undef unless (defined $hmtx && defined $self->{' PARENT'}{'loca'});
-    
-    $hmtx->read->update;
-    $self->{' PARENT'}{'loca'}->read->update;
-    $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'};
-    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-
-    return undef unless ($hmtx->{' isDirty'} || $self->{' PARENT'}{'loca'}{' isDirty'});
-    
-    for ($i = 0; $i < $num; $i++)
-    {
-        $aw = $hmtx->{'advance'}[$i];
-        $lsb = $hmtx->{'lsb'}[$i];
-        if (defined $glyphs->[$i])
-        { $ext = $lsb + $glyphs->[$i]->read->{'xMax'} - $glyphs->[$i]{'xMin'}; }
-        else
-        { $ext = $aw; }
-        $maw = $aw if ($aw > $maw);
-        $mlsb = $lsb if ($lsb < $mlsb or $i == 0);
-        $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0);
-        $mext = $ext if ($ext > $mext);
-    }
-    $self->{'advanceWidthMax'} = $maw;
-    $self->{'minLeftSideBearing'} = $mlsb;
-    $self->{'minRightSideBearing'} = $mrsb;
-    $self->{'xMaxExtent'} = $mext;
-    $self->{'numberOfHMetrics'} = $hmtx->numMetrics;
-    $self;
-}
-
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Hhea;
+
+=head1 NAME
+
+TTF:Hhea - Horizontal Header table
+
+=head1 DESCRIPTION
+
+This is a simplte table with just standards specified instance variables
+
+=head1 INSTANCE VARIABLES
+
+    version
+    Ascender
+    Descender
+    LineGap
+    advanceWidthMax
+    minLeftSideBearing
+    minRightSideBearing
+    xMaxExtent
+    caretSlopeRise
+    caretSlopeRun
+    metricDataFormat
+    numberOfHMetrics
+
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+
+require Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'version' => 'f',
+    'Ascender' => 's',
+    'Descender' => 's',
+    'LineGap' => 's',
+    'advanceWidthMax' => 'S',
+    'minLeftSideBearing' => 's',
+    'minRightSideBearing' => 's',
+    'xMaxExtent' => 's',
+    'caretSlopeRise' => 's',
+    'caretSlopeRun' => 's',
+    'metricDataFormat' => '+10s',
+    'numberOfHMetrics' => 'S');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory as instance variables
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read or return $self;
+    init unless defined $fields{'Ascender'};
+    $self->{' INFILE'}->read($dat, 36);
+
+    TTF_Read_Fields($self, $dat, \%fields);
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $self->{'numberOfHMetrics'} = $self->{' PARENT'}{'hmtx'}->numMetrics || $self->{'numberOfHMetrics'};
+    $fh->print(TTF_Out_Fields($self, \%fields, 36));
+    $self;
+}
+
+
+=head2 $t->update
+
+Updates various parameters in the hhea table from the hmtx table, assuming
+the C<hmtx> table is dirty.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($hmtx) = $self->{' PARENT'}{'hmtx'};
+    my ($glyphs);
+    my ($num, $res);
+    my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext);
+
+    return undef unless ($self->SUPER::update);
+    return undef unless (defined $hmtx && defined $self->{' PARENT'}{'loca'});
+    
+    $res = $hmtx->read->update;
+    $res |= $self->{' PARENT'}{'loca'}->read->update;
+    $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'};
+    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+
+    return undef unless ($res);
+    
+    for ($i = 0; $i < $num; $i++)
+    {
+        $aw = $hmtx->{'advance'}[$i];
+        $lsb = $hmtx->{'lsb'}[$i];
+        if (defined $glyphs->[$i])
+        { $ext = $lsb + $glyphs->[$i]->read->{'xMax'} - $glyphs->[$i]{'xMin'}; }
+        else
+        { $ext = $aw; }
+        $maw = $aw if ($aw > $maw);
+        $mlsb = $lsb if ($lsb < $mlsb or $i == 0);
+        $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0);
+        $mext = $ext if ($ext > $mext);
+    }
+    $self->{'advanceWidthMax'} = $maw;
+    $self->{'minLeftSideBearing'} = $mlsb;
+    $self->{'minRightSideBearing'} = $mrsb;
+    $self->{'xMaxExtent'} = $mext;
+    $self->{'numberOfHMetrics'} = $hmtx->numMetrics;
+    $self;
+}
+
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hmtx.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hmtx.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Hmtx.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,214 +1,214 @@
-package Font::TTF::Hmtx;
-
-=head1 NAME
-
-Font::TTF::Hmtx - Horizontal Metrics
-
-=head1 DESCRIPTION
-
-Contains the advance width and left side bearing for each glyph. Given the
-compressability of the data onto disk, this table uses information from
-other tables, and thus must do part of its output during the output of
-other tables
-
-=head1 INSTANCE VARIABLES
-
-The horizontal metrics are kept in two arrays by glyph id. The variable names
-do not start with a space
-
-=over 4
-
-=item advance
-
-An array containing the advance width for each glyph
-
-=item lsb
-
-An array containing the left side bearing for each glyph
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-require Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
-
-
-=head2 $t->read
-
-Reads the horizontal metrics from the TTF file into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($numh, $numg);
-
-    $numh = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'};
-    $numg = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
-    $self->_read($numg, $numh, "advance", "lsb");
-}
-
-sub _read
-{
-    my ($self, $numg, $numh, $tAdv, $tLsb) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($i, $dat);
-    
-    $self->SUPER::read or return $self;
-
-    for ($i = 0; $i < $numh; $i++)
-    {
-        $fh->read($dat, 4);
-        ($self->{$tAdv}[$i], $self->{$tLsb}[$i]) = unpack("nn", $dat);
-        $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768);
-    }
-    
-    $i--;
-    while ($i++ < $numg)
-    {
-        $fh->read($dat, 2);
-        $self->{$tAdv}[$i] = $self->{$tAdv}[$numh - 1];
-        $self->{$tLsb}[$i] = unpack("n", $dat);
-        $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768);
-    }
-    $self;
-}
-    
-=head2 $t->numMetrics
-
-Calculates again the number of long metrics required to store the information
-here. Returns undef if the table has not been read.
-
-=cut
-
-sub numMetrics
-{
-    my ($self) = @_;
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    my ($i);
-
-    return undef unless $self->{' read'};
-
-    for ($i = $numg - 2; $i >= 0; $i--)
-    { last if ($self->{'advance'}[$i] != $self->{'advance'}[$i + 1]); }
-
-    return $i + 2;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the metrics to a TTF file. Assumes that the C<hhea> has updated the
-numHMetrics from here
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    my ($numh) = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'};
-    $self->_out($fh, $numg, $numh, "advance", "lsb");
-}
-
-sub _out
-{
-    my ($self, $fh, $numg, $numh, $tAdv, $tLsb) = @_;
-    my ($i, $lsb);
-
-    return $self->SUPER::out($fh) unless ($self->{' read'});
-
-    for ($i = 0; $i < $numg; $i++)
-    {
-        $lsb = $self->{$tLsb}[$i];
-        $lsb += 65536 if $lsb < 0;
-        if ($i >= $numh)
-        { $fh->print(pack("n", $lsb)); }
-        else
-        { $fh->print(pack("n2", $self->{$tAdv}[$i], $lsb)); }
-    }
-    $self;
-}
-
-
-=head2 $t->update
-
-Updates the lsb values from the xMin from the each glyph
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    my ($i);
-
-    return undef unless ($self->SUPER::update);
-# lsb & xMin must always be the same, regardless of any flags!
-#    return $self unless ($self->{' PARENT'}{'head'}{'flags'} & 2);        # lsb & xMin the same
-
-    $self->{' PARENT'}{'loca'}->update;
-    for ($i = 0; $i < $numg; $i++)
-    {
-        my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i];
-        if ($g)
-        { $self->{'lsb'}[$i] = $g->read->update_bbox->{'xMin'}; }
-        else
-        { $self->{'lsb'}[$i] = 0; }
-    }
-    $self->{' PARENT'}{'head'}{'flags'} |= 2;
-    $self;
-}
-    
-
-=head2 $t->out_xml($context, $depth)
-
-Outputs the table in XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    my ($addr) = ($self =~ m/\((.+)\)$/o);
-    my ($i);
-
-    if ($context->{'addresses'}{$addr})
-    {
-        $fh->printf("%s<%s id_ref='%s'/>\n", $depth, $context->{'name'}, $addr);
-        return $self;
-    }
-    else
-    { $fh->printf("%s<%s id='%s'>\n", $depth, $context->{'name'}, $addr); }
-
-    $self->read;
-
-    for ($i = 0; $i < $numg; $i++)
-    { $fh->print("$depth$context->{'indent'}<width adv='$self->{'advance'}[$i]' lsb='$self->{'lsb'}[$i]'/>\n"); }
-
-    $fh->print("$depth</$context->{'name'}>\n");
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Hmtx;
+
+=head1 NAME
+
+Font::TTF::Hmtx - Horizontal Metrics
+
+=head1 DESCRIPTION
+
+Contains the advance width and left side bearing for each glyph. Given the
+compressability of the data onto disk, this table uses information from
+other tables, and thus must do part of its output during the output of
+other tables
+
+=head1 INSTANCE VARIABLES
+
+The horizontal metrics are kept in two arrays by glyph id. The variable names
+do not start with a space
+
+=over 4
+
+=item advance
+
+An array containing the advance width for each glyph
+
+=item lsb
+
+An array containing the left side bearing for each glyph
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+require Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+
+
+=head2 $t->read
+
+Reads the horizontal metrics from the TTF file into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($numh, $numg);
+
+    $numh = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'};
+    $numg = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
+    $self->_read($numg, $numh, "advance", "lsb");
+}
+
+sub _read
+{
+    my ($self, $numg, $numh, $tAdv, $tLsb) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($i, $dat);
+    
+    $self->SUPER::read or return $self;
+
+    for ($i = 0; $i < $numh; $i++)
+    {
+        $fh->read($dat, 4);
+        ($self->{$tAdv}[$i], $self->{$tLsb}[$i]) = unpack("nn", $dat);
+        $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768);
+    }
+    
+    $i--;
+    while ($i++ < $numg)
+    {
+        $fh->read($dat, 2);
+        $self->{$tAdv}[$i] = $self->{$tAdv}[$numh - 1];
+        $self->{$tLsb}[$i] = unpack("n", $dat);
+        $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768);
+    }
+    $self;
+}
+    
+=head2 $t->numMetrics
+
+Calculates again the number of long metrics required to store the information
+here. Returns undef if the table has not been read.
+
+=cut
+
+sub numMetrics
+{
+    my ($self) = @_;
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    my ($i);
+
+    return undef unless $self->{' read'};
+
+    for ($i = $numg - 2; $i >= 0; $i--)
+    { last if ($self->{'advance'}[$i] != $self->{'advance'}[$i + 1]); }
+
+    return $i + 2;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the metrics to a TTF file. Assumes that the C<hhea> has updated the
+numHMetrics from here
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    my ($numh) = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'};
+    $self->_out($fh, $numg, $numh, "advance", "lsb");
+}
+
+sub _out
+{
+    my ($self, $fh, $numg, $numh, $tAdv, $tLsb) = @_;
+    my ($i, $lsb);
+
+    return $self->SUPER::out($fh) unless ($self->{' read'});
+
+    for ($i = 0; $i < $numg; $i++)
+    {
+        $lsb = $self->{$tLsb}[$i];
+        $lsb += 65536 if $lsb < 0;
+        if ($i >= $numh)
+        { $fh->print(pack("n", $lsb)); }
+        else
+        { $fh->print(pack("n2", $self->{$tAdv}[$i], $lsb)); }
+    }
+    $self;
+}
+
+
+=head2 $t->update
+
+Updates the lsb values from the xMin from the each glyph
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    my ($i);
+
+    return undef unless ($self->SUPER::update);
+# lsb & xMin must always be the same, regardless of any flags!
+#    return $self unless ($self->{' PARENT'}{'head'}{'flags'} & 2);        # lsb & xMin the same
+
+    $self->{' PARENT'}{'loca'}->update;
+    for ($i = 0; $i < $numg; $i++)
+    {
+        my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i];
+        if ($g)
+        { $self->{'lsb'}[$i] = $g->read->update_bbox->{'xMin'}; }
+        else
+        { $self->{'lsb'}[$i] = 0; }
+    }
+    $self->{' PARENT'}{'head'}{'flags'} |= 2;
+    $self;
+}
+    
+
+=head2 $t->out_xml($context, $depth)
+
+Outputs the table in XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    my ($addr) = ($self =~ m/\((.+)\)$/o);
+    my ($i);
+
+    if ($context->{'addresses'}{$addr})
+    {
+        $fh->printf("%s<%s id_ref='%s'/>\n", $depth, $context->{'name'}, $addr);
+        return $self;
+    }
+    else
+    { $fh->printf("%s<%s id='%s'>\n", $depth, $context->{'name'}, $addr); }
+
+    $self->read;
+
+    for ($i = 0; $i < $numg; $i++)
+    { $fh->print("$depth$context->{'indent'}<width adv='$self->{'advance'}[$i]' lsb='$self->{'lsb'}[$i]'/>\n"); }
+
+    $fh->print("$depth</$context->{'name'}>\n");
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/ClassArray.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/ClassArray.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/ClassArray.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,152 +1,152 @@
-package Font::TTF::Kern::ClassArray;
-
-=head1 NAME
-
-Font::TTF::Kern::ClassArray
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Kern::Subtable);
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-    
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
- 
-    my $subtableStart = $fh->tell() - 8;
-    my $dat;
-    $fh->read($dat, 8);
-    my ($rowWidth, $leftClassTable, $rightClassTable, $array) = unpack("nnnn", $dat);
-
-    $fh->seek($subtableStart + $leftClassTable, IO::File::SEEK_SET);
-    $fh->read($dat, 4);
-    my ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
-    $fh->read($dat, $nGlyphs * 2);
-    my $leftClasses = [];
-    foreach (TTF_Unpack("S*", $dat)) {
-        push @{$leftClasses->[($_ - $array) / $rowWidth]}, $firstGlyph++;
-    }
-    
-    $fh->seek($subtableStart + $rightClassTable, IO::File::SEEK_SET);
-    $fh->read($dat, 4);
-    ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
-    $fh->read($dat, $nGlyphs * 2);
-    my $rightClasses = [];
-    foreach (TTF_Unpack("S*", $dat)) {
-        push @{$rightClasses->[$_ / 2]}, $firstGlyph++;
-    }
-    
-    $fh->seek($subtableStart + $array, IO::File::SEEK_SET);
-    $fh->read($dat, $self->{'length'} - $array);
-
-    my $offset = 0;
-    my $kernArray = [];
-    while ($offset < length($dat)) {
-        push @$kernArray, [ TTF_Unpack("s*", substr($dat, $offset, $rowWidth)) ];
-        $offset += $rowWidth;
-    }    
-
-    $self->{'leftClasses'} = $leftClasses;
-    $self->{'rightClasses'} = $rightClasses;
-    $self->{'kernArray'} = $kernArray;
-    
-    $fh->seek($subtableStart + $self->{'length'}, IO::File::SEEK_SET);
-    
-    $self;
-}
-
-=head2 $t->out_sub($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out_sub
-{
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    
-}
-
-sub dumpXML
-{
-    my ($self, $fh) = @_;
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-    $fh->printf("<leftClasses>\n");
-    $self->dumpClasses($self->{'leftClasses'}, $fh);    
-    $fh->printf("</leftClasses>\n");
-
-    $fh->printf("<rightClasses>\n");
-    $self->dumpClasses($self->{'rightClasses'}, $fh);    
-    $fh->printf("</rightClasses>\n");
-    
-    $fh->printf("<kernArray>\n");
-    my $kernArray = $self->{'kernArray'};
-    foreach (0 .. $#$kernArray) {
-        $fh->printf("<row index=\"%s\">\n", $_);
-        my $row = $kernArray->[$_];
-        foreach (0 .. $#$row) {
-            $fh->printf("<val index=\"%s\" v=\"%s\"/>\n", $_, $row->[$_]);
-        }
-        $fh->printf("</row>\n");
-    }
-    $fh->printf("</kernArray>\n");
-}
-
-sub type
-{
-    return 'kernClassArray';
-}
-
-
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern::ClassArray;
+
+=head1 NAME
+
+Font::TTF::Kern::ClassArray
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Kern::Subtable);
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+    
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+ 
+    my $subtableStart = $fh->tell() - 8;
+    my $dat;
+    $fh->read($dat, 8);
+    my ($rowWidth, $leftClassTable, $rightClassTable, $array) = unpack("nnnn", $dat);
+
+    $fh->seek($subtableStart + $leftClassTable, IO::File::SEEK_SET);
+    $fh->read($dat, 4);
+    my ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
+    $fh->read($dat, $nGlyphs * 2);
+    my $leftClasses = [];
+    foreach (TTF_Unpack("S*", $dat)) {
+        push @{$leftClasses->[($_ - $array) / $rowWidth]}, $firstGlyph++;
+    }
+    
+    $fh->seek($subtableStart + $rightClassTable, IO::File::SEEK_SET);
+    $fh->read($dat, 4);
+    ($firstGlyph, $nGlyphs) = unpack("nn", $dat);
+    $fh->read($dat, $nGlyphs * 2);
+    my $rightClasses = [];
+    foreach (TTF_Unpack("S*", $dat)) {
+        push @{$rightClasses->[$_ / 2]}, $firstGlyph++;
+    }
+    
+    $fh->seek($subtableStart + $array, IO::File::SEEK_SET);
+    $fh->read($dat, $self->{'length'} - $array);
+
+    my $offset = 0;
+    my $kernArray = [];
+    while ($offset < length($dat)) {
+        push @$kernArray, [ TTF_Unpack("s*", substr($dat, $offset, $rowWidth)) ];
+        $offset += $rowWidth;
+    }    
+
+    $self->{'leftClasses'} = $leftClasses;
+    $self->{'rightClasses'} = $rightClasses;
+    $self->{'kernArray'} = $kernArray;
+    
+    $fh->seek($subtableStart + $self->{'length'}, IO::File::SEEK_SET);
+    
+    $self;
+}
+
+=head2 $t->out_sub($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out_sub
+{
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    
+}
+
+sub dumpXML
+{
+    my ($self, $fh) = @_;
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+    $fh->printf("<leftClasses>\n");
+    $self->dumpClasses($self->{'leftClasses'}, $fh);    
+    $fh->printf("</leftClasses>\n");
+
+    $fh->printf("<rightClasses>\n");
+    $self->dumpClasses($self->{'rightClasses'}, $fh);    
+    $fh->printf("</rightClasses>\n");
+    
+    $fh->printf("<kernArray>\n");
+    my $kernArray = $self->{'kernArray'};
+    foreach (0 .. $#$kernArray) {
+        $fh->printf("<row index=\"%s\">\n", $_);
+        my $row = $kernArray->[$_];
+        foreach (0 .. $#$row) {
+            $fh->printf("<val index=\"%s\" v=\"%s\"/>\n", $_, $row->[$_]);
+        }
+        $fh->printf("</row>\n");
+    }
+    $fh->printf("</kernArray>\n");
+}
+
+sub type
+{
+    return 'kernClassArray';
+}
+
+
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/CompactClassArray.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/CompactClassArray.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/CompactClassArray.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,93 +1,93 @@
-package Font::TTF::Kern::CompactClassArray;
-
-=head1 NAME
-
-Font::TTF::AAT::Kern::CompactClassArray
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Kern::Subtable);
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    
-    die "incomplete";
-            
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out_sub
-{
-    my ($self, $fh) = @_;
-    
-    die "incomplete";
-            
-    $self;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    die "incomplete";
-}
-
-
-sub type
-{
-    return 'kernCompactClassArray';
-}
-
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern::CompactClassArray;
+
+=head1 NAME
+
+Font::TTF::AAT::Kern::CompactClassArray
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Kern::Subtable);
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    
+    die "incomplete";
+            
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out_sub
+{
+    my ($self, $fh) = @_;
+    
+    die "incomplete";
+            
+    $self;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    die "incomplete";
+}
+
+
+sub type
+{
+    return 'kernCompactClassArray';
+}
+
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/OrderedList.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/OrderedList.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/OrderedList.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,108 +1,108 @@
-package Font::TTF::Kern::OrderedList;
-
-=head1 NAME
-
-Font::TTF::Kern::OrderedList
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Kern::Subtable);
-
-sub new
-{
-    my ($class, @options) = @_;
-    my ($self) = {};
-    
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
- 
-    my $dat;
-    $fh->read($dat, 8);
-    my ($nPairs, $searchRange, $entrySelector, $rangeShift) = unpack("nnnn", $dat);
-
-    my $pairs = [];
-    foreach (1 .. $nPairs) {
-        $fh->read($dat, 6);
-        my ($left, $right, $kern) = TTF_Unpack("SSs", $dat);
-        push @$pairs, { 'left' => $left, 'right' => $right, 'kern' => $kern } if $kern != 0;
-    }
-    
-    $self->{'kernPairs'} = $pairs;
-    
-    $self;
-}
-
-=head2 $t->out_sub($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out_sub
-{
-    my ($self, $fh) = @_;
-    
-    my $pairs = $self->{'kernPairs'};
-    $fh->print(pack("nnnn", TTF_bininfo(scalar @$pairs, 6)));
-    
-    foreach (sort { $a->{'left'} <=> $b->{'left'} or $a->{'right'} <=> $b->{'right'} } @$pairs) {
-        $fh->print(TTF_Pack("SSs", $_->{'left'}, $_->{'right'}, $_->{'kern'}));
-    }
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub dumpXML
-{
-    my ($self, $fh) = @_;
-    
-    my $postVal = $self->post()->{'VAL'};
-    
-    $fh = 'STDOUT' unless defined $fh;
-    foreach (@{$self->{'kernPairs'}}) {
-        $fh->printf("<pair l=\"%s\" r=\"%s\" v=\"%s\"/>\n", $postVal->[$_->{'left'}], $postVal->[$_->{'right'}], $_->{'kern'});
-    }
-}
-
-
-sub type
-{
-    return 'kernOrderedList';
-}
-
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern::OrderedList;
+
+=head1 NAME
+
+Font::TTF::Kern::OrderedList
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Kern::Subtable);
+
+sub new
+{
+    my ($class, @options) = @_;
+    my ($self) = {};
+    
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+ 
+    my $dat;
+    $fh->read($dat, 8);
+    my ($nPairs, $searchRange, $entrySelector, $rangeShift) = unpack("nnnn", $dat);
+
+    my $pairs = [];
+    foreach (1 .. $nPairs) {
+        $fh->read($dat, 6);
+        my ($left, $right, $kern) = TTF_Unpack("SSs", $dat);
+        push @$pairs, { 'left' => $left, 'right' => $right, 'kern' => $kern } if $kern != 0;
+    }
+    
+    $self->{'kernPairs'} = $pairs;
+    
+    $self;
+}
+
+=head2 $t->out_sub($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out_sub
+{
+    my ($self, $fh) = @_;
+    
+    my $pairs = $self->{'kernPairs'};
+    $fh->print(pack("nnnn", TTF_bininfo(scalar @$pairs, 6)));
+    
+    foreach (sort { $a->{'left'} <=> $b->{'left'} or $a->{'right'} <=> $b->{'right'} } @$pairs) {
+        $fh->print(TTF_Pack("SSs", $_->{'left'}, $_->{'right'}, $_->{'kern'}));
+    }
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub dumpXML
+{
+    my ($self, $fh) = @_;
+    
+    my $postVal = $self->post()->{'VAL'};
+    
+    $fh = 'STDOUT' unless defined $fh;
+    foreach (@{$self->{'kernPairs'}}) {
+        $fh->printf("<pair l=\"%s\" r=\"%s\" v=\"%s\"/>\n", $postVal->[$_->{'left'}], $postVal->[$_->{'right'}], $_->{'kern'});
+    }
+}
+
+
+sub type
+{
+    return 'kernOrderedList';
+}
+
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/StateTable.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/StateTable.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/StateTable.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,142 +1,142 @@
-package Font::TTF::Kern::StateTable;
-
-=head1 NAME
-
-Font::TTF::Kern::StateTable
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Kern::Subtable;
-
- at ISA = qw(Font::TTF::Kern::Subtable);
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-    
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-    
-    my $stTableStart = $fh->tell();
-
-    my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
-
-    foreach (@$entries) {
-        my $flags = $_->{'flags'};
-        delete $_->{'flags'};
-        $_->{'push'} = 1        if $flags & 0x8000;
-        $_->{'noAdvance'} = 1    if $flags & 0x4000;
-        $flags &= ~0xC000;
-        if ($flags != 0) {
-            my $kernList = [];
-            $fh->seek($stTableStart + $flags, IO::File::SEEK_SET);
-            while (1) {
-                $fh->read($dat, 2);
-                my $k = TTF_Unpack("s", $dat);
-                push @$kernList, ($k & ~1);
-                last if ($k & 1) != 0;
-            }
-            $_->{'kernList'} = $kernList;
-        }
-    }
-
-    $self->{'classes'} = $classes;
-    $self->{'states'} = $states;
-    $self->{'entries'} = $entries;
-
-    $fh->seek($stTableStart - 8 + $self->{'length'}, IO::File::SEEK_SET);
-    
-    $self;
-}
-
-=head2 $t->out_sub($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out_sub
-{
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-}
-
-sub dumpXML
-{
-    my ($self, $fh) = @_;
-    
-    $fh->printf("<classes>\n");
-    $self->dumpClasses($self->{'classes'}, $fh);
-    $fh->printf("</classes>\n");
-
-    $fh->printf("<states>\n");
-    my $states = $self->{'states'};
-    foreach (0 .. $#$states) {
-        $fh->printf("<state index=\"%s\">\n", $_);
-        my $members = $states->[$_];
-        foreach (0 .. $#$members) {
-            my $m = $members->[$_];
-            $fh->printf("<m index=\"%s\" nextState=\"%s\"", $_, $m->{'nextState'});
-            $fh->printf(" push=\"1\"")        if $m->{'push'};
-            $fh->printf(" noAdvance=\"1\"")    if $m->{'noAdvance'};
-            if (exists $m->{'kernList'}) {
-                $fh->printf(">");
-                foreach (@{$m->{'kernList'}}) {
-                    $fh->printf("<kern v=\"%s\"/>", $_);
-                }
-                $fh->printf("</m>\n");
-            }
-            else {
-                $fh->printf("/>\n");
-            }
-        }
-        $fh->printf("</state>\n");
-    }
-    $fh->printf("</states>\n");
-}
-
-sub type
-{
-    return 'kernStateTable';
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern::StateTable;
+
+=head1 NAME
+
+Font::TTF::Kern::StateTable
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Kern::Subtable;
+
+ at ISA = qw(Font::TTF::Kern::Subtable);
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+    
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+    
+    my $stTableStart = $fh->tell();
+
+    my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
+
+    foreach (@$entries) {
+        my $flags = $_->{'flags'};
+        delete $_->{'flags'};
+        $_->{'push'} = 1        if $flags & 0x8000;
+        $_->{'noAdvance'} = 1    if $flags & 0x4000;
+        $flags &= ~0xC000;
+        if ($flags != 0) {
+            my $kernList = [];
+            $fh->seek($stTableStart + $flags, IO::File::SEEK_SET);
+            while (1) {
+                $fh->read($dat, 2);
+                my $k = TTF_Unpack("s", $dat);
+                push @$kernList, ($k & ~1);
+                last if ($k & 1) != 0;
+            }
+            $_->{'kernList'} = $kernList;
+        }
+    }
+
+    $self->{'classes'} = $classes;
+    $self->{'states'} = $states;
+    $self->{'entries'} = $entries;
+
+    $fh->seek($stTableStart - 8 + $self->{'length'}, IO::File::SEEK_SET);
+    
+    $self;
+}
+
+=head2 $t->out_sub($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out_sub
+{
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+}
+
+sub dumpXML
+{
+    my ($self, $fh) = @_;
+    
+    $fh->printf("<classes>\n");
+    $self->dumpClasses($self->{'classes'}, $fh);
+    $fh->printf("</classes>\n");
+
+    $fh->printf("<states>\n");
+    my $states = $self->{'states'};
+    foreach (0 .. $#$states) {
+        $fh->printf("<state index=\"%s\">\n", $_);
+        my $members = $states->[$_];
+        foreach (0 .. $#$members) {
+            my $m = $members->[$_];
+            $fh->printf("<m index=\"%s\" nextState=\"%s\"", $_, $m->{'nextState'});
+            $fh->printf(" push=\"1\"")        if $m->{'push'};
+            $fh->printf(" noAdvance=\"1\"")    if $m->{'noAdvance'};
+            if (exists $m->{'kernList'}) {
+                $fh->printf(">");
+                foreach (@{$m->{'kernList'}}) {
+                    $fh->printf("<kern v=\"%s\"/>", $_);
+                }
+                $fh->printf("</m>\n");
+            }
+            else {
+                $fh->printf("/>\n");
+            }
+        }
+        $fh->printf("</state>\n");
+    }
+    $fh->printf("</states>\n");
+}
+
+sub type
+{
+    return 'kernStateTable';
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/Subtable.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/Subtable.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern/Subtable.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,174 +1,174 @@
-package Font::TTF::Kern::Subtable;
-
-=head1 NAME
-
-Font::TTF::Kern::Subtable
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
-require Font::TTF::Kern::OrderedList;
-require Font::TTF::Kern::StateTable;
-require Font::TTF::Kern::ClassArray;
-require Font::TTF::Kern::CompactClassArray;
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-
-    $class = ref($class) || $class;
-
-    bless $self, $class;
-}
-
-sub create
-{
-    my ($class, $type, $coverage, $length) = @_;
-
-    $class = ref($class) || $class;
-
-    my $subclass;
-    if ($type == 0) {
-        $subclass = 'Font::TTF::Kern::OrderedList';
-    }
-    elsif ($type == 1) {
-        $subclass = 'Font::TTF::Kern::StateTable';
-    }
-    elsif ($type == 2) {
-        $subclass = 'Font::TTF::Kern::ClassArray';
-    }
-    elsif ($type == 3) {
-        $subclass = 'Font::TTF::Kern::CompactClassArray';
-    }
-    
-    my @options;
-    push @options,'vertical'    if ($coverage & 0x8000) != 0;
-    push @options,'crossStream'    if ($coverage & 0x4000) != 0;
-    push @options,'variation'    if ($coverage & 0x2000) != 0;
-    
-    my ($subTable) = $subclass->new(@options);
-
-    map { $subTable->{$_} = 1 } @options;
-
-    $subTable->{'type'} = $type;
-    $subTable->{'length'} = $length;
-
-    $subTable;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    my $subtableStart = $fh->tell();
-    my $type = $self->{'type'};
-    my $coverage = $type;
-    $coverage += 0x4000 if $self->{'direction'} eq 'RL';
-    $coverage += 0x2000 if $self->{'orientation'} eq 'VH';
-    $coverage += 0x8000 if $self->{'orientation'} eq 'V';
-    
-    $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'}));    # placeholder for length
-    
-    $self->out_sub($fh);
-    
-    my $length = $fh->tell() - $subtableStart;
-    my $padBytes = (4 - ($length & 3)) & 3;
-    $fh->print(pack("C*", (0) x $padBytes));
-    $length += $padBytes;
-    $fh->seek($subtableStart, IO::File::SEEK_SET);
-    $fh->print(pack("n", $length));
-    $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub post
-{
-    my ($self) = @_;
-    
-    my $post = $self->{' PARENT'}{' PARENT'}{'post'};
-    if (defined $post) {
-        $post->read;
-    }
-    else {
-        $post = {};
-    }
-    
-    return $post;
-}
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    $fh = 'STDOUT' unless defined $fh;
-}
-
-=head2 $t->print_classes($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print_classes
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    my $classes = $self->{'classes'};
-    foreach (0 .. $#$classes) {
-        my $class = $classes->[$_];
-        if (defined $class) {
-            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
-        }
-    }
-}
-
-sub dumpClasses
-{
-    my ($self, $classes, $fh) = @_;
-    my $post = $self->post();
-    
-    foreach (0 .. $#$classes) {
-        my $c = $classes->[$_];
-        if ($#$c > -1) {
-            $fh->printf("<class n=\"%s\">\n", $_);
-            foreach (@$c) {
-                $fh->printf("<g index=\"%s\" name=\"%s\"/>\n", $_, $post->{'VAL'}[$_]);
-            }
-            $fh->printf("</class>\n");
-        }
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern::Subtable;
+
+=head1 NAME
+
+Font::TTF::Kern::Subtable
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+require Font::TTF::Kern::OrderedList;
+require Font::TTF::Kern::StateTable;
+require Font::TTF::Kern::ClassArray;
+require Font::TTF::Kern::CompactClassArray;
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+
+    $class = ref($class) || $class;
+
+    bless $self, $class;
+}
+
+sub create
+{
+    my ($class, $type, $coverage, $length) = @_;
+
+    $class = ref($class) || $class;
+
+    my $subclass;
+    if ($type == 0) {
+        $subclass = 'Font::TTF::Kern::OrderedList';
+    }
+    elsif ($type == 1) {
+        $subclass = 'Font::TTF::Kern::StateTable';
+    }
+    elsif ($type == 2) {
+        $subclass = 'Font::TTF::Kern::ClassArray';
+    }
+    elsif ($type == 3) {
+        $subclass = 'Font::TTF::Kern::CompactClassArray';
+    }
+    
+    my @options;
+    push @options,'vertical'    if ($coverage & 0x8000) != 0;
+    push @options,'crossStream'    if ($coverage & 0x4000) != 0;
+    push @options,'variation'    if ($coverage & 0x2000) != 0;
+    
+    my ($subTable) = $subclass->new(@options);
+
+    map { $subTable->{$_} = 1 } @options;
+
+    $subTable->{'type'} = $type;
+    $subTable->{'length'} = $length;
+
+    $subTable;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    my $subtableStart = $fh->tell();
+    my $type = $self->{'type'};
+    my $coverage = $type;
+    $coverage += 0x4000 if $self->{'direction'} eq 'RL';
+    $coverage += 0x2000 if $self->{'orientation'} eq 'VH';
+    $coverage += 0x8000 if $self->{'orientation'} eq 'V';
+    
+    $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'}));    # placeholder for length
+    
+    $self->out_sub($fh);
+    
+    my $length = $fh->tell() - $subtableStart;
+    my $padBytes = (4 - ($length & 3)) & 3;
+    $fh->print(pack("C*", (0) x $padBytes));
+    $length += $padBytes;
+    $fh->seek($subtableStart, IO::File::SEEK_SET);
+    $fh->print(pack("n", $length));
+    $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub post
+{
+    my ($self) = @_;
+    
+    my $post = $self->{' PARENT'}{' PARENT'}{'post'};
+    if (defined $post) {
+        $post->read;
+    }
+    else {
+        $post = {};
+    }
+    
+    return $post;
+}
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    $fh = 'STDOUT' unless defined $fh;
+}
+
+=head2 $t->print_classes($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print_classes
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    my $classes = $self->{'classes'};
+    foreach (0 .. $#$classes) {
+        my $class = $classes->[$_];
+        if (defined $class) {
+            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
+        }
+    }
+}
+
+sub dumpClasses
+{
+    my ($self, $classes, $fh) = @_;
+    my $post = $self->post();
+    
+    foreach (0 .. $#$classes) {
+        my $c = $classes->[$_];
+        if ($#$c > -1) {
+            $fh->printf("<class n=\"%s\">\n", $_);
+            foreach (@$c) {
+                $fh->printf("<g index=\"%s\" name=\"%s\"/>\n", $_, $post->{'VAL'}[$_]);
+            }
+            $fh->printf("</class>\n");
+        }
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Kern.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,293 +1,293 @@
-package Font::TTF::Kern;
-
-=head1 NAME
-
-Font::TTF::Kern - Kerning tables
-
-=head1 DESCRIPTION
-
-Kerning tables are held as an ordered collection of subtables each giving
-incremental information regarding the kerning of various pairs of glyphs.
-
-The basic structure of the kerning data structure is:
-
-    $kern = $f->{'kern'}{'tables'}[$tnum]{'kerns'}{$leftnum}{$rightnum};
-
-Due to the possible complexity of some kerning tables the above information
-is insufficient. Reference also needs to be made to the type of the table and
-the coverage field.
-
-=head1 INSTANCE VARIABLES
-
-The instance variables for a kerning table are relatively straightforward.
-
-=over 4
-
-=item Version
-
-Version number of the kerning table
-
-=item Num
-
-Number of subtables in the kerning table
-
-=item tables
-
-Array of subtables in the kerning table
-
-=over 4
-
-Each subtable has a number of instance variables.
-
-=item kern
-
-A two level hash array containing kerning values. The indexing is left
-value and then right value. In the case of type 2 tables, the indexing
-is via left class and right class. It may seem using hashes is strange,
-but most tables are not type 2 and this method saves empty array values.
-
-=item type
-
-Stores the table type. Only type 0 and type 2 tables are specified for
-TrueType so far.
-
-=item coverage
-
-A bit field of coverage information regarding the kerning value. See the
-TrueType specification for details.
-
-=item Version
-
-Contains the version number of the table.
-
-=item Num
-
-Number of kerning pairs in this type 0 table.
-
-=item left
-
-An array indexed by glyph - left_first which returns a class number for
-the glyph in type 2 tables.
-
-=item right
-
-An array indexed by glyph - right_first which returns a class number for
-the glyph in type 2 tables.
-
-=item left_first
-
-the glyph number of the first element in the left array for type 2 tables.
-
-=item right_first
-
-the glyph number of the first element in the right array for type 2 tables.
-
-=item num_left
-
-Number of left classes
-
-=item num_right
-
-Number of right classes
-
-=back
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the whole kerning table into structures
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($dat, $i, $numt, $len, $cov, $t);
-
-    $self->SUPER::read or return $self;
-
-    $fh->read($dat, 4);
-    ($self->{'Version'}, $numt) = unpack("n2", $dat);
-    $self->{'Num'} = $numt;
-
-    for ($i = 0; $i < $numt; $i++)
-    {
-        $t = {};
-        $fh->read($dat, 6);
-        ($t->{'Version'}, $len, $cov) = unpack("n3", $dat);
-        $t->{'coverage'} = $cov & 255;
-        $t->{'type'} = $cov >> 8;
-        $fh->read($dat, $len - 6);
-        if ($t->{'Version'} == 0)
-        {
-            my ($j);
-
-            $t->{'Num'} = unpack("n", $dat);
-            for ($j = 0; $j < $t->{'Num'}; $j++)
-            {
-                my ($f, $l, $v) = TTF_Unpack("SSs", substr($dat, $j * 6 + 8, 6));
-                $t->{'kern'}{$f}{$l} = $v;
-            }
-        } elsif ($t->{'Version'} == 2)
-        {
-            my ($wid, $off, $numg, $maxl, $maxr, $j);
-            
-            $wid = unpack("n", $dat);
-            $off = unpack("n", substr($dat, 2));
-            ($t->{'left_first'}, $numg) = unpack("n2", substr($dat, $off));
-            $t->{'left'} = [unpack("C$numg", substr($dat, $off + 4))];
-            foreach (@{$t->{'left'}})
-            {
-                $_ /= $wid;
-                $maxl = $_ if ($_ > $maxl);
-            }
-            $t->{'left_max'} = $maxl;
-
-            $off = unpack("n", substr($dat, 4));
-            ($t->{'right_first'}, $numg) = unpack("n2", substr($dat, $off));
-            $t->{'right'} = [unpack("C$numg", substr($dat, $off + 4))];
-            foreach (@{$t->{'right'}})
-            {
-                $_ >>= 1;
-                $maxr = $_ if ($_ > $maxr);
-            }
-            $t->{'right_max'} = $maxr;
-
-            $off = unpack("n", substr($dat, 6));
-            for ($j = 0; $j <= $maxl; $j++)
-            {
-                my ($k) = 0;
-
-                map { $t->{'kern'}{$j}{$k} = $_ if $_; $k++; }
-                        unpack("n$maxr", substr($dat, $off + $wid * $j));
-            }
-        }
-        push (@{$self->{'tables'}}, $t);
-    }
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Outputs the kerning tables to the given file
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($i, $l, $r, $loc, $loc1, $t);
-
-    return $self->SUPER::out($fh) unless ($self->{' read'});
-
-    $fh->print(pack("n2", $self->{'Version'}, $self->{'Num'}));
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $t = $self->{'tables'}[$i];
-        $loc = $fh->tell();
-
-        $fh->print(pack("nnn", $t->{'Version'}, 0, $t->{'coverage'}));
-        if ($t->{'Version'} == 0)
-        {
-            my ($dat);
-            foreach $l (sort {$a <=> $b} keys %{$t->{'kern'}})
-            {
-                foreach $r (sort {$a <=> $b} keys %{$t->{'kern'}{$l}})
-                { $dat .= TTF_Pack("SSs", $l, $r, $t->{'kern'}{$l}{$r}); }
-            }
-            $fh->print(TTF_Pack("SSSS", Font::TTF::Utils::TTF_bininfo(length($dat) / 6, 6)));
-            $fh->print($dat);
-        } elsif ($t->{'Version'} == 2)
-        {
-            my ($arr);
-
-            $fh->print(pack("nnnn", $t->{'right_max'} << 1, 8, ($#{$t->{'left'}} + 7) << 1,
-                    ($#{$t->{'left'}} + $#{$t->{'right'}} + 10) << 1));
-
-            $fh->print(pack("nn", $t->{'left_first'}, $#{$t->{'left'}} + 1));
-            foreach (@{$t->{'left'}})
-            { $fh->print(pack("C", $_ * (($t->{'left_max'} + 1) << 1))); }
-
-            $fh->print(pack("nn", $t->{'right_first'}, $#{$t->{'right'}} + 1));
-            foreach (@{$t->{'right'}})
-            { $fh->print(pack("C", $_ << 1)); }
-
-            $arr = "\000\000" x (($t->{'left_max'} + 1) * ($t->{'right_max'} + 1));
-            foreach $l (keys %{$t->{'kern'}})
-            {
-                foreach $r (keys %{$t->{'kern'}{$l}})
-                { substr($arr, ($l * ($t->{'left_max'} + 1) + $r) << 1, 2)
-                        = pack("n", $t->{'kern'}{$l}{$r}); }
-            }
-            $fh->print($arr);
-        }
-        $loc1 = $fh->tell();
-        $fh->seek($loc + 2, 0);
-        $fh->print(pack("n", $loc1 - $loc));
-        $fh->seek($loc1, 0);
-    }
-    $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $key, $value)
-
-Handles outputting the kern hash into XML a little more tidily
-
-=cut
-
-sub XML_element
-{
-    my ($self) = shift;
-    my ($context, $depth, $key, $value) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($f, $l);
-
-    return $self->SUPER::XML_element(@_) unless ($key eq 'kern');
-    $fh->print("$depth<kern-table>\n");
-    foreach $f (sort {$a <=> $b} keys %{$value})
-    {
-        foreach $l (sort {$a <=> $b} keys %{$value->{$f}})
-        { $fh->print("$depth$context->{'indent'}<adjust first='$f' last='$l' dist='$value->{$f}{$l}'/>\n"); }
-    }
-    $fh->print("$depth</kern-table>\n");
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-Only supports kerning table types 0 & 2.
-
-=item *
-
-No real support functions to I<do> anything with the kerning tables yet.
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Kern;
+
+=head1 NAME
+
+Font::TTF::Kern - Kerning tables
+
+=head1 DESCRIPTION
+
+Kerning tables are held as an ordered collection of subtables each giving
+incremental information regarding the kerning of various pairs of glyphs.
+
+The basic structure of the kerning data structure is:
+
+    $kern = $f->{'kern'}{'tables'}[$tnum]{'kerns'}{$leftnum}{$rightnum};
+
+Due to the possible complexity of some kerning tables the above information
+is insufficient. Reference also needs to be made to the type of the table and
+the coverage field.
+
+=head1 INSTANCE VARIABLES
+
+The instance variables for a kerning table are relatively straightforward.
+
+=over 4
+
+=item Version
+
+Version number of the kerning table
+
+=item Num
+
+Number of subtables in the kerning table
+
+=item tables
+
+Array of subtables in the kerning table
+
+=over 4
+
+Each subtable has a number of instance variables.
+
+=item kern
+
+A two level hash array containing kerning values. The indexing is left
+value and then right value. In the case of type 2 tables, the indexing
+is via left class and right class. It may seem using hashes is strange,
+but most tables are not type 2 and this method saves empty array values.
+
+=item type
+
+Stores the table type. Only type 0 and type 2 tables are specified for
+TrueType so far.
+
+=item coverage
+
+A bit field of coverage information regarding the kerning value. See the
+TrueType specification for details.
+
+=item Version
+
+Contains the version number of the table.
+
+=item Num
+
+Number of kerning pairs in this type 0 table.
+
+=item left
+
+An array indexed by glyph - left_first which returns a class number for
+the glyph in type 2 tables.
+
+=item right
+
+An array indexed by glyph - right_first which returns a class number for
+the glyph in type 2 tables.
+
+=item left_first
+
+the glyph number of the first element in the left array for type 2 tables.
+
+=item right_first
+
+the glyph number of the first element in the right array for type 2 tables.
+
+=item num_left
+
+Number of left classes
+
+=item num_right
+
+Number of right classes
+
+=back
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the whole kerning table into structures
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($dat, $i, $numt, $len, $cov, $t);
+
+    $self->SUPER::read or return $self;
+
+    $fh->read($dat, 4);
+    ($self->{'Version'}, $numt) = unpack("n2", $dat);
+    $self->{'Num'} = $numt;
+
+    for ($i = 0; $i < $numt; $i++)
+    {
+        $t = {};
+        $fh->read($dat, 6);
+        ($t->{'Version'}, $len, $cov) = unpack("n3", $dat);
+        $t->{'coverage'} = $cov & 255;
+        $t->{'type'} = $cov >> 8;
+        $fh->read($dat, $len - 6);
+        if ($t->{'Version'} == 0)
+        {
+            my ($j);
+
+            $t->{'Num'} = unpack("n", $dat);
+            for ($j = 0; $j < $t->{'Num'}; $j++)
+            {
+                my ($f, $l, $v) = TTF_Unpack("SSs", substr($dat, $j * 6 + 8, 6));
+                $t->{'kern'}{$f}{$l} = $v;
+            }
+        } elsif ($t->{'Version'} == 2)
+        {
+            my ($wid, $off, $numg, $maxl, $maxr, $j);
+            
+            $wid = unpack("n", $dat);
+            $off = unpack("n", substr($dat, 2));
+            ($t->{'left_first'}, $numg) = unpack("n2", substr($dat, $off));
+            $t->{'left'} = [unpack("C$numg", substr($dat, $off + 4))];
+            foreach (@{$t->{'left'}})
+            {
+                $_ /= $wid;
+                $maxl = $_ if ($_ > $maxl);
+            }
+            $t->{'left_max'} = $maxl;
+
+            $off = unpack("n", substr($dat, 4));
+            ($t->{'right_first'}, $numg) = unpack("n2", substr($dat, $off));
+            $t->{'right'} = [unpack("C$numg", substr($dat, $off + 4))];
+            foreach (@{$t->{'right'}})
+            {
+                $_ >>= 1;
+                $maxr = $_ if ($_ > $maxr);
+            }
+            $t->{'right_max'} = $maxr;
+
+            $off = unpack("n", substr($dat, 6));
+            for ($j = 0; $j <= $maxl; $j++)
+            {
+                my ($k) = 0;
+
+                map { $t->{'kern'}{$j}{$k} = $_ if $_; $k++; }
+                        unpack("n$maxr", substr($dat, $off + $wid * $j));
+            }
+        }
+        push (@{$self->{'tables'}}, $t);
+    }
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Outputs the kerning tables to the given file
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($i, $l, $r, $loc, $loc1, $t);
+
+    return $self->SUPER::out($fh) unless ($self->{' read'});
+
+    $fh->print(pack("n2", $self->{'Version'}, $self->{'Num'}));
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $t = $self->{'tables'}[$i];
+        $loc = $fh->tell();
+
+        $fh->print(pack("nnn", $t->{'Version'}, 0, $t->{'coverage'}));
+        if ($t->{'Version'} == 0)
+        {
+            my ($dat);
+            foreach $l (sort {$a <=> $b} keys %{$t->{'kern'}})
+            {
+                foreach $r (sort {$a <=> $b} keys %{$t->{'kern'}{$l}})
+                { $dat .= TTF_Pack("SSs", $l, $r, $t->{'kern'}{$l}{$r}); }
+            }
+            $fh->print(TTF_Pack("SSSS", Font::TTF::Utils::TTF_bininfo(length($dat) / 6, 6)));
+            $fh->print($dat);
+        } elsif ($t->{'Version'} == 2)
+        {
+            my ($arr);
+
+            $fh->print(pack("nnnn", $t->{'right_max'} << 1, 8, ($#{$t->{'left'}} + 7) << 1,
+                    ($#{$t->{'left'}} + $#{$t->{'right'}} + 10) << 1));
+
+            $fh->print(pack("nn", $t->{'left_first'}, $#{$t->{'left'}} + 1));
+            foreach (@{$t->{'left'}})
+            { $fh->print(pack("C", $_ * (($t->{'left_max'} + 1) << 1))); }
+
+            $fh->print(pack("nn", $t->{'right_first'}, $#{$t->{'right'}} + 1));
+            foreach (@{$t->{'right'}})
+            { $fh->print(pack("C", $_ << 1)); }
+
+            $arr = "\000\000" x (($t->{'left_max'} + 1) * ($t->{'right_max'} + 1));
+            foreach $l (keys %{$t->{'kern'}})
+            {
+                foreach $r (keys %{$t->{'kern'}{$l}})
+                { substr($arr, ($l * ($t->{'left_max'} + 1) + $r) << 1, 2)
+                        = pack("n", $t->{'kern'}{$l}{$r}); }
+            }
+            $fh->print($arr);
+        }
+        $loc1 = $fh->tell();
+        $fh->seek($loc + 2, 0);
+        $fh->print(pack("n", $loc1 - $loc));
+        $fh->seek($loc1, 0);
+    }
+    $self;
+}
+
+
+=head2 $t->XML_element($context, $depth, $key, $value)
+
+Handles outputting the kern hash into XML a little more tidily
+
+=cut
+
+sub XML_element
+{
+    my ($self) = shift;
+    my ($context, $depth, $key, $value) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($f, $l);
+
+    return $self->SUPER::XML_element(@_) unless ($key eq 'kern');
+    $fh->print("$depth<kern-table>\n");
+    foreach $f (sort {$a <=> $b} keys %{$value})
+    {
+        foreach $l (sort {$a <=> $b} keys %{$value->{$f}})
+        { $fh->print("$depth$context->{'indent'}<adjust first='$f' last='$l' dist='$value->{$f}{$l}'/>\n"); }
+    }
+    $fh->print("$depth</kern-table>\n");
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+Only supports kerning table types 0 & 2.
+
+=item *
+
+No real support functions to I<do> anything with the kerning tables yet.
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/LTSH.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/LTSH.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/LTSH.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,88 +1,88 @@
-package Font::TTF::LTSH;
-
-=head1 NAME
-
-Font::TTF::LTSH - Linear Threshold table
-
-=head1 DESCRIPTION
-
-Holds the linear threshold for each glyph. This is the ppem value at which a
-glyph's metrics become linear. The value is set to 1 if a glyph's metrics are
-always linear.
-
-=head1 INSTANCE VARIABLES
-
-=over 4
-
-=item glyphs
-
-An array of ppem values. One value per glyph
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($numg, $dat);
-
-    $self->SUPER::read or return $self;
-
-    $fh->read($dat, 4);
-    ($self->{'Version'}, $numg) = unpack("nn", $dat);
-    $self->{'Num'} = $numg;
-
-    $fh->read($dat, $numg);
-    $self->{'glyphs'} = [unpack("C$numg", $dat)];
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Outputs the LTSH to the given fh.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-
-    return $self->SUPER::out($fh) unless ($self->{' read'});
-
-    $fh->print(pack("nn", 0, $numg));
-    $fh->print(pack("C$numg", @{$self->{'glyphs'}}));
-    $self;
-}
-    
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::LTSH;
+
+=head1 NAME
+
+Font::TTF::LTSH - Linear Threshold table
+
+=head1 DESCRIPTION
+
+Holds the linear threshold for each glyph. This is the ppem value at which a
+glyph's metrics become linear. The value is set to 1 if a glyph's metrics are
+always linear.
+
+=head1 INSTANCE VARIABLES
+
+=over 4
+
+=item glyphs
+
+An array of ppem values. One value per glyph
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($numg, $dat);
+
+    $self->SUPER::read or return $self;
+
+    $fh->read($dat, 4);
+    ($self->{'Version'}, $numg) = unpack("nn", $dat);
+    $self->{'Num'} = $numg;
+
+    $fh->read($dat, $numg);
+    $self->{'glyphs'} = [unpack("C$numg", $dat)];
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Outputs the LTSH to the given fh.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+
+    return $self->SUPER::out($fh) unless ($self->{' read'});
+
+    $fh->print(pack("nn", 0, $numg));
+    $fh->print(pack("C$numg", @{$self->{'glyphs'}}));
+    $self;
+}
+    
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Loca.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Loca.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Loca.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,183 +1,183 @@
-package Font::TTF::Loca;
-
-=head1 NAME
-
-Font::TTF::Loca - the Locations table, which is intimately tied to the glyf table
-
-=head1 DESCRIPTION
-
-The location table holds the directory of locations of each glyph within the
-glyf table. Due to this relationship and the unimportance of the actual locations
-when it comes to holding glyphs in memory, reading the location table results
-in the creation of glyph objects for each glyph and stores them here.
-So if you are looking for glyphs, don't look in the C<glyf> table, look here
-instead.
-
-Things get complicated if you try to change the glyph list within the one table.
-The recommendation is to create another clean location object to replace this
-table in the font, ensuring that the old table is read first and to transfer
-or copy glyphs across from the read table to the new table.
-
-=head1 INSTANCE VARIABLES
-
-The instance variables do not start with a space
-
-=over 4
-
-=item glyphs
-
-An array of glyph objects for each glyph.
-
-=item glyphtype
-
-A string containing the class name to create for each new glyph. If empty,
-defaults to L<Font::TTF::Glyph>.
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
- at ISA = qw(Font::TTF::Table);
-
-require Font::TTF::Glyph;
-
-
-=head2 $t->new
-
-Creates a new location table making sure it has a glyphs array
-
-=cut
-
-sub new
-{
-    my ($class) = shift;
-    my ($res) = $class->SUPER::new(@_);
-    $res->{'glyphs'} = [];
-    $res;
-}
-
-=head2 $t->read
-
-Reads the location table creating glyph objects (L<Font::TTF::Glyph>) for each glyph
-allowing their later reading.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($locFmt) = $self->{' PARENT'}{'head'}->read->{'indexToLocFormat'};
-    my ($numGlyphs) = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
-    my ($glyfLoc) = $self->{' PARENT'}{'glyf'}{' OFFSET'};
-    my ($dat, $last, $i, $loc);
-
-    $self->SUPER::read or return $self;
-    $fh->read($dat, $locFmt ? 4 : 2);
-    $last = unpack($locFmt ? "N" : "n", $dat);
-    for ($i = 0; $i < $numGlyphs; $i++)
-    {
-        $fh->read($dat, $locFmt ? 4 : 2);
-        $loc = unpack($locFmt ? "N" : "n", $dat);
-        $self->{'glyphs'}[$i] = ($self->{'glyphtype'} || "Font::TTF::Glyph")->new(
-                LOC => $last << ($locFmt ? 0 : 1),
-                OUTLOC => $last << ($locFmt ? 0 : 1),
-                PARENT => $self->{' PARENT'},
-                INFILE => $fh,
-                BASE => $glyfLoc,
-                OUTLEN => ($loc - $last) << ($locFmt ? 0 : 1),
-                LEN => ($loc - $last) << ($locFmt ? 0 : 1)) if ($loc != $last);
-        $last = $loc;
-    }
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the location table out to $fh. Notice that not having read the location
-table implies that the glyf table has not been read either, so the numbers in
-the location table are still valid. Let's hope that C<maxp/numGlyphs> and
-C<head/indexToLocFmt> haven't changed otherwise we are in big trouble.
-
-The function uses the OUTLOC location in the glyph calculated when the glyf
-table was attempted to be output.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($locFmt) = $self->{' PARENT'}{'head'}->read->{'indexToLocFormat'};
-    my ($numGlyphs) = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
-    my ($count, $i, $offset, $g);
-
-    return $self->SUPER::out($fh) unless ($self->{' read'});
-
-    $count = 0;
-    for ($i = 0; $i < $numGlyphs; $i++)
-    {
-        $g = ($self->{'glyphs'}[$i]) || "";
-        unless ($g)
-        {
-            $count++;
-            next;
-        } else
-        {
-            if ($locFmt)
-            { $fh->print(pack("N", $g->{' OUTLOC'}) x ($count + 1)); }
-            else
-            { $fh->print(pack("n", $g->{' OUTLOC'} >> 1) x ($count + 1)); }
-            $count = 0;
-            $offset = $g->{' OUTLOC'} + $g->{' OUTLEN'};
-        }
-    }
-    $fh->print(pack($locFmt ? "N" : "n", ($locFmt ? $offset: $offset >> 1)) x ($count + 1));
-}
-
-
-=head2 $t->out_xml($context, $depth)
-
-No need to output a loca table, this is dynamically generated
-
-=cut
-
-sub out_xml
-{ return $_[0]; }
-
-
-=head2 $t->glyphs_do(&func)
-
-Calls func for each glyph in this location table in numerical order:
-
-    &func($glyph, $glyph_num)
-
-=cut
-
-sub glyphs_do
-{
-    my ($self, $func) = @_;
-    my ($i);
-
-    for ($i = 0; $i <= $#{$self->{'glyphs'}}; $i++)
-    { &$func($self->{'glyphs'}[$i], $i) if defined $self->{'glyphs'}[$i]; }
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Loca;
+
+=head1 NAME
+
+Font::TTF::Loca - the Locations table, which is intimately tied to the glyf table
+
+=head1 DESCRIPTION
+
+The location table holds the directory of locations of each glyph within the
+glyf table. Due to this relationship and the unimportance of the actual locations
+when it comes to holding glyphs in memory, reading the location table results
+in the creation of glyph objects for each glyph and stores them here.
+So if you are looking for glyphs, don't look in the C<glyf> table, look here
+instead.
+
+Things get complicated if you try to change the glyph list within the one table.
+The recommendation is to create another clean location object to replace this
+table in the font, ensuring that the old table is read first and to transfer
+or copy glyphs across from the read table to the new table.
+
+=head1 INSTANCE VARIABLES
+
+The instance variables do not start with a space
+
+=over 4
+
+=item glyphs
+
+An array of glyph objects for each glyph.
+
+=item glyphtype
+
+A string containing the class name to create for each new glyph. If empty,
+defaults to L<Font::TTF::Glyph>.
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+ at ISA = qw(Font::TTF::Table);
+
+require Font::TTF::Glyph;
+
+
+=head2 $t->new
+
+Creates a new location table making sure it has a glyphs array
+
+=cut
+
+sub new
+{
+    my ($class) = shift;
+    my ($res) = $class->SUPER::new(@_);
+    $res->{'glyphs'} = [];
+    $res;
+}
+
+=head2 $t->read
+
+Reads the location table creating glyph objects (L<Font::TTF::Glyph>) for each glyph
+allowing their later reading.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($locFmt) = $self->{' PARENT'}{'head'}->read->{'indexToLocFormat'};
+    my ($numGlyphs) = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
+    my ($glyfLoc) = $self->{' PARENT'}{'glyf'}{' OFFSET'};
+    my ($dat, $last, $i, $loc);
+
+    $self->SUPER::read or return $self;
+    $fh->read($dat, $locFmt ? 4 : 2);
+    $last = unpack($locFmt ? "N" : "n", $dat);
+    for ($i = 0; $i < $numGlyphs; $i++)
+    {
+        $fh->read($dat, $locFmt ? 4 : 2);
+        $loc = unpack($locFmt ? "N" : "n", $dat);
+        $self->{'glyphs'}[$i] = ($self->{'glyphtype'} || "Font::TTF::Glyph")->new(
+                LOC => $last << ($locFmt ? 0 : 1),
+                OUTLOC => $last << ($locFmt ? 0 : 1),
+                PARENT => $self->{' PARENT'},
+                INFILE => $fh,
+                BASE => $glyfLoc,
+                OUTLEN => ($loc - $last) << ($locFmt ? 0 : 1),
+                LEN => ($loc - $last) << ($locFmt ? 0 : 1)) if ($loc != $last);
+        $last = $loc;
+    }
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the location table out to $fh. Notice that not having read the location
+table implies that the glyf table has not been read either, so the numbers in
+the location table are still valid. Let's hope that C<maxp/numGlyphs> and
+C<head/indexToLocFmt> haven't changed otherwise we are in big trouble.
+
+The function uses the OUTLOC location in the glyph calculated when the glyf
+table was attempted to be output.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($locFmt) = $self->{' PARENT'}{'head'}->read->{'indexToLocFormat'};
+    my ($numGlyphs) = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
+    my ($count, $i, $offset, $g);
+
+    return $self->SUPER::out($fh) unless ($self->{' read'});
+
+    $count = 0;
+    for ($i = 0; $i < $numGlyphs; $i++)
+    {
+        $g = ($self->{'glyphs'}[$i]) || "";
+        unless ($g)
+        {
+            $count++;
+            next;
+        } else
+        {
+            if ($locFmt)
+            { $fh->print(pack("N", $g->{' OUTLOC'}) x ($count + 1)); }
+            else
+            { $fh->print(pack("n", $g->{' OUTLOC'} >> 1) x ($count + 1)); }
+            $count = 0;
+            $offset = $g->{' OUTLOC'} + $g->{' OUTLEN'};
+        }
+    }
+    $fh->print(pack($locFmt ? "N" : "n", ($locFmt ? $offset: $offset >> 1)) x ($count + 1));
+}
+
+
+=head2 $t->out_xml($context, $depth)
+
+No need to output a loca table, this is dynamically generated
+
+=cut
+
+sub out_xml
+{ return $_[0]; }
+
+
+=head2 $t->glyphs_do(&func)
+
+Calls func for each glyph in this location table in numerical order:
+
+    &func($glyph, $glyph_num)
+
+=cut
+
+sub glyphs_do
+{
+    my ($self, $func) = @_;
+    my ($i);
+
+    for ($i = 0; $i <= $#{$self->{'glyphs'}}; $i++)
+    { &$func($self->{'glyphs'}[$i], $i) if defined $self->{'glyphs'}[$i]; }
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Manual.pod
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Manual.pod	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Manual.pod	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,214 +1,214 @@
-
-=head1 NAME
-
-Manual.pod - Information regarding the whole module set
-
-=head1 INTRODUCTION
-
-This document looks at the whole issue of how the various modules in the
-TrueType Font work together. As such it is partly information on this font
-system and partly information on TrueType fonts in general.
-
-Due to the inter-relation between so many tables in a TrueType font, different
-tables will make expectations as to which other tables exist. At the very least
-a font should consist of a C<head> table and a C<maxp> table. The system has
-been designed around the expectation that the necessary tables for font
-rendering in the Windows environment exist. But inter table dependencies have
-been kept to what are considered necessary.
-
-This module set is not meant as a simple to use, mindless, font editing suite,
-but as a low-level, get your hands dirty, know what you are doing, set of
-classes for those who understand the intricacies (and there are many) of
-TrueType fonts. To this end, if you get something wrong in the data structures,
-etc. then this module set won't tell you and will happily create fonts which
-don't work.
-
-At the time of writing, not every TrueType table in existence has been
-implemented! Only the core basic tables of TrueType 1.0 (i.e. no embedded bitmap
-tables, no postscript type tables, no OpenType tables and no GX tables) have
-been implemented. If you want to help by implementing another table or two, then
-please go ahead and send me your code. For a full list of tables, see
-L<Font::TTF::Font>.
-
-
-=head2 Design Principles
-
-PERL is not C++. C++ encourages methods to be written for changing and reading
-each instance variable in a class. If we did this in this PERL program the
-results would be rather large and slow. Instead, since most access will be read
-access, we expose as much of the inner storage of an object to user access
-directly via hash lookup. The advantage this gives are great. For example, by
-following an instance variable chain, looking up the C<yMax> parameter for a
-particular glyph becomes:
-
-    $f->{'loca'}{'glyphs'}[$glyph]{'yMax'}
-
-Or, if we are feeling very lazy and don't mind waiting:
-
-    $f->{'loca'}{'glyphs'}[$f->{'cmap'}->ms_lookup(0x41)]{'yMax'}
-
-The disadvantage of this method is that it behoves module users to behave
-themselves. Thus it does not hold your hand and ensure that if you make a change
-to a table, that the table is marked as I<dirty>, or that other tables are
-updated accordingly.
-
-It is up to the application developer to understand the implications of the
-changes they make to a font, and to take the necessary action to ensure that the
-data they get out is what they want. Thus, you could go and change the C<yMax>
-value on a glyph and output a new font with this change, but it is up to you to
-ensure that the font's bounding box details in the C<head> table are correct,
-and even that your changing C<yMax> is well motivated.
-
-To help with using the system, each module (or table) will not only describe the
-methods it supports, which are relatively few, but also the instance variables
-it supports, which are many. Most of the variables directly reflect table
-attributes as specified in the OpenType specification, available from Microsoft
-(L<http::/www.microsoft.com/typography>), Adobe and Apple. A list of the names
-used is also given in each module, but not necessarily with any further
-description. After all, this code is not a TrueType manual as well!
-
-
-=head2 Conventions
-
-There are various conventions used in this system.
-
-Firstly we consider the documentation conventions regarding instance variables.
-Each instance variable is marked indicating whether it is a B<(P)>rivate
-variable which users of the module are not expected to read and certainly not
-write to or a B<(R)>ead only variable which users may well want to read but not
-write to.
-
-
-=head1 METHODS
-
-This section examines various methods and how the various modules work with
-these methods.
-
-
-=head2 read and read_dat
-
-Before the data structures for a table can be accessed, they need to be filled
-in from somewhere. The usual way to do this is to read an existing TrueType
-font. This may be achieved by:
-
-    $f = Font::TTF::Font->open($filename) || die "Unable to read $filename";
-
-This will open an existing font and read its directory header. Notice that at
-this point, none of the tables in the font have been read. (Actually, the
-C<head> and C<maxp> tables are read at this point too since they contain the
-commonly required parameters of):
-
-    $f->{'head'}{'unitsPerEm'}
-    $f->{'maxp'}{'numGlyphs'}
-
-In order to be able to access information from a table, it is first necessary to
-C<read> it. Consider trying to find the advance width of a space character
-(U+0020). The following code should do it:
-
-    $f = Font::TTF::Font->open($ARGV[0]);
-    $snum = $f->{'cmap'}->ms_lookup(0x0020);
-    $sadv = $f->{'hmtx'}{'advance'}[$snum];
-    print $sadv;
-
-This would result in the value zero being printed, which is far from correct.
-But why? The first line would correctly read the font directory. The second line
-would, incidently, correctly locate the space character in the Windows cmap
-(assuming a non symbol encoded font). The third line would not succeed in its
-task since the C<hmtx> table has not been filled in from the font file. To
-achieve what we want we would first need to cause it to be read:
-
-    $f->{'hmtx'}->read;
-    $sadv = $f->{'hmtx'}{'advance'}[$snum];
-
-Or for those who are too lazy to write multiple lines, C<read> returns the
-object it reads. Thus we could write:
-
-    $sadv = $f->{'hmtx'}->read->{'advance'}[$snum];
-
-Why, if we always have to read tables before accessing information from them,
-did we not have to do this for the C<cmap> table? The answer lies in the method
-call. It senses that the table hasn't been read and reads it for us. This will
-generally happen with all method calls, it is only when we do direct data access
-that we have to take the responsibility to read the table first.
-
-Reading a table does not necessarily result in all the data being placed into
-internal data structures. In the case of a simple table C<read> is sufficient.
-In fact, the normal case is that C<read_dat> reads the data from the file into
-an instance variable called C<' dat'> (including the space) and not into the
-data structures.
-
-This is true except for the C<glyph> class which represents a single glyph. Here
-the process is reversed. Reading a C<glyph> reads the data for the glyph into
-the C<' dat'> instance variable and sets various header attributes for the glyph
-(C<xMin>, C<numContours>, etc.). The data is converted out of the variable into
-data structures via the C<read_dat> method.
-
-The aim, therefore, is that C<read> should do the natural thing (read into data
-structures for those tables and elements for which it is helpful -- all except
-C<glyph> at present) and C<read_dat> should do the unnatural thing: read just
-the binary data for normal tables and convert binary data to data structures for
-C<glyph>s.
-
-In summary, therefore, use C<read> unless you want to hack around with the
-internals of glyphs in which case see L<Font::TTF::Glyph> for more details.
-
-
-=head2 update
-
-The aim of this method is to allow the various data elements in a C<read> font
-to update themselves. All tables know how to update themselves. All tables also
-contain information which cannot be I<updated> but is new knowledge in the font.
-As a result, certain tables do nothing when they are updated. We can, therefore,
-build an update hierarchy of tables, with the independent tables at the bottom
-and C<Font> at the top:
-
-       +--loca
-       |
- glyf--+--maxp
-       |
-       +---+--head
-           |
- hmtx------+--hhea
-
- cmap-----OS/2
-
- name--
-
- post--
- 
-There is an important universal dependency which it is up to the user to
-keep up to date. This is C<maxp/numOfGlyphs> which is used to iterate over all
-the glyphs. Note that the glyphs themselves are not held in the C<glyph> table
-but in the C<loca> table, so adding glyphs, etc. automatically involves keeping
-the C<loca> table up to date.
-
-=head2 Creating fonts
-
-Suppose we were creating a font from scratch. How much information do we need
-to supply and how much will C<update> do for us?
-
-The following information is required:
-
-    $f->{'loca'}{'glyphs'}
-    $f->{'head'}{'upem'}
-    $f->{'maxp'}{'numGlyphs'}   (doesn't come from $f->{'loca'}{'glyphs'})
-    $f->{'hmtx'}{'advance'}
-    $f->{'post'}['format'}
-    $f->{'post'}{'VAL'}
-    $f->{'cmap'}
-    $f->{'name'}
-
-Pretty much everything else is calculated for you. Details of what is needed
-for a glyph may be found in L<Font::TTF::Glyph>. Once we have all the
-information we need (and there is lots more that you could add) then we simply
-
-    $f->dirty;          # mark all tables dirty
-    $f->update;         # update the font
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+
+=head1 TITLE
+
+Manual.pod - Information regarding the whole module set
+
+=head1 INTRODUCTION
+
+This document looks at the whole issue of how the various modules in the
+TrueType Font work together. As such it is partly information on this font
+system and partly information on TrueType fonts in general.
+
+Due to the inter-relation between so many tables in a TrueType font, different
+tables will make expectations as to which other tables exist. At the very least
+a font should consist of a C<head> table and a C<maxp> table. The system has
+been designed around the expectation that the necessary tables for font
+rendering in the Windows environment exist. But inter table dependencies have
+been kept to what are considered necessary.
+
+This module set is not meant as a simple to use, mindless, font editing suite,
+but as a low-level, get your hands dirty, know what you are doing, set of
+classes for those who understand the intricacies (and there are many) of
+TrueType fonts. To this end, if you get something wrong in the data structures,
+etc. then this module set won't tell you and will happily create fonts which
+don't work.
+
+At the time of writing, not every TrueType table in existence has been
+implemented! Only the core basic tables of TrueType 1.0 (i.e. no embedded bitmap
+tables, no postscript type tables, no OpenType tables and no GX tables) have
+been implemented. If you want to help by implementing another table or two, then
+please go ahead and send me your code. For a full list of tables, see
+L<Font::TTF::Font>.
+
+
+=head2 Design Principles
+
+PERL is not C++. C++ encourages methods to be written for changing and reading
+each instance variable in a class. If we did this in this PERL program the
+results would be rather large and slow. Instead, since most access will be read
+access, we expose as much of the inner storage of an object to user access
+directly via hash lookup. The advantage this gives are great. For example, by
+following an instance variable chain, looking up the C<yMax> parameter for a
+particular glyph becomes:
+
+    $f->{'loca'}{'glyphs'}[$glyph]{'yMax'}
+
+Or, if we are feeling very lazy and don't mind waiting:
+
+    $f->{'loca'}{'glyphs'}[$f->{'cmap'}->ms_lookup(0x41)]{'yMax'}
+
+The disadvantage of this method is that it behoves module users to behave
+themselves. Thus it does not hold your hand and ensure that if you make a change
+to a table, that the table is marked as I<dirty>, or that other tables are
+updated accordingly.
+
+It is up to the application developer to understand the implications of the
+changes they make to a font, and to take the necessary action to ensure that the
+data they get out is what they want. Thus, you could go and change the C<yMax>
+value on a glyph and output a new font with this change, but it is up to you to
+ensure that the font's bounding box details in the C<head> table are correct,
+and even that your changing C<yMax> is well motivated.
+
+To help with using the system, each module (or table) will not only describe the
+methods it supports, which are relatively few, but also the instance variables
+it supports, which are many. Most of the variables directly reflect table
+attributes as specified in the OpenType specification, available from Microsoft
+(L<http::/www.microsoft.com/typography>), Adobe and Apple. A list of the names
+used is also given in each module, but not necessarily with any further
+description. After all, this code is not a TrueType manual as well!
+
+
+=head2 Conventions
+
+There are various conventions used in this system.
+
+Firstly we consider the documentation conventions regarding instance variables.
+Each instance variable is marked indicating whether it is a B<(P)>rivate
+variable which users of the module are not expected to read and certainly not
+write to or a B<(R)>ead only variable which users may well want to read but not
+write to.
+
+
+=head1 METHODS
+
+This section examines various methods and how the various modules work with
+these methods.
+
+
+=head2 read and read_dat
+
+Before the data structures for a table can be accessed, they need to be filled
+in from somewhere. The usual way to do this is to read an existing TrueType
+font. This may be achieved by:
+
+    $f = Font::TTF::Font->open($filename) || die "Unable to read $filename";
+
+This will open an existing font and read its directory header. Notice that at
+this point, none of the tables in the font have been read. (Actually, the
+C<head> and C<maxp> tables are read at this point too since they contain the
+commonly required parameters of):
+
+    $f->{'head'}{'unitsPerEm'}
+    $f->{'maxp'}{'numGlyphs'}
+
+In order to be able to access information from a table, it is first necessary to
+C<read> it. Consider trying to find the advance width of a space character
+(U+0020). The following code should do it:
+
+    $f = Font::TTF::Font->open($ARGV[0]);
+    $snum = $f->{'cmap'}->ms_lookup(0x0020);
+    $sadv = $f->{'hmtx'}{'advance'}[$snum];
+    print $sadv;
+
+This would result in the value zero being printed, which is far from correct.
+But why? The first line would correctly read the font directory. The second line
+would, incidently, correctly locate the space character in the Windows cmap
+(assuming a non symbol encoded font). The third line would not succeed in its
+task since the C<hmtx> table has not been filled in from the font file. To
+achieve what we want we would first need to cause it to be read:
+
+    $f->{'hmtx'}->read;
+    $sadv = $f->{'hmtx'}{'advance'}[$snum];
+
+Or for those who are too lazy to write multiple lines, C<read> returns the
+object it reads. Thus we could write:
+
+    $sadv = $f->{'hmtx'}->read->{'advance'}[$snum];
+
+Why, if we always have to read tables before accessing information from them,
+did we not have to do this for the C<cmap> table? The answer lies in the method
+call. It senses that the table hasn't been read and reads it for us. This will
+generally happen with all method calls, it is only when we do direct data access
+that we have to take the responsibility to read the table first.
+
+Reading a table does not necessarily result in all the data being placed into
+internal data structures. In the case of a simple table C<read> is sufficient.
+In fact, the normal case is that C<read_dat> reads the data from the file into
+an instance variable called C<' dat'> (including the space) and not into the
+data structures.
+
+This is true except for the C<glyph> class which represents a single glyph. Here
+the process is reversed. Reading a C<glyph> reads the data for the glyph into
+the C<' dat'> instance variable and sets various header attributes for the glyph
+(C<xMin>, C<numContours>, etc.). The data is converted out of the variable into
+data structures via the C<read_dat> method.
+
+The aim, therefore, is that C<read> should do the natural thing (read into data
+structures for those tables and elements for which it is helpful -- all except
+C<glyph> at present) and C<read_dat> should do the unnatural thing: read just
+the binary data for normal tables and convert binary data to data structures for
+C<glyph>s.
+
+In summary, therefore, use C<read> unless you want to hack around with the
+internals of glyphs in which case see L<Font::TTF::Glyph> for more details.
+
+
+=head2 update
+
+The aim of this method is to allow the various data elements in a C<read> font
+to update themselves. All tables know how to update themselves. All tables also
+contain information which cannot be I<updated> but is new knowledge in the font.
+As a result, certain tables do nothing when they are updated. We can, therefore,
+build an update hierarchy of tables, with the independent tables at the bottom
+and C<Font> at the top:
+
+       +--loca
+       |
+ glyf--+--maxp
+       |
+       +---+--head
+           |
+ hmtx------+--hhea
+
+ cmap-----OS/2
+
+ name--
+
+ post--
+ 
+There is an important universal dependency which it is up to the user to
+keep up to date. This is C<maxp/numOfGlyphs> which is used to iterate over all
+the glyphs. Note that the glyphs themselves are not held in the C<glyph> table
+but in the C<loca> table, so adding glyphs, etc. automatically involves keeping
+the C<loca> table up to date.
+
+=head2 Creating fonts
+
+Suppose we were creating a font from scratch. How much information do we need
+to supply and how much will C<update> do for us?
+
+The following information is required:
+
+    $f->{'loca'}{'glyphs'}
+    $f->{'head'}{'upem'}
+    $f->{'maxp'}{'numGlyphs'}   (doesn't come from $f->{'loca'}{'glyphs'})
+    $f->{'hmtx'}{'advance'}
+    $f->{'post'}['format'}
+    $f->{'post'}{'VAL'}
+    $f->{'cmap'}
+    $f->{'name'}
+
+Pretty much everything else is calculated for you. Details of what is needed
+for a glyph may be found in L<Font::TTF::Glyph>. Once we have all the
+information we need (and there is lots more that you could add) then we simply
+
+    $f->dirty;          # mark all tables dirty
+    $f->update;         # update the font
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Maxp.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Maxp.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Maxp.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,177 +1,177 @@
-package Font::TTF::Maxp;
-
-=head1 NAME
-
-Font::TTF::Maxp - Maximum Profile table in a font
-
-=head1 DESCRIPTION
-
-A collection of useful instance variables following the TTF standard. Probably
-the most used being C<numGlyphs>. Note that this particular value is
-foundational and should be kept up to date by the application, it is not updated
-by C<update>.
-
-Handles table versions 0.5, 1.0
-
-=head1 INSTANCE VARIABLES
-
-No others beyond those specified in the standard:
-
-    numGlyphs
-    maxPoints
-    maxContours
-    maxCompositePoints
-    maxCompositeContours
-    maxZones
-    maxTwilightPoints
-    maxStorage
-    maxFunctionDefs
-    maxInstructionDefs
-    maxStackElements
-    maxSizeOfInstructions
-    maxComponentElements
-    maxComponentDepth
-
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'numGlyphs' => 'S',
-    'maxPoints' => 'S',
-    'maxContours' => 'S',
-    'maxCompositePoints' => 'S',
-    'maxCompositeContours' => 'S',
-    'maxZones' => 'S',
-    'maxTwilightPoints' => 'S',
-    'maxStorage' => 'S',
-    'maxFunctionDefs' => 'S',
-    'maxInstructionDefs' => 'S',
-    'maxStackElements' => 'S',
-    'maxSizeOfInstructions' => 'S',
-    'maxComponentElements' => 'S',
-    'maxComponentDepth' => 'S');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read or return $self;
-
-    init unless defined $fields{'numGlyphs'};    # any key would do
-    $self->{' INFILE'}->read($dat, 4);
-    $self->{'version'} = TTF_Unpack("f", $dat);
-
-    if ($self->{'version'} == 0.5)
-    {
-        $self->{' INFILE'}->read($dat, 2);
-        $self->{'numGlyphs'} = unpack("n", $dat);
-    } else
-    {
-        $self->{' INFILE'}->read($dat, 28);
-        TTF_Read_Fields($self, $dat, \%fields);
-    }
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-    $fh->print(TTF_Pack("f", $self->{'version'}));
-    
-    if ($self->{'version'} == 0.5)
-    { $fh->print(pack("n", $self->{'numGlyphs'})); }
-    else
-    { $fh->print(TTF_Out_Fields($self, \%fields, 28)); }
-    $self;
-}
-
-
-=head2 $t->update
-
-Calculates all the maximum values for a font based on the glyphs in the font.
-Only those fields which require hinting code interpretation are ignored and
-left as they were read.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($i, $num, @n, @m, $j);
-    my (@name) = qw(maxPoints maxContours maxCompositePoints maxCompositeContours
-                    maxSizeOfInstructions maxComponentElements maxComponentDepth);
-
-    return undef unless ($self->SUPER::update);
-    return undef if ($self->{'version'} == 0.5);        # only got numGlyphs
-    return undef unless (defined $self->{' PARENT'}{'loca'});
-    $self->{' PARENT'}{'loca'}->update;
-    $num = $self->{'numGlyphs'};
-
-    for ($i = 0; $i < $num; $i++)
-    {
-        my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i] || next;
-
-        @n = $g->maxInfo($self->{' PARENT'}{'loca'}{'glyphs'});
-
-        for ($j = 0; $j <= $#n; $j++)
-        { $m[$j] = $n[$j] if $n[$j] > $m[$j]; }
-    }
-
-    foreach ('prep', 'fpgm')
-    { $m[4] = length($self->{' PARENT'}{$_}{' dat'})
-            if (defined $self->{' PARENT'}{$_} 
-                && length($self->{' PARENT'}{$_}{' dat'}) > $m[4]);
-    }
-
-    for ($j = 0; $j <= $#name; $j++)
-    { $self->{$name[$j]} = $m[$j]; }
-    $self;
-}
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
+package Font::TTF::Maxp;
+
+=head1 NAME
+
+Font::TTF::Maxp - Maximum Profile table in a font
+
+=head1 DESCRIPTION
+
+A collection of useful instance variables following the TTF standard. Probably
+the most used being C<numGlyphs>. Note that this particular value is
+foundational and should be kept up to date by the application, it is not updated
+by C<update>.
+
+Handles table versions 0.5, 1.0
+
+=head1 INSTANCE VARIABLES
+
+No others beyond those specified in the standard:
+
+    numGlyphs
+    maxPoints
+    maxContours
+    maxCompositePoints
+    maxCompositeContours
+    maxZones
+    maxTwilightPoints
+    maxStorage
+    maxFunctionDefs
+    maxInstructionDefs
+    maxStackElements
+    maxSizeOfInstructions
+    maxComponentElements
+    maxComponentDepth
+
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'numGlyphs' => 'S',
+    'maxPoints' => 'S',
+    'maxContours' => 'S',
+    'maxCompositePoints' => 'S',
+    'maxCompositeContours' => 'S',
+    'maxZones' => 'S',
+    'maxTwilightPoints' => 'S',
+    'maxStorage' => 'S',
+    'maxFunctionDefs' => 'S',
+    'maxInstructionDefs' => 'S',
+    'maxStackElements' => 'S',
+    'maxSizeOfInstructions' => 'S',
+    'maxComponentElements' => 'S',
+    'maxComponentDepth' => 'S');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read or return $self;
+
+    init unless defined $fields{'numGlyphs'};    # any key would do
+    $self->{' INFILE'}->read($dat, 4);
+    $self->{'version'} = TTF_Unpack("f", $dat);
+
+    if ($self->{'version'} == 0.5)
+    {
+        $self->{' INFILE'}->read($dat, 2);
+        $self->{'numGlyphs'} = unpack("n", $dat);
+    } else
+    {
+        $self->{' INFILE'}->read($dat, 28);
+        TTF_Read_Fields($self, $dat, \%fields);
+    }
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+    $fh->print(TTF_Pack("f", $self->{'version'}));
+    
+    if ($self->{'version'} == 0.5)
+    { $fh->print(pack("n", $self->{'numGlyphs'})); }
+    else
+    { $fh->print(TTF_Out_Fields($self, \%fields, 28)); }
+    $self;
+}
+
+
+=head2 $t->update
+
+Calculates all the maximum values for a font based on the glyphs in the font.
+Only those fields which require hinting code interpretation are ignored and
+left as they were read.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($i, $num, @n, @m, $j);
+    my (@name) = qw(maxPoints maxContours maxCompositePoints maxCompositeContours
+                    maxSizeOfInstructions maxComponentElements maxComponentDepth);
+
+    return undef unless ($self->SUPER::update);
+    return undef if ($self->{'version'} == 0.5);        # only got numGlyphs
+    return undef unless (defined $self->{' PARENT'}{'loca'});
+    $self->{' PARENT'}{'loca'}->update;
+    $num = $self->{'numGlyphs'};
+
+    for ($i = 0; $i < $num; $i++)
+    {
+        my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i] || next;
+
+        @n = $g->maxInfo($self->{' PARENT'}{'loca'}{'glyphs'});
+
+        for ($j = 0; $j <= $#n; $j++)
+        { $m[$j] = $n[$j] if $n[$j] > $m[$j]; }
+    }
+
+    foreach ('prep', 'fpgm')
+    { $m[4] = length($self->{' PARENT'}{$_}{' dat'})
+            if (defined $self->{' PARENT'}{$_} 
+                && length($self->{' PARENT'}{$_}{' dat'}) > $m[4]);
+    }
+
+    for ($j = 0; $j <= $#name; $j++)
+    { $self->{$name[$j]} = $m[$j]; }
+    $self;
+}
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Chain.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Chain.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Chain.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,195 +1,195 @@
-package Font::TTF::Mort::Chain;
-
-=head1 NAME
-
-Font::TTF::Mort::Chain
-
-=cut
-
-use strict;
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Mort::Subtable;
-
-=head2 $t->new
-
-=cut
-
-sub new
-{
-    my ($class, %parms) = @_;
-    my ($self) = {};
-    my ($p);
-
-    $class = ref($class) || $class;
-    foreach $p (keys %parms)
-    { $self->{" $p"} = $parms{$p}; }
-    bless $self, $class;
-}
-
-=head2 $t->read($fh)
-
-Reads the chain into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-
-    my $chainStart = $fh->tell();
-    $fh->read($dat, 12);
-    my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat);
-
-    my $featureEntries = [];
-    foreach (1 .. $nFeatureEntries) {
-        $fh->read($dat, 12);
-        my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat);
-        push @$featureEntries,    {
-                                    'type'        => $featureType,
-                                    'setting'    => $featureSetting,
-                                    'enable'    => $enableFlags,
-                                    'disable'    => $disableFlags
-                                };
-    }
-
-    my $subtables = [];
-    foreach (1 .. $nSubtables) {
-        my $subtableStart = $fh->tell();
-        
-        $fh->read($dat, 8);
-        my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat);
-        my $type = $coverage & 0x0007;
-
-        my $subtable = Font::TTF::Mort::Subtable->create($type, $coverage, $subFeatureFlags, $length);
-        $subtable->read($fh);
-        $subtable->{' PARENT'} = $self;
-        
-        push @$subtables, $subtable;
-        $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
-    }
-    
-    $self->{'defaultFlags'} = $defaultFlags;
-    $self->{'featureEntries'} = $featureEntries;
-    $self->{'subtables'} = $subtables;
-
-    $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    my $chainStart = $fh->tell();
-    my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'});
-    $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length
-    
-    foreach (@$featureEntries) {
-        $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}));
-    }
-    
-    foreach (@$subtables) {
-        $_->out($fh);
-    }
-    
-    my $chainLength = $fh->tell() - $chainStart;
-    $fh->seek($chainStart + 4, IO::File::SEEK_SET);
-    $fh->print(pack("N", $chainLength));
-    $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the chain
-
-=cut
-
-sub feat
-{
-    my ($self) = @_;
-    
-    my $feat = $self->{' PARENT'}{' PARENT'}{'feat'};
-    if (defined $feat) {
-        $feat->read;
-    }
-    else {
-        $feat = {};
-    }
-    
-    return $feat;
-}
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    $fh->printf("version %f\n", $self->{'version'});
-    
-    my $defaultFlags = $self->{'defaultFlags'};
-    $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags);
-    
-    my $feat = $self->feat();
-    my $featureEntries = $self->{'featureEntries'};
-    foreach (@$featureEntries) {
-        $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n",
-                    $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'},
-                    $feat->settingName($_->{'type'}, $_->{'setting'}));
-    }
-    
-    my $subtables = $self->{'subtables'};
-    foreach (@$subtables) {
-        my $type = $_->{'type'};
-        my $subFeatureFlags = $_->{'subFeatureFlags'};
-        $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
-                    subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
-                    "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
-                    join(", ",
-                        map {
-                            join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
-                        } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
-                    ) );
-        
-        $_->print($fh);
-    }
-}
-
-sub subtable_type_
-{
-    my ($val) = @_;
-    my ($res);
-    
-    my @types =    (
-                    'Rearrangement',
-                    'Contextual',
-                    'Ligature',
-                    undef,
-                    'Non-contextual',
-                    'Insertion',
-                );
-    $res = $types[$val] or ('Undefined (' . $val . ')');
-    
-    $res;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Chain;
+
+=head1 NAME
+
+Font::TTF::Mort::Chain
+
+=cut
+
+use strict;
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Mort::Subtable;
+
+=head2 $t->new
+
+=cut
+
+sub new
+{
+    my ($class, %parms) = @_;
+    my ($self) = {};
+    my ($p);
+
+    $class = ref($class) || $class;
+    foreach $p (keys %parms)
+    { $self->{" $p"} = $parms{$p}; }
+    bless $self, $class;
+}
+
+=head2 $t->read($fh)
+
+Reads the chain into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+
+    my $chainStart = $fh->tell();
+    $fh->read($dat, 12);
+    my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat);
+
+    my $featureEntries = [];
+    foreach (1 .. $nFeatureEntries) {
+        $fh->read($dat, 12);
+        my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat);
+        push @$featureEntries,    {
+                                    'type'        => $featureType,
+                                    'setting'    => $featureSetting,
+                                    'enable'    => $enableFlags,
+                                    'disable'    => $disableFlags
+                                };
+    }
+
+    my $subtables = [];
+    foreach (1 .. $nSubtables) {
+        my $subtableStart = $fh->tell();
+        
+        $fh->read($dat, 8);
+        my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat);
+        my $type = $coverage & 0x0007;
+
+        my $subtable = Font::TTF::Mort::Subtable->create($type, $coverage, $subFeatureFlags, $length);
+        $subtable->read($fh);
+        $subtable->{' PARENT'} = $self;
+        
+        push @$subtables, $subtable;
+        $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
+    }
+    
+    $self->{'defaultFlags'} = $defaultFlags;
+    $self->{'featureEntries'} = $featureEntries;
+    $self->{'subtables'} = $subtables;
+
+    $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    my $chainStart = $fh->tell();
+    my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'});
+    $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length
+    
+    foreach (@$featureEntries) {
+        $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}));
+    }
+    
+    foreach (@$subtables) {
+        $_->out($fh);
+    }
+    
+    my $chainLength = $fh->tell() - $chainStart;
+    $fh->seek($chainStart + 4, IO::File::SEEK_SET);
+    $fh->print(pack("N", $chainLength));
+    $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the chain
+
+=cut
+
+sub feat
+{
+    my ($self) = @_;
+    
+    my $feat = $self->{' PARENT'}{' PARENT'}{'feat'};
+    if (defined $feat) {
+        $feat->read;
+    }
+    else {
+        $feat = {};
+    }
+    
+    return $feat;
+}
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    $fh->printf("version %f\n", $self->{'version'});
+    
+    my $defaultFlags = $self->{'defaultFlags'};
+    $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags);
+    
+    my $feat = $self->feat();
+    my $featureEntries = $self->{'featureEntries'};
+    foreach (@$featureEntries) {
+        $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n",
+                    $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'},
+                    $feat->settingName($_->{'type'}, $_->{'setting'}));
+    }
+    
+    my $subtables = $self->{'subtables'};
+    foreach (@$subtables) {
+        my $type = $_->{'type'};
+        my $subFeatureFlags = $_->{'subFeatureFlags'};
+        $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
+                    subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
+                    "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
+                    join(", ",
+                        map {
+                            join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
+                        } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
+                    ) );
+        
+        $_->print($fh);
+    }
+}
+
+sub subtable_type_
+{
+    my ($val) = @_;
+    my ($res);
+    
+    my @types =    (
+                    'Rearrangement',
+                    'Contextual',
+                    'Ligature',
+                    undef,
+                    'Non-contextual',
+                    'Insertion',
+                );
+    $res = $types[$val] or ('Undefined (' . $val . ')');
+    
+    $res;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Contextual.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Contextual.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Contextual.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,156 +1,156 @@
-package Font::TTF::Mort::Contextual;
-
-=head1 NAME
-
-Font::TTF::Mort::Contextual
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Mort::Subtable;
-
- at ISA = qw(Font::TTF::AAT::Mort::Subtable);
-
-sub new
-{
-    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
-    my ($self) = {
-                    'direction'            => $direction,
-                    'orientation'        => $orientation,
-                    'subFeatureFlags'    => $subFeatureFlags
-                };
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-    
-    my $stateTableStart = $fh->tell();
-    my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
-
-    $fh->seek($stateTableStart, IO::File::SEEK_SET);
-    $fh->read($dat, 10);
-    my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat);
-    my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $self->{'length'} - 8];
-
-    foreach (@$entries) {
-        my $actions = $_->{'actions'};
-        foreach (@$actions) {
-            $_ = $_ ? $_ - ($mappingTables / 2) : undef;
-        }
-    }
-    
-    $self->{'classes'} = $classes;
-    $self->{'states'} = $states;
-    $self->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))];
-            
-    $self;
-}
-
-=head2 $t->pack_sub()
-
-=cut
-
-sub pack_sub
-{
-    my ($self) = @_;
-    
-    my ($dat) = pack("nnnnn", (0) x 5);    # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables
-    
-    my $classTable = length($dat);
-    my $classes = $self->{'classes'};
-    $dat .= AAT_pack_classes($classes);
-    
-    my $stateArray = length($dat);
-    my $states = $self->{'states'};
-    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, 
-            sub {
-                my $actions = $_->{'actions'};
-                ( $_->{'flags'}, @$actions )
-            }
-        );
-    $dat .= $dat1;
-    
-    my $entryTable = length($dat);
-    my $offset = ($entryTable + 8 * @$entries) / 2;
-    foreach (@$entries) {
-        my ($nextState, $flags, @parts) = split /,/;
-        $dat .= pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts);
-    }
-
-    my $mappingTables = length($dat);
-    my $mappings = $self->{'mappings'};
-    $dat .= pack("n*", @$mappings);
-    
-    $dat1 = pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables);
-    substr($dat, 0, length($dat1)) = $dat1;
-    
-    return $dat;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $self->print_classes($fh);
-    
-    $fh->print("\n");
-    my $states = $self->{'states'};
-    foreach (0 .. $#$states) {
-        $fh->printf("\t\tState %d:", $_);
-        my $state = $states->[$_];
-        foreach (@$state) {
-            my $flags;
-            $flags .= "!" if ($_->{'flags'} & 0x4000);
-            $flags .= "*" if ($_->{'flags'} & 0x8000);
-            my $actions = $_->{'actions'};
-            $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
-        }
-        $fh->print("\n");
-    }
-
-    $fh->print("\n");
-    my $mappings = $self->{'mappings'};
-    foreach (0 .. $#$mappings) {
-        $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]);
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Contextual;
+
+=head1 NAME
+
+Font::TTF::Mort::Contextual
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Mort::Subtable;
+
+ at ISA = qw(Font::TTF::AAT::Mort::Subtable);
+
+sub new
+{
+    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
+    my ($self) = {
+                    'direction'            => $direction,
+                    'orientation'        => $orientation,
+                    'subFeatureFlags'    => $subFeatureFlags
+                };
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+    
+    my $stateTableStart = $fh->tell();
+    my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
+
+    $fh->seek($stateTableStart, IO::File::SEEK_SET);
+    $fh->read($dat, 10);
+    my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat);
+    my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $self->{'length'} - 8];
+
+    foreach (@$entries) {
+        my $actions = $_->{'actions'};
+        foreach (@$actions) {
+            $_ = $_ ? $_ - ($mappingTables / 2) : undef;
+        }
+    }
+    
+    $self->{'classes'} = $classes;
+    $self->{'states'} = $states;
+    $self->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))];
+            
+    $self;
+}
+
+=head2 $t->pack_sub()
+
+=cut
+
+sub pack_sub
+{
+    my ($self) = @_;
+    
+    my ($dat) = pack("nnnnn", (0) x 5);    # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables
+    
+    my $classTable = length($dat);
+    my $classes = $self->{'classes'};
+    $dat .= AAT_pack_classes($classes);
+    
+    my $stateArray = length($dat);
+    my $states = $self->{'states'};
+    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, 
+            sub {
+                my $actions = $_->{'actions'};
+                ( $_->{'flags'}, @$actions )
+            }
+        );
+    $dat .= $dat1;
+    
+    my $entryTable = length($dat);
+    my $offset = ($entryTable + 8 * @$entries) / 2;
+    foreach (@$entries) {
+        my ($nextState, $flags, @parts) = split /,/;
+        $dat .= pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts);
+    }
+
+    my $mappingTables = length($dat);
+    my $mappings = $self->{'mappings'};
+    $dat .= pack("n*", @$mappings);
+    
+    $dat1 = pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables);
+    substr($dat, 0, length($dat1)) = $dat1;
+    
+    return $dat;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $self->print_classes($fh);
+    
+    $fh->print("\n");
+    my $states = $self->{'states'};
+    foreach (0 .. $#$states) {
+        $fh->printf("\t\tState %d:", $_);
+        my $state = $states->[$_];
+        foreach (@$state) {
+            my $flags;
+            $flags .= "!" if ($_->{'flags'} & 0x4000);
+            $flags .= "*" if ($_->{'flags'} & 0x8000);
+            my $actions = $_->{'actions'};
+            $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
+        }
+        $fh->print("\n");
+    }
+
+    $fh->print("\n");
+    my $mappings = $self->{'mappings'};
+    foreach (0 .. $#$mappings) {
+        $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]);
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Insertion.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Insertion.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Insertion.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,178 +1,178 @@
-package Font::TTF::Mort::Insertion;
-
-=head1 NAME
-
-Font::TTF::Mort::Insertion
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Mort::Subtable);
-
-sub new
-{
-    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
-    my ($self) = {
-                    'direction'            => $direction,
-                    'orientation'        => $orientation,
-                    'subFeatureFlags'    => $subFeatureFlags
-                };
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-    
-    my $subtableStart = $fh->tell();
-
-    my $stateTableStart = $fh->tell();
-    my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
-    
-    my %insertListHash;
-    my $insertLists;
-    foreach (@$entries) {
-        my $flags = $_->{'flags'};
-        my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f));
-        my $actions = $_->{'actions'};
-        foreach (0 .. 1) {
-            if ($insertCount[$_] > 0) {
-                $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET);
-                $fh->read($dat, $insertCount[$_] * 2);
-                if (not defined $insertListHash{$dat}) {
-                    push @$insertLists, [unpack("n*", $dat)];
-                    $insertListHash{$dat} = $#$insertLists;
-                }
-                $actions->[$_] = $insertListHash{$dat};
-            }
-            else {
-                $actions->[$_] = undef;
-            }
-        }
-    }
-
-    $self->{'classes'} = $classes;
-    $self->{'states'} = $states;
-    $self->{'insertLists'} = $insertLists;
-            
-    $self;
-}
-
-=head2 $t->pack_sub()
-
-=cut
-
-sub pack_sub
-{
-    my ($self) = @_;
-    
-    my ($dat) = pack("nnnn", (0) x 4);
-    
-    my $classTable = length($dat);
-    my $classes = $self->{'classes'};
-    $dat .= AAT_pack_classes($classes);
-    
-    my $stateArray = length($dat);
-    my $states = $self->{'states'};
-    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, 
-            sub {
-                my $actions = $_->{'actions'};
-                ( $_->{'flags'}, @$actions )
-            }
-        );
-    $dat .= $dat1;
-
-    my $entryTable = length($dat);
-    my $offset = ($entryTable + 8 * @$entries);
-    my @insListOffsets;
-    my $insertLists = $self->{'insertLists'};
-    foreach (@$insertLists) {
-        push @insListOffsets, $offset;
-        $offset += 2 * scalar @$_;
-    }
-    foreach (@$entries) {
-        my ($nextState, $flags, @lists) = split /,/;
-        $flags &= ~0x03ff;
-        $flags |= (scalar @{$insertLists->[$lists[0]]}) << 5 if $lists[0] ne '';
-        $flags |= (scalar @{$insertLists->[$lists[1]]}) if $lists[1] ne '';
-        $dat .= pack("nnnn", $nextState, $flags,
-                    map { $_ eq '' ? 0 : $insListOffsets[$_] } @lists);
-    }
-    
-    foreach (@$insertLists) {
-        $dat .= pack("n*", @$_);
-    }
-
-    $dat1 = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable);
-    substr($dat, 0, length($dat1)) = $dat1;
-
-    return $dat;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $self->print_classes($fh);
-    
-    $fh->print("\n");
-    my $states = $self->{'states'};
-    foreach (0 .. $#$states) {
-        $fh->printf("\t\tState %d:", $_);
-        my $state = $states->[$_];
-        foreach (@$state) {
-            my $flags;
-            $flags .= "!" if ($_->{'flags'} & 0x4000);
-            $flags .= "*" if ($_->{'flags'} & 0x8000);
-            my $actions = $_->{'actions'};
-            $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
-        }
-        $fh->print("\n");
-    }
-
-    $fh->print("\n");
-    my $insertLists = $self->{'insertLists'};
-    foreach (0 .. $#$insertLists) {
-        my $insertList = $insertLists->[$_];
-        $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList));
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Insertion;
+
+=head1 NAME
+
+Font::TTF::Mort::Insertion
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Mort::Subtable);
+
+sub new
+{
+    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
+    my ($self) = {
+                    'direction'            => $direction,
+                    'orientation'        => $orientation,
+                    'subFeatureFlags'    => $subFeatureFlags
+                };
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+    
+    my $subtableStart = $fh->tell();
+
+    my $stateTableStart = $fh->tell();
+    my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
+    
+    my %insertListHash;
+    my $insertLists;
+    foreach (@$entries) {
+        my $flags = $_->{'flags'};
+        my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f));
+        my $actions = $_->{'actions'};
+        foreach (0 .. 1) {
+            if ($insertCount[$_] > 0) {
+                $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET);
+                $fh->read($dat, $insertCount[$_] * 2);
+                if (not defined $insertListHash{$dat}) {
+                    push @$insertLists, [unpack("n*", $dat)];
+                    $insertListHash{$dat} = $#$insertLists;
+                }
+                $actions->[$_] = $insertListHash{$dat};
+            }
+            else {
+                $actions->[$_] = undef;
+            }
+        }
+    }
+
+    $self->{'classes'} = $classes;
+    $self->{'states'} = $states;
+    $self->{'insertLists'} = $insertLists;
+            
+    $self;
+}
+
+=head2 $t->pack_sub()
+
+=cut
+
+sub pack_sub
+{
+    my ($self) = @_;
+    
+    my ($dat) = pack("nnnn", (0) x 4);
+    
+    my $classTable = length($dat);
+    my $classes = $self->{'classes'};
+    $dat .= AAT_pack_classes($classes);
+    
+    my $stateArray = length($dat);
+    my $states = $self->{'states'};
+    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, 
+            sub {
+                my $actions = $_->{'actions'};
+                ( $_->{'flags'}, @$actions )
+            }
+        );
+    $dat .= $dat1;
+
+    my $entryTable = length($dat);
+    my $offset = ($entryTable + 8 * @$entries);
+    my @insListOffsets;
+    my $insertLists = $self->{'insertLists'};
+    foreach (@$insertLists) {
+        push @insListOffsets, $offset;
+        $offset += 2 * scalar @$_;
+    }
+    foreach (@$entries) {
+        my ($nextState, $flags, @lists) = split /,/;
+        $flags &= ~0x03ff;
+        $flags |= (scalar @{$insertLists->[$lists[0]]}) << 5 if $lists[0] ne '';
+        $flags |= (scalar @{$insertLists->[$lists[1]]}) if $lists[1] ne '';
+        $dat .= pack("nnnn", $nextState, $flags,
+                    map { $_ eq '' ? 0 : $insListOffsets[$_] } @lists);
+    }
+    
+    foreach (@$insertLists) {
+        $dat .= pack("n*", @$_);
+    }
+
+    $dat1 = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable);
+    substr($dat, 0, length($dat1)) = $dat1;
+
+    return $dat;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $self->print_classes($fh);
+    
+    $fh->print("\n");
+    my $states = $self->{'states'};
+    foreach (0 .. $#$states) {
+        $fh->printf("\t\tState %d:", $_);
+        my $state = $states->[$_];
+        foreach (@$state) {
+            my $flags;
+            $flags .= "!" if ($_->{'flags'} & 0x4000);
+            $flags .= "*" if ($_->{'flags'} & 0x8000);
+            my $actions = $_->{'actions'};
+            $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
+        }
+        $fh->print("\n");
+    }
+
+    $fh->print("\n");
+    my $insertLists = $self->{'insertLists'};
+    foreach (0 .. $#$insertLists) {
+        my $insertList = $insertLists->[$_];
+        $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList));
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Ligature.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Ligature.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Ligature.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,245 +1,245 @@
-package Font::TTF::Mort::Ligature;
-
-=head1 NAME
-
-Font::TTF::Mort::Ligature
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Mort::Subtable);
-
-sub new
-{
-    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
-    my ($self) = {
-                    'direction'            => $direction,
-                    'orientation'        => $orientation,
-                    'subFeatureFlags'    => $subFeatureFlags
-                };
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-
-    my $stateTableStart = $fh->tell();
-    my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
-    
-    $fh->seek($stateTableStart, IO::File::SEEK_SET);
-    $fh->read($dat, 14);
-    my ($stateSize, $classTable, $stateArray, $entryTable,
-        $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat);
-    my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $self->{'length'} - 8];
-    
-    my %actions;
-    my $actionLists;
-    foreach (@$entries) {
-        my $offset = $_->{'flags'} & 0x3fff;
-        $_->{'flags'} &= ~0x3fff;
-        if ($offset != 0) {
-            if (not defined $actions{$offset}) {
-                $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET);
-                my $actionList;
-                while (1) {
-                    $fh->read($dat, 4);
-                    my $action = unpack("N", $dat);
-                    my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff));
-                    $component -= 0x40000000 if $component > 0x1fffffff;
-                    $component -= $componentTable / 2;
-                    push @$actionList, { 'store' => $store, 'component' => $component };
-                    last if $last;
-                }
-                push @$actionLists, $actionList;
-                $actions{$offset} = $#$actionLists;
-            }
-            $_->{'actions'} = $actions{$offset};
-        }
-    }
-    
-    $self->{'componentTable'} = $componentTable;
-    my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))];
-    foreach (@$components) {
-        $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable;
-    }
-    $self->{'components'} = $components;
-    
-    $self->{'ligatureTable'} = $ligatureTable;
-    $self->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))];
-    
-    $self->{'classes'} = $classes;
-    $self->{'states'} = $states;
-    $self->{'actionLists'} = $actionLists;
-        
-    $self;
-}
-
-=head2 $t->pack_sub($fh)
-
-=cut
-
-sub pack_sub
-{
-    my ($self) = @_;
-    my ($dat);
-    
-    $dat .= pack("nnnnnnn", (0) x 7);    # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures
-
-    my $classTable = length($dat);
-    my $classes = $self->{'classes'};
-    $dat .= AAT_pack_classes($classes);
-    
-    my $stateArray = length($dat);
-    my $states = $self->{'states'};
-    
-    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states,
-            sub {
-                ( $_->{'flags'} & 0xc000, $_->{'actions'} )
-            }
-        );
-    $dat .= $dat1;
-    
-    my $actionLists = $self->{'actionLists'};
-    my %actionListOffset;
-    my $actionListDataLength = 0;
-    my @actionListEntries;
-    foreach (0 .. $#$entries) {
-        my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]);
-        if ($offset eq "") {
-            $offset = undef;
-        }
-        else {
-            if (defined $actionListOffset{$offset}) {
-                $offset = $actionListOffset{$offset};
-            }
-            else {
-                $actionListOffset{$offset} = $actionListDataLength;
-                my $list = $actionLists->[$offset];
-                $actionListDataLength += 4 * @$list;
-                push @actionListEntries, $list;
-                $offset = $actionListOffset{$offset};
-            }
-        }
-        $entries->[$_] = [ $nextState, $flags, $offset ];
-    }
-    my $entryTable = length($dat);
-    my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3;
-    foreach (@$entries) {
-        $_->[2] += $ligActionLists if defined $_->[2];
-        $dat .= pack("nn", $_->[0], $_->[1] + $_->[2]);
-    }
-    $dat .= pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4));
-    
-    die "internal error" unless length($dat) == $ligActionLists;
-    
-    my $componentTable = length($dat) + $actionListDataLength;
-    my $actionList;
-    foreach $actionList (@actionListEntries) {
-        foreach (0 .. $#$actionList) {
-            my $action = $actionList->[$_];
-            my $val = $action->{'component'} + $componentTable / 2;
-            $val += 0x40000000 if $val < 0;
-            $val &= 0x3fffffff;
-            $val |= 0x40000000 if $action->{'store'};
-            $val |= 0x80000000 if $_ == $#$actionList;
-            $dat .= pack("N", $val);
-        }
-    }
-
-    die "internal error" unless length($dat) == $componentTable;
-
-    my $components = $self->{'components'};
-    my $ligatureTable = $componentTable + @$components * 2;
-    $dat .= pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components);
-    
-    my $ligatures = $self->{'ligatures'};
-    $dat .= pack("n*", @$ligatures);
-    
-    $dat1 = pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable);
-    substr($dat, 0, length($dat1)) = $dat1;
-
-    return $dat;
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $self->print_classes($fh);
-    
-    $fh->print("\n");
-    my $states = $self->{'states'};
-    foreach (0 .. $#$states) {
-        $fh->printf("\t\tState %d:", $_);
-        my $state = $states->[$_];
-        foreach (@$state) {
-            my $flags;
-            $flags .= "!" if ($_->{'flags'} & 0x4000);
-            $flags .= "*" if ($_->{'flags'} & 0x8000);
-            $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "=");
-        }
-        $fh->print("\n");
-    }
-
-    $fh->print("\n");
-    my $actionLists = $self->{'actionLists'};
-    foreach (0 .. $#$actionLists) {
-        $fh->printf("\t\tList %d:\t", $_);
-        my $actionList = $actionLists->[$_];
-        $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList));
-    }
-
-    my $ligatureTable = $self->{'ligatureTable'};
-
-    $fh->print("\n");
-    my $components = $self->{'components'};
-    foreach (0 .. $#$components) {
-        $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]);
-    }
-    
-    $fh->print("\n");
-    my $ligatures = $self->{'ligatures'};
-    foreach (0 .. $#$ligatures) {
-        $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]);
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Ligature;
+
+=head1 NAME
+
+Font::TTF::Mort::Ligature
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Mort::Subtable);
+
+sub new
+{
+    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
+    my ($self) = {
+                    'direction'            => $direction,
+                    'orientation'        => $orientation,
+                    'subFeatureFlags'    => $subFeatureFlags
+                };
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+
+    my $stateTableStart = $fh->tell();
+    my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
+    
+    $fh->seek($stateTableStart, IO::File::SEEK_SET);
+    $fh->read($dat, 14);
+    my ($stateSize, $classTable, $stateArray, $entryTable,
+        $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat);
+    my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $self->{'length'} - 8];
+    
+    my %actions;
+    my $actionLists;
+    foreach (@$entries) {
+        my $offset = $_->{'flags'} & 0x3fff;
+        $_->{'flags'} &= ~0x3fff;
+        if ($offset != 0) {
+            if (not defined $actions{$offset}) {
+                $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET);
+                my $actionList;
+                while (1) {
+                    $fh->read($dat, 4);
+                    my $action = unpack("N", $dat);
+                    my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff));
+                    $component -= 0x40000000 if $component > 0x1fffffff;
+                    $component -= $componentTable / 2;
+                    push @$actionList, { 'store' => $store, 'component' => $component };
+                    last if $last;
+                }
+                push @$actionLists, $actionList;
+                $actions{$offset} = $#$actionLists;
+            }
+            $_->{'actions'} = $actions{$offset};
+        }
+    }
+    
+    $self->{'componentTable'} = $componentTable;
+    my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))];
+    foreach (@$components) {
+        $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable;
+    }
+    $self->{'components'} = $components;
+    
+    $self->{'ligatureTable'} = $ligatureTable;
+    $self->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))];
+    
+    $self->{'classes'} = $classes;
+    $self->{'states'} = $states;
+    $self->{'actionLists'} = $actionLists;
+        
+    $self;
+}
+
+=head2 $t->pack_sub($fh)
+
+=cut
+
+sub pack_sub
+{
+    my ($self) = @_;
+    my ($dat);
+    
+    $dat .= pack("nnnnnnn", (0) x 7);    # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures
+
+    my $classTable = length($dat);
+    my $classes = $self->{'classes'};
+    $dat .= AAT_pack_classes($classes);
+    
+    my $stateArray = length($dat);
+    my $states = $self->{'states'};
+    
+    my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states,
+            sub {
+                ( $_->{'flags'} & 0xc000, $_->{'actions'} )
+            }
+        );
+    $dat .= $dat1;
+    
+    my $actionLists = $self->{'actionLists'};
+    my %actionListOffset;
+    my $actionListDataLength = 0;
+    my @actionListEntries;
+    foreach (0 .. $#$entries) {
+        my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]);
+        if ($offset eq "") {
+            $offset = undef;
+        }
+        else {
+            if (defined $actionListOffset{$offset}) {
+                $offset = $actionListOffset{$offset};
+            }
+            else {
+                $actionListOffset{$offset} = $actionListDataLength;
+                my $list = $actionLists->[$offset];
+                $actionListDataLength += 4 * @$list;
+                push @actionListEntries, $list;
+                $offset = $actionListOffset{$offset};
+            }
+        }
+        $entries->[$_] = [ $nextState, $flags, $offset ];
+    }
+    my $entryTable = length($dat);
+    my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3;
+    foreach (@$entries) {
+        $_->[2] += $ligActionLists if defined $_->[2];
+        $dat .= pack("nn", $_->[0], $_->[1] + $_->[2]);
+    }
+    $dat .= pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4));
+    
+    die "internal error" unless length($dat) == $ligActionLists;
+    
+    my $componentTable = length($dat) + $actionListDataLength;
+    my $actionList;
+    foreach $actionList (@actionListEntries) {
+        foreach (0 .. $#$actionList) {
+            my $action = $actionList->[$_];
+            my $val = $action->{'component'} + $componentTable / 2;
+            $val += 0x40000000 if $val < 0;
+            $val &= 0x3fffffff;
+            $val |= 0x40000000 if $action->{'store'};
+            $val |= 0x80000000 if $_ == $#$actionList;
+            $dat .= pack("N", $val);
+        }
+    }
+
+    die "internal error" unless length($dat) == $componentTable;
+
+    my $components = $self->{'components'};
+    my $ligatureTable = $componentTable + @$components * 2;
+    $dat .= pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components);
+    
+    my $ligatures = $self->{'ligatures'};
+    $dat .= pack("n*", @$ligatures);
+    
+    $dat1 = pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable);
+    substr($dat, 0, length($dat1)) = $dat1;
+
+    return $dat;
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $self->print_classes($fh);
+    
+    $fh->print("\n");
+    my $states = $self->{'states'};
+    foreach (0 .. $#$states) {
+        $fh->printf("\t\tState %d:", $_);
+        my $state = $states->[$_];
+        foreach (@$state) {
+            my $flags;
+            $flags .= "!" if ($_->{'flags'} & 0x4000);
+            $flags .= "*" if ($_->{'flags'} & 0x8000);
+            $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "=");
+        }
+        $fh->print("\n");
+    }
+
+    $fh->print("\n");
+    my $actionLists = $self->{'actionLists'};
+    foreach (0 .. $#$actionLists) {
+        $fh->printf("\t\tList %d:\t", $_);
+        my $actionList = $actionLists->[$_];
+        $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList));
+    }
+
+    my $ligatureTable = $self->{'ligatureTable'};
+
+    $fh->print("\n");
+    my $components = $self->{'components'};
+    foreach (0 .. $#$components) {
+        $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]);
+    }
+    
+    $fh->print("\n");
+    my $ligatures = $self->{'ligatures'};
+    foreach (0 .. $#$ligatures) {
+        $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]);
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Noncontextual.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Noncontextual.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Noncontextual.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,95 +1,95 @@
-package Font::TTF::Mort::Noncontextual;
-
-=head1 NAME
-
-Font::TTF::Mort::Noncontextual
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Mort::Subtable);
-
-sub new
-{
-    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
-    my ($self) = {
-                    'direction'            => $direction,
-                    'orientation'        => $orientation,
-                    'subFeatureFlags'    => $subFeatureFlags
-                };
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    my ($dat);
-    
-    my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{'length'} - 8, undef);
-    $self->{'format'} = $format;
-    $self->{'lookup'} = $lookup;
-
-    $self;
-}
-
-=head2 $t->pack_sub($fh)
-
-=cut
-
-sub pack_sub
-{
-    my ($self) = @_;
-    
-    return AAT_pack_lookup($self->{'format'}, $self->{'lookup'}, 2, undef);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    my $lookup = $self->{'lookup'};
-    $fh->printf("\t\tLookup format %d\n", $self->{'format'});
-    if (defined $lookup) {
-        foreach (sort { $a <=> $b } keys %$lookup) {
-            $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]);
-        }
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Noncontextual;
+
+=head1 NAME
+
+Font::TTF::Mort::Noncontextual
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Mort::Subtable);
+
+sub new
+{
+    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
+    my ($self) = {
+                    'direction'            => $direction,
+                    'orientation'        => $orientation,
+                    'subFeatureFlags'    => $subFeatureFlags
+                };
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    my ($dat);
+    
+    my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{'length'} - 8, undef);
+    $self->{'format'} = $format;
+    $self->{'lookup'} = $lookup;
+
+    $self;
+}
+
+=head2 $t->pack_sub($fh)
+
+=cut
+
+sub pack_sub
+{
+    my ($self) = @_;
+    
+    return AAT_pack_lookup($self->{'format'}, $self->{'lookup'}, 2, undef);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    my $lookup = $self->{'lookup'};
+    $fh->printf("\t\tLookup format %d\n", $self->{'format'});
+    if (defined $lookup) {
+        foreach (sort { $a <=> $b } keys %$lookup) {
+            $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]);
+        }
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Rearrangement.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Rearrangement.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Rearrangement.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,107 +1,107 @@
-package Font::TTF::Mort::Rearrangement;
-
-=head1 NAME
-
-Font::TTF::Mort::Rearrangement
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Mort::Subtable);
-
-sub new
-{
-    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
-    my ($self) = {
-                    'direction'            => $direction,
-                    'orientation'        => $orientation,
-                    'subFeatureFlags'    => $subFeatureFlags
-                };
-
-    $class = ref($class) || $class;
-    bless $self, $class;
-}
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self, $fh) = @_;
-    
-    my ($classes, $states) = AAT_read_state_table($fh, 0);
-    $self->{'classes'} = $classes;
-    $self->{'states'} = $states;
-            
-    $self;
-}
-
-=head2 $t->pack_sub()
-
-=cut
-
-sub pack_sub
-{
-    my ($self) = @_;
-    
-    return AAT_pack_state_table($self->{'classes'}, $self->{'states'}, 0);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my $post = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $self->print_classes($fh);
-
-    $fh->print("\n");
-    my $states = $self->{'states'};
-    my @verbs = (    "0", "Ax->xA", "xD->Dx", "AxD->DxA",
-                    "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx",
-                    "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA",
-                    "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA");
-    foreach (0 .. $#$states) {
-        $fh->printf("\t\tState %d:", $_);
-        my $state = $states->[$_];
-        foreach (@$state) {
-            my $flags;
-            $flags .= "!" if ($_->{'flags'} & 0x4000);
-            $flags .= "<" if ($_->{'flags'} & 0x8000);
-            $flags .= ">" if ($_->{'flags'} & 0x2000);
-            $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]);
-        }
-        $fh->print("\n");
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Rearrangement;
+
+=head1 NAME
+
+Font::TTF::Mort::Rearrangement
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Mort::Subtable);
+
+sub new
+{
+    my ($class, $direction, $orientation, $subFeatureFlags) = @_;
+    my ($self) = {
+                    'direction'            => $direction,
+                    'orientation'        => $orientation,
+                    'subFeatureFlags'    => $subFeatureFlags
+                };
+
+    $class = ref($class) || $class;
+    bless $self, $class;
+}
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self, $fh) = @_;
+    
+    my ($classes, $states) = AAT_read_state_table($fh, 0);
+    $self->{'classes'} = $classes;
+    $self->{'states'} = $states;
+            
+    $self;
+}
+
+=head2 $t->pack_sub()
+
+=cut
+
+sub pack_sub
+{
+    my ($self) = @_;
+    
+    return AAT_pack_state_table($self->{'classes'}, $self->{'states'}, 0);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my $post = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $self->print_classes($fh);
+
+    $fh->print("\n");
+    my $states = $self->{'states'};
+    my @verbs = (    "0", "Ax->xA", "xD->Dx", "AxD->DxA",
+                    "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx",
+                    "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA",
+                    "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA");
+    foreach (0 .. $#$states) {
+        $fh->printf("\t\tState %d:", $_);
+        my $state = $states->[$_];
+        foreach (@$state) {
+            my $flags;
+            $flags .= "!" if ($_->{'flags'} & 0x4000);
+            $flags .= "<" if ($_->{'flags'} & 0x8000);
+            $flags .= ">" if ($_->{'flags'} & 0x2000);
+            $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]);
+        }
+        $fh->print("\n");
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Subtable.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Subtable.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort/Subtable.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,199 +1,199 @@
-package Font::TTF::Mort::Subtable;
-
-=head1 NAME
-
-Font::TTF::Mort::Subtable
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
-require Font::TTF::Mort::Rearrangement;
-require Font::TTF::Mort::Contextual;
-require Font::TTF::Mort::Ligature;
-require Font::TTF::Mort::Noncontextual;
-require Font::TTF::Mort::Insertion;
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = {};
-
-    $class = ref($class) || $class;
-
-    bless $self, $class;
-}
-
-sub create
-{
-    my ($class, $type, $coverage, $subFeatureFlags, $length) = @_;
-
-    $class = ref($class) || $class;
-
-    my $subclass;
-    if ($type == 0) {
-        $subclass = 'Font::TTF::Mort::Rearrangement';
-    }
-    elsif ($type == 1) {
-        $subclass = 'Font::TTF::Mort::Contextual';
-    }
-    elsif ($type == 2) {
-        $subclass = 'Font::TTF::Mort::Ligature';
-    }
-    elsif ($type == 4) {
-        $subclass = 'Font::TTF::Mort::Noncontextual';
-    }
-    elsif ($type == 5) {
-        $subclass = 'Font::TTF::Mort::Insertion';
-    }
-    
-    my ($self) = $subclass->new(
-            (($coverage & 0x4000) ? 'RL' : 'LR'),
-            (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'),
-            $subFeatureFlags
-        );
-
-    $self->{'type'} = $type;
-    $self->{'length'} = $length;
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    my ($subtableStart) = $fh->tell();
-    my ($type) = $self->{'type'};
-    my ($coverage) = $type;
-    $coverage += 0x4000 if $self->{'direction'} eq 'RL';
-    $coverage += 0x2000 if $self->{'orientation'} eq 'VH';
-    $coverage += 0x8000 if $self->{'orientation'} eq 'V';
-    
-    $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'}));    # placeholder for length
-    
-    my ($dat) = $self->pack_sub();
-    $fh->print($dat);
-    
-    my ($length) = $fh->tell() - $subtableStart;
-    my ($padBytes) = (4 - ($length & 3)) & 3;
-    $fh->print(pack("C*", (0) x $padBytes));
-    $length += $padBytes;
-    $fh->seek($subtableStart, IO::File::SEEK_SET);
-    $fh->print(pack("n", $length));
-    $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub post
-{
-    my ($self) = @_;
-    
-    my ($post) = $self->{' PARENT'}{' PARENT'}{' PARENT'}{'post'};
-    if (defined $post) {
-        $post->read;
-    }
-    else {
-        $post = {};
-    }
-    
-    return $post;
-}
-
-sub feat
-{
-    my ($self) = @_;
-    
-    return $self->{' PARENT'}->feat();
-}
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    my ($feat) = $self->feat();
-    my ($post) = $self->post();
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    my ($type) = $self->{'type'};
-    my ($subFeatureFlags) = $self->{'subFeatureFlags'};
-    my ($defaultFlags) = $self->{' PARENT'}{'defaultFlags'};
-    my ($featureEntries) = $self->{' PARENT'}{'featureEntries'};
-    $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
-                subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
-                "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
-                join(", ",
-                    map {
-                        join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
-                    } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
-                ) );
-}
-
-sub subtable_type_
-{
-    my ($val) = @_;
-    my ($res);
-    
-    my (@types) =    (
-                        'Rearrangement',
-                        'Contextual',
-                        'Ligature',
-                        undef,
-                        'Non-contextual',
-                        'Insertion',
-                    );
-    $res = $types[$val] or ('Undefined (' . $val . ')');
-    
-    $res;
-}
-
-=head2 $t->print_classes($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print_classes
-{
-    my ($self, $fh) = @_;
-    
-    my ($post) = $self->post();
-    
-    my ($classes) = $self->{'classes'};
-    foreach (0 .. $#$classes) {
-        my $class = $classes->[$_];
-        if (defined $class) {
-            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
-        }
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort::Subtable;
+
+=head1 NAME
+
+Font::TTF::Mort::Subtable
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+require Font::TTF::Mort::Rearrangement;
+require Font::TTF::Mort::Contextual;
+require Font::TTF::Mort::Ligature;
+require Font::TTF::Mort::Noncontextual;
+require Font::TTF::Mort::Insertion;
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = {};
+
+    $class = ref($class) || $class;
+
+    bless $self, $class;
+}
+
+sub create
+{
+    my ($class, $type, $coverage, $subFeatureFlags, $length) = @_;
+
+    $class = ref($class) || $class;
+
+    my $subclass;
+    if ($type == 0) {
+        $subclass = 'Font::TTF::Mort::Rearrangement';
+    }
+    elsif ($type == 1) {
+        $subclass = 'Font::TTF::Mort::Contextual';
+    }
+    elsif ($type == 2) {
+        $subclass = 'Font::TTF::Mort::Ligature';
+    }
+    elsif ($type == 4) {
+        $subclass = 'Font::TTF::Mort::Noncontextual';
+    }
+    elsif ($type == 5) {
+        $subclass = 'Font::TTF::Mort::Insertion';
+    }
+    
+    my ($self) = $subclass->new(
+            (($coverage & 0x4000) ? 'RL' : 'LR'),
+            (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'),
+            $subFeatureFlags
+        );
+
+    $self->{'type'} = $type;
+    $self->{'length'} = $length;
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    my ($subtableStart) = $fh->tell();
+    my ($type) = $self->{'type'};
+    my ($coverage) = $type;
+    $coverage += 0x4000 if $self->{'direction'} eq 'RL';
+    $coverage += 0x2000 if $self->{'orientation'} eq 'VH';
+    $coverage += 0x8000 if $self->{'orientation'} eq 'V';
+    
+    $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'}));    # placeholder for length
+    
+    my ($dat) = $self->pack_sub();
+    $fh->print($dat);
+    
+    my ($length) = $fh->tell() - $subtableStart;
+    my ($padBytes) = (4 - ($length & 3)) & 3;
+    $fh->print(pack("C*", (0) x $padBytes));
+    $length += $padBytes;
+    $fh->seek($subtableStart, IO::File::SEEK_SET);
+    $fh->print(pack("n", $length));
+    $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub post
+{
+    my ($self) = @_;
+    
+    my ($post) = $self->{' PARENT'}{' PARENT'}{' PARENT'}{'post'};
+    if (defined $post) {
+        $post->read;
+    }
+    else {
+        $post = {};
+    }
+    
+    return $post;
+}
+
+sub feat
+{
+    my ($self) = @_;
+    
+    return $self->{' PARENT'}->feat();
+}
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    my ($feat) = $self->feat();
+    my ($post) = $self->post();
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    my ($type) = $self->{'type'};
+    my ($subFeatureFlags) = $self->{'subFeatureFlags'};
+    my ($defaultFlags) = $self->{' PARENT'}{'defaultFlags'};
+    my ($featureEntries) = $self->{' PARENT'}{'featureEntries'};
+    $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
+                subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
+                "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
+                join(", ",
+                    map {
+                        join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
+                    } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
+                ) );
+}
+
+sub subtable_type_
+{
+    my ($val) = @_;
+    my ($res);
+    
+    my (@types) =    (
+                        'Rearrangement',
+                        'Contextual',
+                        'Ligature',
+                        undef,
+                        'Non-contextual',
+                        'Insertion',
+                    );
+    $res = $types[$val] or ('Undefined (' . $val . ')');
+    
+    $res;
+}
+
+=head2 $t->print_classes($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print_classes
+{
+    my ($self, $fh) = @_;
+    
+    my ($post) = $self->post();
+    
+    my ($classes) = $self->{'classes'};
+    foreach (0 .. $#$classes) {
+        my $class = $classes->[$_];
+        if (defined $class) {
+            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
+        }
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Mort.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,108 +1,108 @@
-package Font::TTF::Mort;
-
-=head1 NAME
-
-Font::TTF::Mort - Glyph Metamorphosis table in a font
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Mort::Chain;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $fh, $numChains);
-    
-    $self->SUPER::read or return $self;
-
-    $fh = $self->{' INFILE'};
-
-    $fh->read($dat, 8);
-    ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat);
-    
-    my $chains = [];
-    foreach (1 .. $numChains) {
-        my $chain = new Font::TTF::Mort::Chain->new;
-        $chain->read($fh);
-        $chain->{' PARENT'} = $self;
-        push @$chains, $chain;
-    }
-
-    $self->{'chains'} = $chains;
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    my $chains = $self->{'chains'};
-    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains));
-
-    foreach (@$chains) {
-        $_->out($fh);
-    }
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    $self->read unless $self->{' read'};
-    my $feat = $self->{' PARENT'}->{'feat'};
-    $feat->read;
-    my $post = $self->{' PARENT'}->{'post'};
-    $post->read;
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $fh->printf("version %f\n", $self->{'version'});
-    
-    my $chains = $self->{'chains'};
-    foreach (@$chains) {
-        $_->print($fh);
-    }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Mort;
+
+=head1 NAME
+
+Font::TTF::Mort - Glyph Metamorphosis table in a font
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Mort::Chain;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $fh, $numChains);
+    
+    $self->SUPER::read or return $self;
+
+    $fh = $self->{' INFILE'};
+
+    $fh->read($dat, 8);
+    ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat);
+    
+    my $chains = [];
+    foreach (1 .. $numChains) {
+        my $chain = new Font::TTF::Mort::Chain->new;
+        $chain->read($fh);
+        $chain->{' PARENT'} = $self;
+        push @$chains, $chain;
+    }
+
+    $self->{'chains'} = $chains;
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    my $chains = $self->{'chains'};
+    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains));
+
+    foreach (@$chains) {
+        $_->out($fh);
+    }
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    $self->read unless $self->{' read'};
+    my $feat = $self->{' PARENT'}->{'feat'};
+    $feat->read;
+    my $post = $self->{' PARENT'}->{'post'};
+    $post->read;
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $fh->printf("version %f\n", $self->{'version'});
+    
+    my $chains = $self->{'chains'};
+    foreach (@$chains) {
+        $_->print($fh);
+    }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Name.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Name.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Name.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,472 +1,472 @@
-package Font::TTF::Name;
-
-=head1 NAME
-
-Font::TTF::Name - String table for a TTF font
-
-=head1 DESCRIPTION
-
-Strings are held by number, platform, encoding and language. Strings are
-accessed as:
-
-    $f->{'name'}{'strings'}[$number][$platform_id][$encoding_id]{$language_id}
-
-Notice that the language is held in an associative array due to its sparse
-nature on some platforms such as Microsoft ($pid = 3). Notice also that the
-array order is different from the stored array order (platform, encoding,
-language, number) to allow for easy manipulation of strings by number (which is
-what I guess most people will want to do).
-
-By default, C<$Font::TTF::Name::utf8> is set to 1, and strings will be stored as UTF8 wherever
-possible. The method C<is_utf8> can be used to find out if a string in a particular
-platform and encoding will be returned as UTF8. Unicode strings are always
-converted if utf8 is requested. Otherwise, strings are stored according to platform:
-
-    ***WARNING NON-UTF8 is deprecated and utf8 strings has become the default***
-
-You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour.
-
-=over 4
-
-=item Apple Unicode (platform id = 0)
-
-Data is stored as network ordered UCS2. There is no encoding id for this platform
-but there are language ids as per Mac language ids.
-
-=item Mac (platform id = 1)
-
-Data is stored as 8-bit binary data, leaving the interpretation to the user
-according to encoding id.
-
-=item Unicode (platform id = 2)
-
-Currently stored as 16-bit network ordered UCS2. Upon release of Perl 5.005 this
-will change to utf8 assuming current UCS2 semantics for all encoding ids.
-
-=item Windows (platform id = 3)
-
-As per Unicode, the data is currently stored as 16-bit network ordered UCS2. Upon
-release of Perl 5.005 this will change to utf8 assuming current UCS2 semantics for
-all encoding ids.
-
-=back
-
-=head1 INSTANCE VARIABLES
-
-=over 4
-
-=item strings
-
-An array of arrays, etc.
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA $VERSION @apple_encs @apple_encodings $utf8 $cp_1252 @cp_1252);
-use Font::TTF::Table;
-use Font::TTF::Utils;
- at ISA = qw(Font::TTF::Table);
-
-$utf8 = 1;
-
-{
-    my ($count, $i);
-    eval {require Compress::Zlib;};
-    unless ($@)
-    {
-        for ($i = 0; $i <= $#apple_encs; $i++)
-        {
-            $apple_encodings[0][$i] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $apple_encs[$i])))]
-                if (defined $apple_encs[$i]);
-            $count = 0;
-            $apple_encodings[1][$i] = {map({$_ => $count++} @{$apple_encodings[0][$i]})};
-        }
-        $cp_1252[0] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $cp_1252)))];
-        $count = 0;
-        $cp_1252[1] = {map({$_ => $count++} @{$cp_1252[0]})};
-    }
-}
-    
-
-$VERSION = 1.1;             # MJPH  17-JUN-2000     Add utf8 support
-# $VERSION = 1.001;           # MJPH  10-AUG-1998     Put $number first in list
-
-=head2 $t->read
-
-Reads all the names into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($dat, $num, $stroff, $i, $pid, $eid, $lid, $nid, $len, $off, $here);
-
-    $self->SUPER::read or return $self;
-    $fh->read($dat, 6);
-    ($num, $stroff) = unpack("x2nn", $dat);
-    for ($i = 0; $i < $num; $i++)
-    {
-        $fh->read($dat, 12);
-        ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $dat);
-        $here = $fh->tell();
-        $fh->seek($self->{' OFFSET'} + $stroff + $off, 0);
-        $fh->read($dat, $len);
-        if ($utf8)
-        {
-            if ($pid == 1 && defined $apple_encodings[0][$eid])
-            { $dat = TTF_word_utf8(pack("n*", map({$apple_encodings[0][$eid][$_]} unpack("C*", $dat)))); }
-            elsif ($pid == 2 && $eid == 2 && defined @cp_1252)
-            { $dat = TTF_word_utf8(pack("n*", map({$cp_1252[0][$_]} unpack("C*", $dat)))); }
-            elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
-            { $dat = TTF_word_utf8($dat); }
-        }
-        $self->{'strings'}[$nid][$pid][$eid]{$lid} = $dat;
-        $fh->seek($here, 0);
-    }
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes out all the strings
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($pid, $eid, $lid, $nid, $todo, @todo);
-    my ($len, $offset, $loc, $stroff, $endloc, $str_trans);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $loc = $fh->tell();
-    $fh->print(pack("n3", 0, 0, 0));
-    foreach $nid (0 .. $#{$self->{'strings'}})
-    {
-        foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
-        {
-            foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
-            {
-                foreach $lid (sort keys %{$self->{'strings'}[$nid][$pid][$eid]})
-                {
-                    $str_trans = $self->{'strings'}[$nid][$pid][$eid]{$lid};
-                    if ($utf8)
-                    {
-                        if ($pid == 1 && defined $apple_encodings[1][$eid])
-                        { $str_trans = pack("C*",
-                                map({$apple_encodings[1][$eid]{$_} || "?"} unpack("n*",
-                                TTF_utf8_word($str_trans)))); }
-                        elsif ($pid == 2 && $eid == 2 && defined @cp_1252)
-                        { $str_trans = pack("C*",
-                                map({$cp_1252[1][$eid]{$_} || "?"} unpack("n*",
-                                TTF_utf8_word($str_trans)))); }
-                        elsif ($pid == 2 && $eid == 0)
-                        { $str_trans =~ s/[\xc0-\xff][\x80-\xbf]+/?/og; }
-                        elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
-                        { $str_trans = TTF_utf8_word($str_trans); }
-                    }
-                    push (@todo, [$pid, $eid, $lid, $nid, $str_trans]);
-                }
-            }
-        }
-    }
-
-    $offset = 0;
-    @todo = (sort {$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $a->[2]
-            || $a->[3] <=> $b->[3]} @todo);
-    foreach $todo (@todo)
-    {
-        $len = length($todo->[4]);
-        $fh->print(pack("n6", @{$todo}[0..3], $len, $offset));
-        $offset += $len;
-    }
-    
-    $stroff = $fh->tell() - $loc;
-    foreach $todo (@todo)
-    { $fh->print($todo->[4]); }
-
-    $endloc = $fh->tell();
-    $fh->seek($loc, 0);
-    $fh->print(pack("n3", 0, $#todo + 1, $stroff));
-    $fh->seek($endloc, 0);
-    $self;
-}
-
-
-=head2 $t->XML_element($context, $depth, $key, $value)
-
-Outputs the string element in nice XML (which is all the table really!)
-
-=cut
-
-sub XML_element
-{
-    my ($self) = shift;
-    my ($context, $depth, $key, $value) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($nid, $pid, $eid, $lid);
-
-    return $self->SUPER::XML_element(@_) unless ($key eq 'strings');
-
-    foreach $nid (0 .. $#{$self->{'strings'}})
-    {
-        next unless ref($self->{'strings'}[$nid]);
-#        $fh->print("$depth<strings id='$nid'>\n");
-        foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
-        {
-            foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
-            {
-                foreach $lid (sort {$a <=> $b} keys %{$self->{'strings'}[$nid][$pid][$eid]})
-                {
-                    $fh->printf("%s<string id='%s' platform='%s' encoding='%s' language='%s'>\n%s%s%s\n%s</string>\n",
-                            $depth, $nid, $pid, $eid, $lid, $depth,
-                            $context->{'indent'}, $self->{'strings'}[$nid][$pid][$eid]{$lid}, $depth);
-                }
-            }
-        }
-#        $fh->print("$depth</strings>\n");
-    }
-    $self;
-}
-
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Store strings in the right place
-
-=cut
-
-sub XML_end
-{
-    my ($self) = shift;
-    my ($context, $tag, %attrs) = @_;
-
-    if ($tag eq 'string')
-    {
-        $self->{'strings'}[$attrs{'id'}][$attrs{'platform'}][$attrs{'encoding'}]{$attrs{'language'}}
-            = $context->{'text'};
-        return $context;
-    }
-    else
-    { return $self->SUPER::XML_end(@_); }
-}
-
-=head2 is_utf8($pid, $eid)
-
-Returns whether a string of a given platform and encoding is going to be in UTF8
-
-=cut
-
-sub is_utf8
-{
-    my ($self, $pid, $eid) = @_;
-
-    return ($utf8 && ($pid == 0 || $pid == 3 || ($pid == 2 && ($eid != 2 || defined @cp_1252))
-            || ($pid == 1 && defined $apple_encodings[$eid])));
-}
-
-
-=head2 find_name($nid)
-
-Hunts down a name in all the standard places and returns the string and for an
-array context the pid, eid & lid as well
-
-=cut
-
-sub find_name
-{
-    my ($self, $nid) = @_;
-    my ($res, $pid, $eid, $lid, $look, $k);
-
-    my (@lookup) = ([3, 1, 1033], [3, 1, -1], [3, 0, 1033], [3, 0, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1],
-                    [0, 0, 0], [1, 0, 0]);
-    foreach $look (@lookup)
-    {
-        ($pid, $eid, $lid) = @$look;
-        if ($lid == -1)
-        {
-            foreach $k (keys %{$self->{'strings'}[$nid][$pid][$eid]})
-            {
-                if (($res = $self->{strings}[$nid][$pid][$eid]{$k}) ne '')
-                {
-                    $lid = $k;
-                    last;
-                }
-            }
-        } else
-        { $res = $self->{strings}[$nid][$pid][$eid]{$lid} }
-        if ($res ne '')
-        { return wantarray ? ($res, $pid, $eid, $lid) : $res; }
-    }
-    return '';
-}
-    
-
-BEGIN {
- at apple_encs = (
-<<'EOT',
-M>)RES==NCW$`@.'G_S5Q*L(!#?+K1VO4:.W6IJA-:\^BM?>L>1&NP(A0Q$BL
-M<*!62ZV8Z1)[K]BE$MR#O,=/7OW]7T&*6"NMI4K31EOMM)>N at XXZZ2Q#IBZZ
-MZJ:['GKJ)4NVWOKHJ]\_/\!`@PR68XBAALDUW`@CC3+:&&.-,UZ>?!-,-,ED
-M4TPUS70SS#3+;`7FF&N>0D7F6V"A119;8JEEEEMAI5566V.M==;;H-A&FVRV
-MQ5;;_OTONJ3<%;?<5^NQ1YYXYJGG7GKME3?>>N^=#S[ZY(O/OOKNFU]^JO<[
-M!$?LLMO>$#OAH4-*4F+'[(L+E*F,6SH:%\9%]C@>1W&CN&%2:9QNO]-))5ZH
-M<]9.!^/DQ/8X-V[@@#,AS0ZE+KB7R$ODA\:A26@>6H2FH9D?J17^)(I#3C at 8
-MLD)V?:(^"BE.AN30,F0XK\(Y5UUVW0TW77/'W;H_;JM6HRJ1&95%M0Y'E5%5
-.5.U4]""JB<K_`B>`?E$`
-EOT
-
-undef,
-undef,
-undef,
-<<'EOT',
-M>)RES[=/%```1O$WO8G_@$'J';W70Z2WHS>5WJN%8D6%D;BZ,3*P,;#C2D(8
-M,9&)08V)+4*(1((X2'(#[.:;7[[\*./_%D,L<<230"(!@B213`JII)%.!IED
-MD4T.N>213P&%%%%,B!)N4LJMR[Z<"BJIHIH::JFCG@;"--)$,RVTTD8['732
-M13>WN<-=>NBECWX&&&2(848898QQ)IADBFEFF.4>]WG`0^:89X%%'O&8)SSE
-M&<]9X at 4O><4R*Y?_.ZRSRQ[[''#(1S[PB<]NL\D7OO&5[_S at 9TR`(XXYX1=O
-M.>4W9_SAG`O^7OF=O>XW*N)WV!%''7/<"2>=<MH90D9'_-X(AHTUSG at 33#1@
-MT"2333'5--/-,-,LL\TQUSSS+;#0(HL-7?DMM\)*JZRVQEKKK+?!L(TVV6R+
-9K;;9;H<K+KGJ>S?<\K5O(G[7?/</+>Y>'```
-EOT
-
-<<'EOT',
-M>)RED$LSEW$`A9_-^00L,H-^(=>4Y%^2J'1Q*Y+[I2(BHA`B?!%J6EM1*28S
-M;9II[/PI*7*_%TUN\_*VZ%W:FN9LSYEGGD,\_Q?#$?SP)X"C!!)$,"&$$L8Q
-MPCG."2(X222GB,+%:<X0S5EB.$<LYXES]A>XR"42N,P5KG*-1))()H54KG.#
-M--*Y20:WR"2+;'+()8]\"BBDB-O<X2[%E'"/4LJX3SD5/*"2*AY230V/>$PM
-M==3SA`8::>(IS;3PC%;::'?X'^W#?&(0-Z-,,,,TL\PSQP)+K+#,*C]9XQ?K
-M_.8/FVRPQ0[;[+&+S=_]_J;KX/Y6I?&U.JQ.Z[GU0 at -VBNTR@;Q4G]ZI5V_U
-MQG at 83^-M?,PAXV6'VF'ZH&Z]4H_>J]]IO=:0W!K6B#[KBT;U56/ZIN\:UX1^
-?:%)3FM:,9C6G>2UH44M:UHI6'?<BYX,"6O\!%-%\5```
-EOT
-
-<<'EOT',
-M>)RES5=OSG$`0.$CYR.(A(3DUS]J4WOO59O6;&F+UMY[7R&(V'N^4ETZ=*"J
-M:M:H=>E*0D1B)7HC1KC0[R#G^LEA,/]7((Z(EK2B-?&TH2WM:$\'.M*)SG0A
-M@:YTHSL]Z$DO>M.'OO2C/P,8R*`&/X2A#&,X(QC)*$:3R!C&,H[Q3&`BDYC,
-M%))(9BK3F,X,9C*+%%*9S1S22">#N<QC/IEDL8"%+&(Q2UC*,I:S at I6L8C5K
-M6,LZUK.!C6QB,UO8RC:VLZ/A7TL5Y=11P6O>N(MWO.>#.\GG(Y_YQ!>^DAT7
-M\8WZ$%$3$OC.#W(IYC=_^!N"1SWF*<]ZP1AO*:'`;*^0%V502J6'*8LRHRQR
-M/.)Q3WC2TY[QG+D6FF^!19ZGR(M>BA*]3"'5(9Z8.>:YVSV-DD/CT"0T#RU"
-MT]",G^YUG_L]8+$E7O6%!WUIF>4^]9K7?6R%E59YQUM6>]L:[WK/5][WH;7>
-4M,X'/O&1-WSF<P]9^BOV#YW%>_\`
-EOT
-
-<<'EOT',
-M>)RERT=.%5``0-&+7K'&!B(@X/L/^/3>ZZ?SZ=*K@`KVWOL:U!68.#!&8G2@
-M$Q?F5/=@SOB0XO\$$D2**:&4)&644T$E55130RUUU--`(TTTTT(K;;3302==
-M=--#[[_?1S\###+$,".,DF:,<2:89(II9KC`+'/,L\`B2RRSPBIKK+/!13;9
-M8IM+7.8*.^QRE6M<YP8WN<5M[G"7>]SG`0]YQ&.>\)1G/.<%+WG%:][PEI0G
-M/>5IL\SVC#F>-=<\\SUG at 846>=Y at PFBQ)9::M,QR*ZRTRFIKK+4N!+[[CD]\
-M#I%?9O*-+XGH/N?BMON=CT7\B#MQUR5^^MY#ZH('7?:PJQYQS14/L!?S,S[$
-M=,SD*[]#DH\>==UC;K at 8LD)V*`B%(3?D\2<4>=Q-3[B5R#'#66>LM\%&FVRV
-GQ5;;;+?#3KOLML=>4_;9[X"##CGLB*.F'7/<"2>=<CKL_06V`DD#
-EOT
-
-undef,
-<<'EOT',
-M>)RED-DVUG$`1;=:U*Y%0C)5O^^/SSS/F>>9#"$JE7D>"D6\3S=>Q^MPU^JF
-M&^M<G[7//G1ROP1B1.130"%QBBBFA%+***>"2JJHIH9:ZJBG at 4:::*:%M[32
-M1CL==_TNNNFAES[Z&6"0(889890QQIE at DG=,,<T,L[QGCGD6^,`B2WSD$Y]9
-MY at M?^<8*JZRQS@:;;+'-#KOLL<\!AQQQS'=^<,(I9_SD%^=<\)M+KN[X-U%:
-M2`\9(2MDAWB(^,-U+/KKYYJ'_W_`!!_XT$23?.1C]8E/3?&9J2:;9KH9/O>%
-MF;XTRVQSS#7/5[[VC<&8D?D66&C<(HLML=0RRZVPTBJ7K;;&6NNLM\%&FVRV
-L):388:===MMCKP,..F2_(XXZYK#CMKGZS[YU-]QTRVUWW'7/?0]N`4(?0WT`
-EOT
-
-<<'EOT',
-M>)RED,5.0U$415=(D.X!$"ANMX^VN+M#D>+N[H4"Q5W^APF_PZ\PY.9-"`-&
-MY.3LG>-"#_\3 at P^'8OP$"%)"*6644T$E55130RUUU--`(TTTTT(K;;3302==
-M=-OZ7OH(T<\`@PP19I at 11AECG`DFF6*:&6:98YX%%EEBF15666.=#3;98IL=
-M=MECGP,.B7#$,5%...6,&.=<<,D5U]QPRQWW//#($\^\\,J;G?_II)ETXS79
-M)L<$C<,['S[GYSY=?FWK6E>Z^?L'BK,:KP0E*DD>R?6E*-7E='DM9BA36<I6
-MCG*5IWP5J%!%,O+)4;'\"BBH$I7:S')5J%)5JE:-M6JMUKM]FM1LL55M)EG=
-GZE&O^A1R(V$-NSRF<8L3ZO3L_]KN4!$=Z5A1G>A49XKI_!M<9D8J
-EOT
-
-<<'EOT',
-M>)RED,E3SW$8QU_77@<''+A]^Y5(2-F7+"%92\B^ES5ES]H,)L(8&21E*UNH
-M&"8T8ZS3I(FS_T"$_`L^-^/D8)YY/^]Y/\L\"Y/Y/XN()T8"B0P at B8$,(IG!
-MI#"$H0PCE>&DD<X(1C**T8QA+.,8SP0FDL&DT#^%J60RC>G,((N99#.+V<QA
-M+O.83PZY+""/A2QB,?DL82G+6,X*5K**U:QA+>M8SP8**&0CF]C,%K:RC2*V
-M4TP).]C)+G:SA[WLHY3]'.`@ASC,$<K"_,^QWE&?J&_4+^H?)44Q[M,<'_MS
-M7USAOS[@48]YW')/>-(*3WG:,R%ZSDK/!K[@1<][R2HO6^T5:ZSUJM>\[@UO
-M6F>]M[SM'>]ZSX90_\"'-MIDLX^">ASPQ*?!M_C,Y[ZP->KE*U_[QK>^\WW(
-CM/O!ML"=?K3#3[Z,*_AKOR]V^=5O=OO='_ZTQU^_`2-%:*``
-EOT
-
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-<<'EOT',
-M>)REC]=.E&$`1(\%&W at 4004%_7:!I?>.Z-+[TJL*=K"`BH`*J,_"+2'A!7PW
-MX;\2[LG<3#*9G!F2G$V!&'$***2(!,644$H9Y5102175U%!+'?4TT$@3S;30
-M2AN/:.<Q3Z)^!YUTT4T/O?31SP"###',""E&&6.<"2:98IH99IECG at 6>\HSG
-M+++$"U[RBM>\X2WO6&:%]WS@(Y]898W/?.$KZWQC at TVV^,X/?K+-#KO\XC=_
-M(OX!?T/"`0<=<MB1$Q?R0KXIDB%NK?TVV&B3S:?RG)`;]?<\YWDO>-$T+WG9
-M*U[UFNEF>%V]X4TSO666V=[VCG?-,==[WC?/?!_XT&#,N`466F3"8DLLM<QR
-M*ZRTRFIK(GJ=]?_Y+;;:]N\HI(>LD&W2#COMLML>>^V+=IX\2<7BCCGNA)-.
-0.>V,L\XY[P*'[!\#D^='L@``
-EOT
-
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-undef,
-);
-
-$cp_1252 = (
-<<'EOT',
-M>)P-SD-B'5```,#YJ6VE>DEM&[\VD]JVF?H./4'-U+93V[9M:SV;$141(Y74
-MTD at KG?0RR"B3S++(*IOL<L at IE]SRR"N?_`J(55`AA1515!`G7C'%E5!2*:65
-M458YY550426555%5-=754%,MM=515SWU-=!05".--=%4,\VUT%(KK;715COM
-M==!1)YTE2-1%5]UTUT-/O?361U_]]#?`0(,,-L10PPPWPDBCC#;&6..,-\%$
-MDTPVQ5333)=DAIEFF6V.N>:%9-$0&YD?BH22(82XF)10.3(@U(DDB$;F_/]%
-M0_Y0(!0*A4-\R!5RQ]R*BX\,#'4CB?]];B3)`@LMLM at 22RVSW`HKK;):LC76
-M6F>]#3;:9+,MMMIFNQUVVF6W/?;:9[\##CKDL"-2''7,<2><=,II9YQUSGD7
-M7'3)95=<=<UU-]QTRVUWW'7/?0\\],AC3SSUS',OO/3*:V^\]<Y['WSTR6=?
-1?/7-=S_\],MO?_S]!Y==>0@`
-EOT
-);
-}
-
-1;
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-Unicode type strings will be stored in utf8 for all known platforms,
-once Perl 5.6 has been released and I can find all the mapping tables, etc.
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Name;
+
+=head1 NAME
+
+Font::TTF::Name - String table for a TTF font
+
+=head1 DESCRIPTION
+
+Strings are held by number, platform, encoding and language. Strings are
+accessed as:
+
+    $f->{'name'}{'strings'}[$number][$platform_id][$encoding_id]{$language_id}
+
+Notice that the language is held in an associative array due to its sparse
+nature on some platforms such as Microsoft ($pid = 3). Notice also that the
+array order is different from the stored array order (platform, encoding,
+language, number) to allow for easy manipulation of strings by number (which is
+what I guess most people will want to do).
+
+By default, C<$Font::TTF::Name::utf8> is set to 1, and strings will be stored as UTF8 wherever
+possible. The method C<is_utf8> can be used to find out if a string in a particular
+platform and encoding will be returned as UTF8. Unicode strings are always
+converted if utf8 is requested. Otherwise, strings are stored according to platform:
+
+    ***WARNING NON-UTF8 is deprecated and utf8 strings has become the default***
+
+You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour.
+
+=over 4
+
+=item Apple Unicode (platform id = 0)
+
+Data is stored as network ordered UCS2. There is no encoding id for this platform
+but there are language ids as per Mac language ids.
+
+=item Mac (platform id = 1)
+
+Data is stored as 8-bit binary data, leaving the interpretation to the user
+according to encoding id.
+
+=item Unicode (platform id = 2)
+
+Currently stored as 16-bit network ordered UCS2. Upon release of Perl 5.005 this
+will change to utf8 assuming current UCS2 semantics for all encoding ids.
+
+=item Windows (platform id = 3)
+
+As per Unicode, the data is currently stored as 16-bit network ordered UCS2. Upon
+release of Perl 5.005 this will change to utf8 assuming current UCS2 semantics for
+all encoding ids.
+
+=back
+
+=head1 INSTANCE VARIABLES
+
+=over 4
+
+=item strings
+
+An array of arrays, etc.
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA $VERSION @apple_encs @apple_encodings $utf8 $cp_1252 @cp_1252);
+use Font::TTF::Table;
+use Font::TTF::Utils;
+ at ISA = qw(Font::TTF::Table);
+
+$utf8 = 1;
+
+{
+    my ($count, $i);
+    eval {require Compress::Zlib;};
+    unless ($@)
+    {
+        for ($i = 0; $i <= $#apple_encs; $i++)
+        {
+            $apple_encodings[0][$i] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $apple_encs[$i])))]
+                if (defined $apple_encs[$i]);
+            $count = 0;
+            $apple_encodings[1][$i] = {map({$_ => $count++} @{$apple_encodings[0][$i]})};
+        }
+        $cp_1252[0] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $cp_1252)))];
+        $count = 0;
+        $cp_1252[1] = {map({$_ => $count++} @{$cp_1252[0]})};
+    }
+}
+    
+
+$VERSION = 1.1;             # MJPH  17-JUN-2000     Add utf8 support
+# $VERSION = 1.001;           # MJPH  10-AUG-1998     Put $number first in list
+
+=head2 $t->read
+
+Reads all the names into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($dat, $num, $stroff, $i, $pid, $eid, $lid, $nid, $len, $off, $here);
+
+    $self->SUPER::read or return $self;
+    $fh->read($dat, 6);
+    ($num, $stroff) = unpack("x2nn", $dat);
+    for ($i = 0; $i < $num; $i++)
+    {
+        $fh->read($dat, 12);
+        ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $dat);
+        $here = $fh->tell();
+        $fh->seek($self->{' OFFSET'} + $stroff + $off, 0);
+        $fh->read($dat, $len);
+        if ($utf8)
+        {
+            if ($pid == 1 && defined $apple_encodings[0][$eid])
+            { $dat = TTF_word_utf8(pack("n*", map({$apple_encodings[0][$eid][$_]} unpack("C*", $dat)))); }
+            elsif ($pid == 2 && $eid == 2 && defined @cp_1252)
+            { $dat = TTF_word_utf8(pack("n*", map({$cp_1252[0][$_]} unpack("C*", $dat)))); }
+            elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
+            { $dat = TTF_word_utf8($dat); }
+        }
+        $self->{'strings'}[$nid][$pid][$eid]{$lid} = $dat;
+        $fh->seek($here, 0);
+    }
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes out all the strings
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($pid, $eid, $lid, $nid, $todo, @todo);
+    my ($len, $offset, $loc, $stroff, $endloc, $str_trans);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $loc = $fh->tell();
+    $fh->print(pack("n3", 0, 0, 0));
+    foreach $nid (0 .. $#{$self->{'strings'}})
+    {
+        foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
+        {
+            foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
+            {
+                foreach $lid (sort keys %{$self->{'strings'}[$nid][$pid][$eid]})
+                {
+                    $str_trans = $self->{'strings'}[$nid][$pid][$eid]{$lid};
+                    if ($utf8)
+                    {
+                        if ($pid == 1 && defined $apple_encodings[1][$eid])
+                        { $str_trans = pack("C*",
+                                map({$apple_encodings[1][$eid]{$_} || "?"} unpack("n*",
+                                TTF_utf8_word($str_trans)))); }
+                        elsif ($pid == 2 && $eid == 2 && defined @cp_1252)
+                        { $str_trans = pack("C*",
+                                map({$cp_1252[1][$eid]{$_} || "?"} unpack("n*",
+                                TTF_utf8_word($str_trans)))); }
+                        elsif ($pid == 2 && $eid == 0)
+                        { $str_trans =~ s/[\xc0-\xff][\x80-\xbf]+/?/og; }
+                        elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
+                        { $str_trans = TTF_utf8_word($str_trans); }
+                    }
+                    push (@todo, [$pid, $eid, $lid, $nid, $str_trans]);
+                }
+            }
+        }
+    }
+
+    $offset = 0;
+    @todo = (sort {$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]
+            || $a->[3] <=> $b->[3]} @todo);
+    foreach $todo (@todo)
+    {
+        $len = length($todo->[4]);
+        $fh->print(pack("n6", @{$todo}[0..3], $len, $offset));
+        $offset += $len;
+    }
+    
+    $stroff = $fh->tell() - $loc;
+    foreach $todo (@todo)
+    { $fh->print($todo->[4]); }
+
+    $endloc = $fh->tell();
+    $fh->seek($loc, 0);
+    $fh->print(pack("n3", 0, $#todo + 1, $stroff));
+    $fh->seek($endloc, 0);
+    $self;
+}
+
+
+=head2 $t->XML_element($context, $depth, $key, $value)
+
+Outputs the string element in nice XML (which is all the table really!)
+
+=cut
+
+sub XML_element
+{
+    my ($self) = shift;
+    my ($context, $depth, $key, $value) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($nid, $pid, $eid, $lid);
+
+    return $self->SUPER::XML_element(@_) unless ($key eq 'strings');
+
+    foreach $nid (0 .. $#{$self->{'strings'}})
+    {
+        next unless ref($self->{'strings'}[$nid]);
+#        $fh->print("$depth<strings id='$nid'>\n");
+        foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
+        {
+            foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
+            {
+                foreach $lid (sort {$a <=> $b} keys %{$self->{'strings'}[$nid][$pid][$eid]})
+                {
+                    $fh->printf("%s<string id='%s' platform='%s' encoding='%s' language='%s'>\n%s%s%s\n%s</string>\n",
+                            $depth, $nid, $pid, $eid, $lid, $depth,
+                            $context->{'indent'}, $self->{'strings'}[$nid][$pid][$eid]{$lid}, $depth);
+                }
+            }
+        }
+#        $fh->print("$depth</strings>\n");
+    }
+    $self;
+}
+
+
+=head2 $t->XML_end($context, $tag, %attrs)
+
+Store strings in the right place
+
+=cut
+
+sub XML_end
+{
+    my ($self) = shift;
+    my ($context, $tag, %attrs) = @_;
+
+    if ($tag eq 'string')
+    {
+        $self->{'strings'}[$attrs{'id'}][$attrs{'platform'}][$attrs{'encoding'}]{$attrs{'language'}}
+            = $context->{'text'};
+        return $context;
+    }
+    else
+    { return $self->SUPER::XML_end(@_); }
+}
+
+=head2 is_utf8($pid, $eid)
+
+Returns whether a string of a given platform and encoding is going to be in UTF8
+
+=cut
+
+sub is_utf8
+{
+    my ($self, $pid, $eid) = @_;
+
+    return ($utf8 && ($pid == 0 || $pid == 3 || ($pid == 2 && ($eid != 2 || defined @cp_1252))
+            || ($pid == 1 && defined $apple_encodings[$eid])));
+}
+
+
+=head2 find_name($nid)
+
+Hunts down a name in all the standard places and returns the string and for an
+array context the pid, eid & lid as well
+
+=cut
+
+sub find_name
+{
+    my ($self, $nid) = @_;
+    my ($res, $pid, $eid, $lid, $look, $k);
+
+    my (@lookup) = ([3, 1, 1033], [3, 1, -1], [3, 0, 1033], [3, 0, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1],
+                    [0, 0, 0], [1, 0, 0]);
+    foreach $look (@lookup)
+    {
+        ($pid, $eid, $lid) = @$look;
+        if ($lid == -1)
+        {
+            foreach $k (keys %{$self->{'strings'}[$nid][$pid][$eid]})
+            {
+                if (($res = $self->{strings}[$nid][$pid][$eid]{$k}) ne '')
+                {
+                    $lid = $k;
+                    last;
+                }
+            }
+        } else
+        { $res = $self->{strings}[$nid][$pid][$eid]{$lid} }
+        if ($res ne '')
+        { return wantarray ? ($res, $pid, $eid, $lid) : $res; }
+    }
+    return '';
+}
+    
+
+BEGIN {
+ at apple_encs = (
+<<'EOT',
+M>)RES==NCW$`@.'G_S5Q*L(!#?+K1VO4:.W6IJA-:\^BM?>L>1&NP(A0Q$BL
+M<*!62ZV8Z1)[K]BE$MR#O,=/7OW]7T&*6"NMI4K31EOMM)>N at XXZZ2Q#IBZZ
+MZJ:['GKJ)4NVWOKHJ]\_/\!`@PR68XBAALDUW`@CC3+:&&.-,UZ>?!-,-,ED
+M4TPUS70SS#3+;`7FF&N>0D7F6V"A119;8JEEEEMAI5566V.M==;;H-A&FVRV
+MQ5;;_OTONJ3<%;?<5^NQ1YYXYJGG7GKME3?>>N^=#S[ZY(O/OOKNFU]^JO<[
+M!$?LLMO>$#OAH4-*4F+'[(L+E*F,6SH:%\9%]C@>1W&CN&%2:9QNO]-))5ZH
+M<]9.!^/DQ/8X-V[@@#,AS0ZE+KB7R$ODA\:A26@>6H2FH9D?J17^)(I#3C at 8
+MLD)V?:(^"BE.AN30,F0XK\(Y5UUVW0TW77/'W;H_;JM6HRJ1&95%M0Y'E5%5
+.5.U4]""JB<K_`B>`?E$`
+EOT
+
+undef,
+undef,
+undef,
+<<'EOT',
+M>)RES[=/%```1O$WO8G_@$'J';W70Z2WHS>5WJN%8D6%D;BZ,3*P,;#C2D(8
+M,9&)08V)+4*(1((X2'(#[.:;7[[\*./_%D,L<<230"(!@B213`JII)%.!IED
+MD4T.N>213P&%%%%,B!)N4LJMR[Z<"BJIHIH::JFCG@;"--)$,RVTTD8['732
+M13>WN<-=>NBECWX&&&2(848898QQ)IADBFEFF.4>]WG`0^:89X%%'O&8)SSE
+M&<]9X at 4O><4R*Y?_.ZRSRQ[[''#(1S[PB<]NL\D7OO&5[_S at 9TR`(XXYX1=O
+M.>4W9_SAG`O^7OF=O>XW*N)WV!%''7/<"2>=<MH90D9'_-X(AHTUSG at 33#1@
+MT"2333'5--/-,-,LL\TQUSSS+;#0(HL-7?DMM\)*JZRVQEKKK+?!L(TVV6R+
+9K;;9;H<K+KGJ>S?<\K5O(G[7?/</+>Y>'```
+EOT
+
+<<'EOT',
+M>)RED$LSEW$`A9_-^00L,H-^(=>4Y%^2J'1Q*Y+[I2(BHA`B?!%J6EM1*28S
+M;9II[/PI*7*_%TUN\_*VZ%W:FN9LSYEGGD,\_Q?#$?SP)X"C!!)$,"&$$L8Q
+MPCG."2(X222GB,+%:<X0S5EB.$<LYXES]A>XR"42N,P5KG*-1))()H54KG.#
+M--*Y20:WR"2+;'+()8]\"BBDB-O<X2[%E'"/4LJX3SD5/*"2*AY230V/>$PM
+M==3SA`8::>(IS;3PC%;::'?X'^W#?&(0-Z-,,,,TL\PSQP)+K+#,*C]9XQ?K
+M_.8/FVRPQ0[;[+&+S=_]_J;KX/Y6I?&U.JQ.Z[GU0 at -VBNTR@;Q4G]ZI5V_U
+MQG at 83^-M?,PAXV6'VF'ZH&Z]4H_>J]]IO=:0W!K6B#[KBT;U56/ZIN\:UX1^
+?:%)3FM:,9C6G>2UH44M:UHI6'?<BYX,"6O\!%-%\5```
+EOT
+
+<<'EOT',
+M>)RES5=OSG$`0.$CYR.(A(3DUS]J4WOO59O6;&F+UMY[7R&(V'N^4ETZ=*"J
+M:M:H=>E*0D1B)7HC1KC0[R#G^LEA,/]7((Z(EK2B-?&TH2WM:$\'.M*)SG0A
+M@:YTHSL]Z$DO>M.'OO2C/P,8R*`&/X2A#&,X(QC)*$:3R!C&,H[Q3&`BDYC,
+M%))(9BK3F,X,9C*+%%*9S1S22">#N<QC/IEDL8"%+&(Q2UC*,I:S at I6L8C5K
+M6,LZUK.!C6QB,UO8RC:VLZ/A7TL5Y=11P6O>N(MWO.>#.\GG(Y_YQ!>^DAT7
+M\8WZ$%$3$OC.#W(IYC=_^!N"1SWF*<]ZP1AO*:'`;*^0%V502J6'*8LRHRQR
+M/.)Q3WC2TY[QG+D6FF^!19ZGR(M>BA*]3"'5(9Z8.>:YVSV-DD/CT"0T#RU"
+MT]",G^YUG_L]8+$E7O6%!WUIF>4^]9K7?6R%E59YQUM6>]L:[WK/5][WH;7>
+4M,X'/O&1-WSF<P]9^BOV#YW%>_\`
+EOT
+
+<<'EOT',
+M>)RERT=.%5``0-&+7K'&!B(@X/L/^/3>ZZ?SZ=*K@`KVWOL:U!68.#!&8G2@
+M$Q?F5/=@SOB0XO\$$D2**:&4)&644T$E55130RUUU--`(TTTTT(K;;3302==
+M=--#[[_?1S\###+$,".,DF:,<2:89(II9KC`+'/,L\`B2RRSPBIKK+/!13;9
+M8IM+7.8*.^QRE6M<YP8WN<5M[G"7>]SG`0]YQ&.>\)1G/.<%+WG%:][PEI0G
+M/>5IL\SVC#F>-=<\\SUG at 846>=Y at PFBQ)9::M,QR*ZRTRFIKK+4N!+[[CD]\
+M#I%?9O*-+XGH/N?BMON=CT7\B#MQUR5^^MY#ZH('7?:PJQYQS14/L!?S,S[$
+M=,SD*[]#DH\>==UC;K at 8LD)V*`B%(3?D\2<4>=Q-3[B5R#'#66>LM\%&FVRV
+GQ5;;;+?#3KOLML=>4_;9[X"##CGLB*.F'7/<"2>=<CKL_06V`DD#
+EOT
+
+undef,
+<<'EOT',
+M>)RED-DVUG$`1;=:U*Y%0C)5O^^/SSS/F>>9#"$JE7D>"D6\3S=>Q^MPU^JF
+M&^M<G[7//G1ROP1B1.130"%QBBBFA%+***>"2JJHIH9:ZJBG at 4:::*:%M[32
+M1CL==_TNNNFAES[Z&6"0(889890QQIE at DG=,,<T,L[QGCGD6^,`B2WSD$Y]9
+MY at M?^<8*JZRQS@:;;+'-#KOLL<\!AQQQS'=^<,(I9_SD%^=<\)M+KN[X-U%:
+M2`\9(2MDAWB(^,-U+/KKYYJ'_W_`!!_XT$23?.1C]8E/3?&9J2:;9KH9/O>%
+MF;XTRVQSS#7/5[[VC<&8D?D66&C<(HLML=0RRZVPTBJ7K;;&6NNLM\%&FVRV
+L):388:===MMCKP,..F2_(XXZYK#CMKGZS[YU-]QTRVUWW'7/?0]N`4(?0WT`
+EOT
+
+<<'EOT',
+M>)RED,5.0U$415=(D.X!$"ANMX^VN+M#D>+N[H4"Q5W^APF_PZ\PY.9-"`-&
+MY.3LG>-"#_\3 at P^'8OP$"%)"*6644T$E55130RUUU--`(TTTTT(K;;3302==
+M=-OZ7OH(T<\`@PP19I at 11AECG`DFF6*:&6:98YX%%EEBF15666.=#3;98IL=
+M=MECGP,.B7#$,5%...6,&.=<<,D5U]QPRQWW//#($\^\\,J;G?_II)ETXS79
+M)L<$C<,['S[GYSY=?FWK6E>Z^?L'BK,:KP0E*DD>R?6E*-7E='DM9BA36<I6
+MCG*5IWP5J%!%,O+)4;'\"BBH$I7:S')5J%)5JE:-M6JMUKM]FM1LL55M)EG=
+GZE&O^A1R(V$-NSRF<8L3ZO3L_]KN4!$=Z5A1G>A49XKI_!M<9D8J
+EOT
+
+<<'EOT',
+M>)RED,E3SW$8QU_77@<''+A]^Y5(2-F7+"%92\B^ES5ES]H,)L(8&21E*UNH
+M&"8T8ZS3I(FS_T"$_`L^-^/D8)YY/^]Y/\L\"Y/Y/XN()T8"B0P at B8$,(IG!
+MI#"$H0PCE>&DD<X(1C**T8QA+.,8SP0FDL&DT#^%J60RC>G,((N99#.+V<QA
+M+O.83PZY+""/A2QB,?DL82G+6,X*5K**U:QA+>M8SP8**&0CF]C,%K:RC2*V
+M4TP).]C)+G:SA[WLHY3]'.`@ASC,$<K"_,^QWE&?J&_4+^H?)44Q[M,<'_MS
+M7USAOS[@48]YW')/>-(*3WG:,R%ZSDK/!K[@1<][R2HO6^T5:ZSUJM>\[@UO
+M6F>]M[SM'>]ZSX90_\"'-MIDLX^">ASPQ*?!M_C,Y[ZP->KE*U_[QK>^\WW(
+CM/O!ML"=?K3#3[Z,*_AKOR]V^=5O=OO='_ZTQU^_`2-%:*``
+EOT
+
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+<<'EOT',
+M>)REC]=.E&$`1(\%&W at 4004%_7:!I?>.Z-+[TJL*=K"`BH`*J,_"+2'A!7PW
+MX;\2[LG<3#*9G!F2G$V!&'$***2(!,644$H9Y5102175U%!+'?4TT$@3S;30
+M2AN/:.<Q3Z)^!YUTT4T/O?31SP"###',""E&&6.<"2:98IH99IECG at 6>\HSG
+M+++$"U[RBM>\X2WO6&:%]WS@(Y]898W/?.$KZWQC at TVV^,X/?K+-#KO\XC=_
+M(OX!?T/"`0<=<MB1$Q?R0KXIDB%NK?TVV&B3S:?RG)`;]?<\YWDO>-$T+WG9
+M*U[UFNEF>%V]X4TSO666V=[VCG?-,==[WC?/?!_XT&#,N`466F3"8DLLM<QR
+M*ZRTRFIK(GJ=]?_Y+;;:]N\HI(>LD&W2#COMLML>>^V+=IX\2<7BCCGNA)-.
+0.>V,L\XY[P*'[!\#D^='L@``
+EOT
+
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+undef,
+);
+
+$cp_1252 = (
+<<'EOT',
+M>)P-SD-B'5```,#YJ6VE>DEM&[\VD]JVF?H./4'-U+93V[9M:SV;$141(Y74
+MTD at KG?0RR"B3S++(*IOL<L at IE]SRR"N?_`J(55`AA1515!`G7C'%E5!2*:65
+M458YY550426555%5-=754%,MM=515SWU-=!05".--=%4,\VUT%(KK;715COM
+M==!1)YTE2-1%5]UTUT-/O?361U_]]#?`0(,,-L10PPPWPDBCC#;&6..,-\%$
+MDTPVQ5333)=DAIEFF6V.N>:%9-$0&YD?BH22(82XF)10.3(@U(DDB$;F_/]%
+M0_Y0(!0*A4-\R!5RQ]R*BX\,#'4CB?]];B3)`@LMLM at 22RVSW`HKK;):LC76
+M6F>]#3;:9+,MMMIFNQUVVF6W/?;:9[\##CKDL"-2''7,<2><=,II9YQUSGD7
+M7'3)95=<=<UU-]QTRVUWW'7/?0\\],AC3SSUS',OO/3*:V^\]<Y['WSTR6=?
+1?/7-=S_\],MO?_S]!Y==>0@`
+EOT
+);
+}
+
+1;
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+Unicode type strings will be stored in utf8 for all known platforms,
+once Perl 5.6 has been released and I can find all the mapping tables, etc.
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/OS_2.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/OS_2.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/OS_2.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,306 +1,306 @@
-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 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);
-use Font::TTF::Table;
-
- at ISA = qw(Font::TTF::Table);
- at 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');
-
-use Font::TTF::Utils;
-
-sub init
-{
-    my ($k, $v, $c, $n, $i, $t, $j);
-
-    $n = 0;
-    @lens = (76, 84, 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 < 3; $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 < 3)
-    {
-        $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);
-
-    return undef unless ($self->SUPER::update);
-
-    $self->{' PARENT'}{'cmap'}->update;
-    $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef;
-
-    @keys = sort {$a <=> $b} 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 ($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;
-    }
-    
-    $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1);
-    $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2);
-    
-    $self;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
+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 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);
+use Font::TTF::Table;
+
+ at ISA = qw(Font::TTF::Table);
+ at 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');
+
+use Font::TTF::Utils;
+
+sub init
+{
+    my ($k, $v, $c, $n, $i, $t, $j);
+
+    $n = 0;
+    @lens = (76, 84, 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 < 3; $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 < 3)
+    {
+        $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);
+
+    return undef unless ($self->SUPER::update);
+
+    $self->{' PARENT'}{'cmap'}->update;
+    $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef;
+
+    @keys = sort {$a <=> $b} 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 ($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;
+    }
+    
+    $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1);
+    $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2);
+    
+    $self;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldCmap.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldCmap.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldCmap.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,358 +1,358 @@
-package Font::TTF::OldCmap;
-
-=head1 NAME
-
-Font::TTF::OldCmap - Character map table
-
-This module is deprecated
-
-=head1 DESCRIPTION
-
-Looks after the character map. The primary structure used for handling a cmap
-is the L<Font::TTF::Segarr> which handles the segmented arrays of format 4 tables,
-and in a simpler form for format 0 tables.
-
-Due to the complexity of working with segmented arrays, most of the handling of
-such arrays is via methods rather than via instance variables.
-
-One important feature of a format 4 table is that it always contains a segment
-with a final address of 0xFFFF. If you are creating a table from scratch this is
-important (although L<Font::TTF::Segarr> can work quite happily without it).
-
-
-=head1 INSTANCE VARIABLES
-
-The instance variables listed here are not preceeded by a space due to their
-emulating structural information in the font.
-
-=over 4
-
-=item Num
-
-Number of subtables in this table
-
-=item Tables
-
-An array of subtables ([0..Num-1])
-
-=back
-
-Each subtables also has its own instance variables which are, again, not
-preceeded by a space.
-
-=over 4
-
-=item Platform
-
-The platform number for this subtable
-
-=item Encoding
-
-The encoding number for this subtable
-
-=item Format
-
-Gives the stored format of this subtable
-
-=item Ver
-
-Gives the version (or language) information for this subtable
-
-=item val
-
-This points to a L<Font::TTF::Segarr> which contains the content of the particular
-subtable.
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-require Font::TTF::Table;
-require Font::TTF::Segarr;
-
- at ISA = qw(Font::TTF::Table);
-
-
-=head2 $t->read
-
-Reads the cmap into memory. Format 4 subtables read the whole subtable and
-fill in the segmented array accordingly.
-
-Format 2 subtables are not read at all.
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $i, $j, $k, $id, @ids, $s);
-    my ($start, $end, $range, $delta, $form, $len, $num, $ver);
-    my ($fh) = $self->{' INFILE'};
-
-    $self->SUPER::read or return $self;
-    $fh->read($dat, 4);
-    $self->{'Num'} = unpack("x2n", $dat);
-    $self->{'Tables'} = [];
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = {};
-        $fh->read($dat, 8);
-        ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat));
-        $s->{'LOC'} += $self->{' OFFSET'};
-        push(@{$self->{'Tables'}}, $s);
-    }
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        $fh->seek($s->{'LOC'}, 0);
-        $fh->read($dat, 6);
-        ($form, $len, $ver) = (unpack("n3", $dat));
-
-        $s->{'Format'} = $form;
-        $s->{'Ver'} = $ver;
-        if ($form == 0)
-        {
-            $s->{'val'} = Font::TTF::Segarr->new;
-            $fh->read($dat, 256);
-            $s->{'val'}->fastadd_segment(0, 2, unpack("C*", $dat));
-            $s->{'Start'} = 0;
-            $s->{'Num'} = 256;
-        } elsif ($form == 6)
-        {
-            my ($start, $ecount);
-            
-            $fh->read($dat, 4);
-            ($start, $ecount) = unpack("n2", $dat);
-            $fh->read($dat, $ecount << 1);
-            $s->{'val'} = Font::TTF::Segarr->new;
-            $s->{'val'}->fastadd_segment($start, 2, unpack("n*", $dat));
-            $s->{'Start'} = $start;
-            $s->{'Num'} = $ecount;
-        } elsif ($form == 2)
-        {
-# no idea what to do here yet
-        } elsif ($form == 4)
-        {
-            $fh->read($dat, 8);
-            $num = unpack("n", $dat);
-            $num >>= 1;
-            $fh->read($dat, $len - 14);
-            $s->{'val'} = Font::TTF::Segarr->new;
-            for ($j = 0; $j < $num; $j++)
-            {
-                $end = unpack("n", substr($dat, $j << 1, 2));
-                $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2));
-                $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2));
-                $delta -= 65536 if $delta > 32767;
-                $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2));
-                @ids = ();
-                for ($k = $start; $k <= $end; $k++)
-                {
-                    if ($range == 0)
-                    { $id = $k + $delta; }
-                    else
-                    { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 +
-                                        2 + ($k - $start) * 2 + $range, 2)) + $delta; }
-		            $id -= 65536 if $id > 65536;
-                    push (@ids, $id);
-                }
-                $s->{'val'}->fastadd_segment($start, 0, @ids);
-            }
-            $s->{'val'}->tidy;
-            $s->{'Num'} = 0x10000;               # always ends here
-            $s->{'Start'} = $s->{'val'}[0]{'START'};
-        }
-    }
-    $self;
-}
-
-
-=head2 $t->ms_lookup($uni)
-
-Given a Unicode value in the MS table (Platform 3, Encoding 1) locates that
-table and looks up the appropriate glyph number from it.
-
-=cut
-
-sub ms_lookup
-{
-    my ($self, $uni) = @_;
-
-    $self->find_ms || return undef unless (defined $self->{' mstable'});
-    return $self->{' mstable'}{'val'}->at($uni);
-}
-
-
-=head2 $t->find_ms
-
-Finds the Microsoft Unicode table and sets the C<mstable> instance variable
-to it if found. Returns the table it finds.
-
-=cut
-sub find_ms
-{
-    my ($self) = @_;
-    my ($i, $s, $alt);
-
-    return $self->{' mstable'} if defined $self->{' mstable'};
-    $self->read;
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        if ($s->{'Platform'} == 3)
-        {
-            $self->{' mstable'} = $s;
-            last if ($s->{'Encoding'} == 1);
-        } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1))
-        { $self->{' mstable'} = $s; }
-    }
-    $self->{' mstable'};
-}
-
-
-=head2 $t->out($fh)
-
-Writes out a cmap table to a filehandle. If it has not been read, then
-just copies from input file to output
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($loc, $s, $i, $base_loc, $j);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $base_loc = $fh->tell();
-    $fh->print(pack("n2", 0, $self->{'Num'}));
-
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); }
-    
-    for ($i = 0; $i < $self->{'Num'}; $i++)
-    {
-        $s = $self->{'Tables'}[$i];
-        $s->{'val'}->tidy;
-        $s->{' outloc'} = $fh->tell();
-        $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'}));       # come back for length
-        if ($s->{'Format'} == 0)
-        {
-            $fh->print(pack("C256", $s->{'val'}->at(0, 256)));
-        } elsif ($s->{'Format'} == 6)
-        {
-            $fh->print(pack("n2", $s->{'Start'}, $s->{'Num'}));
-            $fh->print(pack("n*", $s->{'val'}->at($s->{'Start'}, $s->{'Num'})));
-        } elsif ($s->{'Format'} == 2)
-        {
-        } elsif ($s->{'Format'} == 4)
-        {
-            my ($num, $sRange, $eSel);
-            my (@deltas, $delta, @range, $flat, $k, $segs, $count);
-
-            $num = $#{$s->{'val'}} + 1;
-            $segs = $s->{'val'};
-            for ($sRange = 1, $eSel = 0; $sRange <= $num; $eSel++)
-            { $sRange <<= 1;}
-            $eSel--;
-            $fh->print(pack("n4", $num * 2, $sRange, $eSel, ($num * 2) - $sRange));
-            $fh->print(pack("n*", map {$_->{'START'} + $_->{'LEN'} - 1} @$segs));
-            $fh->print(pack("n", 0));
-            $fh->print(pack("n*", map {$_->{'START'}} @$segs));
-
-            for ($j = 0; $j < $num; $j++)
-            {
-                $delta = $segs->[$j]{'VAL'}[0]; $flat = 1;
-                for ($k = 1; $k < $segs->[$j]{'LEN'}; $k++)
-                {
-                    if ($segs->[$j]{'VAL'}[$k] == 0)
-                    { $flat = 0; }
-                    if ($delta + $k != $segs->[$j]{'VAL'}[$k])
-                    {
-                        $delta = 0;
-                        last;
-                    }
-                }
-                push (@range, $flat);
-                push (@deltas, ($delta ? $delta - $segs->[$j]{'START'} : 0));
-            }
-            $fh->print(pack("n*", @deltas));
-
-            $count = 0;
-            for ($j = 0; $j < $num; $j++)
-            {
-                $delta = $deltas[$j];
-                if ($delta != 0 && $range[$j] == 1)
-                { $range[$j] = 0; }
-                else
-                {
-                    $range[$j] = ($count + $num - $j) << 1;
-                    $count += $segs->[$j]{'LEN'};
-                }
-            }
-
-            $fh->print(pack("n*", @range));
-
-            for ($j = 0; $j < $num; $j++)
-            {
-                next if ($range[$j] == 0);
-                for ($k = 0; $k < $segs->[$j]{'LEN'}; $k++)
-                { $fh->print(pack("n", $segs->[$j]{'VAL'}[$k])); }
-            }
-        }
-
-        $loc = $fh->tell();
-        $fh->seek($s->{' outloc'} + 2, 0);
-        $fh->print(pack("n", $loc - $s->{' outloc'}));
-        $fh->seek($base_loc + 8 + ($i << 3), 0);
-        $fh->print(pack("N", $s->{' outloc'} - $base_loc));
-        $fh->seek($loc, 0);
-    }
-    $self;
-}
-
-
-=head2 @map = $t->reverse([$num])
-
-Returns a reverse map of the table of given number or the Microsoft
-cmap. I.e. given a glyph gives the Unicode value for it.
-
-=cut
-
-sub reverse
-{
-    my ($self, $tnum) = @_;
-    my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms;
-    my (@res, $i, $s, $first);
-
-    foreach $s (@{$table->{'val'}})
-    {
-        $first = $s->{'START'};
-        map {$res[$_] = $first unless $res[$_]; $first++;} @{$s->{'VAL'}};
-    }
-    @res;
-}
-
-1;
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-No support for format 2 tables (MBCS)
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::OldCmap;
+
+=head1 NAME
+
+Font::TTF::OldCmap - Character map table
+
+This module is deprecated
+
+=head1 DESCRIPTION
+
+Looks after the character map. The primary structure used for handling a cmap
+is the L<Font::TTF::Segarr> which handles the segmented arrays of format 4 tables,
+and in a simpler form for format 0 tables.
+
+Due to the complexity of working with segmented arrays, most of the handling of
+such arrays is via methods rather than via instance variables.
+
+One important feature of a format 4 table is that it always contains a segment
+with a final address of 0xFFFF. If you are creating a table from scratch this is
+important (although L<Font::TTF::Segarr> can work quite happily without it).
+
+
+=head1 INSTANCE VARIABLES
+
+The instance variables listed here are not preceeded by a space due to their
+emulating structural information in the font.
+
+=over 4
+
+=item Num
+
+Number of subtables in this table
+
+=item Tables
+
+An array of subtables ([0..Num-1])
+
+=back
+
+Each subtables also has its own instance variables which are, again, not
+preceeded by a space.
+
+=over 4
+
+=item Platform
+
+The platform number for this subtable
+
+=item Encoding
+
+The encoding number for this subtable
+
+=item Format
+
+Gives the stored format of this subtable
+
+=item Ver
+
+Gives the version (or language) information for this subtable
+
+=item val
+
+This points to a L<Font::TTF::Segarr> which contains the content of the particular
+subtable.
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+require Font::TTF::Table;
+require Font::TTF::Segarr;
+
+ at ISA = qw(Font::TTF::Table);
+
+
+=head2 $t->read
+
+Reads the cmap into memory. Format 4 subtables read the whole subtable and
+fill in the segmented array accordingly.
+
+Format 2 subtables are not read at all.
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $i, $j, $k, $id, @ids, $s);
+    my ($start, $end, $range, $delta, $form, $len, $num, $ver);
+    my ($fh) = $self->{' INFILE'};
+
+    $self->SUPER::read or return $self;
+    $fh->read($dat, 4);
+    $self->{'Num'} = unpack("x2n", $dat);
+    $self->{'Tables'} = [];
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = {};
+        $fh->read($dat, 8);
+        ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat));
+        $s->{'LOC'} += $self->{' OFFSET'};
+        push(@{$self->{'Tables'}}, $s);
+    }
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        $fh->seek($s->{'LOC'}, 0);
+        $fh->read($dat, 6);
+        ($form, $len, $ver) = (unpack("n3", $dat));
+
+        $s->{'Format'} = $form;
+        $s->{'Ver'} = $ver;
+        if ($form == 0)
+        {
+            $s->{'val'} = Font::TTF::Segarr->new;
+            $fh->read($dat, 256);
+            $s->{'val'}->fastadd_segment(0, 2, unpack("C*", $dat));
+            $s->{'Start'} = 0;
+            $s->{'Num'} = 256;
+        } elsif ($form == 6)
+        {
+            my ($start, $ecount);
+            
+            $fh->read($dat, 4);
+            ($start, $ecount) = unpack("n2", $dat);
+            $fh->read($dat, $ecount << 1);
+            $s->{'val'} = Font::TTF::Segarr->new;
+            $s->{'val'}->fastadd_segment($start, 2, unpack("n*", $dat));
+            $s->{'Start'} = $start;
+            $s->{'Num'} = $ecount;
+        } elsif ($form == 2)
+        {
+# no idea what to do here yet
+        } elsif ($form == 4)
+        {
+            $fh->read($dat, 8);
+            $num = unpack("n", $dat);
+            $num >>= 1;
+            $fh->read($dat, $len - 14);
+            $s->{'val'} = Font::TTF::Segarr->new;
+            for ($j = 0; $j < $num; $j++)
+            {
+                $end = unpack("n", substr($dat, $j << 1, 2));
+                $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2));
+                $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2));
+                $delta -= 65536 if $delta > 32767;
+                $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2));
+                @ids = ();
+                for ($k = $start; $k <= $end; $k++)
+                {
+                    if ($range == 0)
+                    { $id = $k + $delta; }
+                    else
+                    { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 +
+                                        2 + ($k - $start) * 2 + $range, 2)) + $delta; }
+		            $id -= 65536 if $id > 65536;
+                    push (@ids, $id);
+                }
+                $s->{'val'}->fastadd_segment($start, 0, @ids);
+            }
+            $s->{'val'}->tidy;
+            $s->{'Num'} = 0x10000;               # always ends here
+            $s->{'Start'} = $s->{'val'}[0]{'START'};
+        }
+    }
+    $self;
+}
+
+
+=head2 $t->ms_lookup($uni)
+
+Given a Unicode value in the MS table (Platform 3, Encoding 1) locates that
+table and looks up the appropriate glyph number from it.
+
+=cut
+
+sub ms_lookup
+{
+    my ($self, $uni) = @_;
+
+    $self->find_ms || return undef unless (defined $self->{' mstable'});
+    return $self->{' mstable'}{'val'}->at($uni);
+}
+
+
+=head2 $t->find_ms
+
+Finds the Microsoft Unicode table and sets the C<mstable> instance variable
+to it if found. Returns the table it finds.
+
+=cut
+sub find_ms
+{
+    my ($self) = @_;
+    my ($i, $s, $alt);
+
+    return $self->{' mstable'} if defined $self->{' mstable'};
+    $self->read;
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        if ($s->{'Platform'} == 3)
+        {
+            $self->{' mstable'} = $s;
+            last if ($s->{'Encoding'} == 1);
+        } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1))
+        { $self->{' mstable'} = $s; }
+    }
+    $self->{' mstable'};
+}
+
+
+=head2 $t->out($fh)
+
+Writes out a cmap table to a filehandle. If it has not been read, then
+just copies from input file to output
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($loc, $s, $i, $base_loc, $j);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $base_loc = $fh->tell();
+    $fh->print(pack("n2", 0, $self->{'Num'}));
+
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); }
+    
+    for ($i = 0; $i < $self->{'Num'}; $i++)
+    {
+        $s = $self->{'Tables'}[$i];
+        $s->{'val'}->tidy;
+        $s->{' outloc'} = $fh->tell();
+        $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'}));       # come back for length
+        if ($s->{'Format'} == 0)
+        {
+            $fh->print(pack("C256", $s->{'val'}->at(0, 256)));
+        } elsif ($s->{'Format'} == 6)
+        {
+            $fh->print(pack("n2", $s->{'Start'}, $s->{'Num'}));
+            $fh->print(pack("n*", $s->{'val'}->at($s->{'Start'}, $s->{'Num'})));
+        } elsif ($s->{'Format'} == 2)
+        {
+        } elsif ($s->{'Format'} == 4)
+        {
+            my ($num, $sRange, $eSel);
+            my (@deltas, $delta, @range, $flat, $k, $segs, $count);
+
+            $num = $#{$s->{'val'}} + 1;
+            $segs = $s->{'val'};
+            for ($sRange = 1, $eSel = 0; $sRange <= $num; $eSel++)
+            { $sRange <<= 1;}
+            $eSel--;
+            $fh->print(pack("n4", $num * 2, $sRange, $eSel, ($num * 2) - $sRange));
+            $fh->print(pack("n*", map {$_->{'START'} + $_->{'LEN'} - 1} @$segs));
+            $fh->print(pack("n", 0));
+            $fh->print(pack("n*", map {$_->{'START'}} @$segs));
+
+            for ($j = 0; $j < $num; $j++)
+            {
+                $delta = $segs->[$j]{'VAL'}[0]; $flat = 1;
+                for ($k = 1; $k < $segs->[$j]{'LEN'}; $k++)
+                {
+                    if ($segs->[$j]{'VAL'}[$k] == 0)
+                    { $flat = 0; }
+                    if ($delta + $k != $segs->[$j]{'VAL'}[$k])
+                    {
+                        $delta = 0;
+                        last;
+                    }
+                }
+                push (@range, $flat);
+                push (@deltas, ($delta ? $delta - $segs->[$j]{'START'} : 0));
+            }
+            $fh->print(pack("n*", @deltas));
+
+            $count = 0;
+            for ($j = 0; $j < $num; $j++)
+            {
+                $delta = $deltas[$j];
+                if ($delta != 0 && $range[$j] == 1)
+                { $range[$j] = 0; }
+                else
+                {
+                    $range[$j] = ($count + $num - $j) << 1;
+                    $count += $segs->[$j]{'LEN'};
+                }
+            }
+
+            $fh->print(pack("n*", @range));
+
+            for ($j = 0; $j < $num; $j++)
+            {
+                next if ($range[$j] == 0);
+                for ($k = 0; $k < $segs->[$j]{'LEN'}; $k++)
+                { $fh->print(pack("n", $segs->[$j]{'VAL'}[$k])); }
+            }
+        }
+
+        $loc = $fh->tell();
+        $fh->seek($s->{' outloc'} + 2, 0);
+        $fh->print(pack("n", $loc - $s->{' outloc'}));
+        $fh->seek($base_loc + 8 + ($i << 3), 0);
+        $fh->print(pack("N", $s->{' outloc'} - $base_loc));
+        $fh->seek($loc, 0);
+    }
+    $self;
+}
+
+
+=head2 @map = $t->reverse([$num])
+
+Returns a reverse map of the table of given number or the Microsoft
+cmap. I.e. given a glyph gives the Unicode value for it.
+
+=cut
+
+sub reverse
+{
+    my ($self, $tnum) = @_;
+    my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms;
+    my (@res, $i, $s, $first);
+
+    foreach $s (@{$table->{'val'}})
+    {
+        $first = $s->{'START'};
+        map {$res[$_] = $first unless $res[$_]; $first++;} @{$s->{'VAL'}};
+    }
+    @res;
+}
+
+1;
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+No support for format 2 tables (MBCS)
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldMort.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldMort.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/OldMort.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,705 +1,705 @@
-package Font::TTF::OldMort;
-
-=head1 NAME
-
-Font::TTF::OldMort - Glyph Metamorphosis table in a font
-
-=head1 DESCRIPTION
-
-=head1 INSTANCE VARIABLES
-
-=item version
-
-table version number (Fixed: currently 1.0)
-
-=item chains
-
-list of metamorphosis chains, each of which has its own fields:
-
-=over
-
-=item defaultFlags
-
-chain's default subfeature flags (UInt32)
-
-=item featureEntries
-
-list of feature entries, each of which has fields:
-
-=over
-
-=item type
-
-=item setting
-
-=item enable
-
-=item disable
-
-=back
-
-=item subtables
-
-list of metamorphosis subtables, each of which has fields:
-
-=over
-
-=item type
-
-subtable type (0: rearrangement; 1: contextual substitution; 2: ligature;
-4: non-contextual substitution; 5: insertion)
-
-=item direction
-
-processing direction ('LR' or 'RL')
-
-=item orientation
-
-applies to text in which orientation ('VH', 'V', or 'H')
-
-=item subFeatureFlags
-
-the subfeature flags controlling whether the table is used (UInt32)
-
-=back
-
-Further fields depend on the type of subtable:
-
-=over
-
-Rearrangement table:
-
-=over
-
-=item classes
-
-array of lists of glyphs
-
-=item states
-
-array of arrays of hashes{'nextState', 'flags'}
-
-=back
-
-Contextual substitution table:
-
-=over
-
-=item classes
-
-array of lists of glyphs
-
-=item states
-
-array of array of hashes{'nextState', 'flags', 'actions'}, where C<actions>
-is an array of two elements which are offsets to be added to [marked, current]
-glyph to get index into C<mappings> (or C<undef> if no mapping to be applied)
-
-=item mappings
-
-list of glyph codes mapped to through the state table mappings
-
-=back
-
-Ligature table:
-
-Non-contextual substitution table:
-
-Insertion table:
-
-=back
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $fh, $numChains);
-    
-    $self->SUPER::read or return $self;
-
-    $fh = $self->{' INFILE'};
-
-    $fh->read($dat, 8);
-    ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat);
-    
-    my $chains = [];
-    foreach (1 .. $numChains) {
-        my $chainStart = $fh->tell();
-        $fh->read($dat, 12);
-        my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat);
-        my $featureEntries = [];
-        foreach (1 .. $nFeatureEntries) {
-            $fh->read($dat, 12);
-            my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat);
-            push @$featureEntries,    {
-                                        'type'        => $featureType,
-                                        'setting'    => $featureSetting,
-                                        'enable'    => $enableFlags,
-                                        'disable'    => $disableFlags
-                                    };
-        }
-        my $subtables = [];
-        foreach (1 .. $nSubtables) {
-            my $subtableStart = $fh->tell();
-            $fh->read($dat, 8);
-            my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat);
-            my $type = $coverage & 0x0007;
-
-            my $subtable =    {
-                                'type'                => $type,
-                                'direction'            => (($coverage & 0x4000) ? 'RL' : 'LR'),
-                                'orientation'        => (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'),
-                                'subFeatureFlags'    => $subFeatureFlags
-                            };
-
-            if ($type == 0) {    # rearrangement
-                my ($classes, $states) = AAT_read_state_table($fh, 0);
-                $subtable->{'classes'} = $classes;
-                $subtable->{'states'} = $states;
-            }
-
-            elsif ($type == 1) {    # contextual
-                my $stateTableStart = $fh->tell();
-                my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
-
-                $fh->seek($stateTableStart, IO::File::SEEK_SET);
-                $fh->read($dat, 10);
-                my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat);
-                my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $length - 8];
-
-                foreach (@$entries) {
-                    my $actions = $_->{'actions'};
-                    foreach (@$actions) {
-                        $_ = $_ ? $_ - ($mappingTables / 2) : undef;
-                    }
-                }
-                
-                $subtable->{'classes'} = $classes;
-                $subtable->{'states'} = $states;
-                $subtable->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))];
-            }
-
-            elsif ($type == 2) {    # ligature
-                my $stateTableStart = $fh->tell();
-                my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
-                
-                $fh->seek($stateTableStart, IO::File::SEEK_SET);
-                $fh->read($dat, 14);
-                my ($stateSize, $classTable, $stateArray, $entryTable,
-                    $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat);
-                my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $length - 8];
-                
-                my %actions;
-                my $actionLists;
-                foreach (@$entries) {
-                    my $offset = $_->{'flags'} & 0x3fff;
-                    $_->{'flags'} &= ~0x3fff;
-                    if ($offset != 0) {
-                        if (not defined $actions{$offset}) {
-                            $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET);
-                            my $actionList;
-                            while (1) {
-                                $fh->read($dat, 4);
-                                my $action = unpack("N", $dat);
-                                my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff));
-                                $component -= 0x40000000 if $component > 0x1fffffff;
-                                $component -= $componentTable / 2;
-                                push @$actionList, { 'store' => $store, 'component' => $component };
-                                last if $last;
-                            }
-                            push @$actionLists, $actionList;
-                            $actions{$offset} = $#$actionLists;
-                        }
-                        $_->{'actions'} = $actions{$offset};
-                    }
-                }
-                
-                $subtable->{'componentTable'} = $componentTable;
-                my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))];
-                foreach (@$components) {
-                    $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable;
-                }
-                $subtable->{'components'} = $components;
-                
-                $subtable->{'ligatureTable'} = $ligatureTable;
-                $subtable->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))];
-                
-                $subtable->{'classes'} = $classes;
-                $subtable->{'states'} = $states;
-                $subtable->{'actionLists'} = $actionLists;
-            }
-
-            elsif ($type == 4) {    # non-contextual
-                my ($format, $lookup) = AAT_read_lookup($fh, 2, $length - 8, undef);
-                $subtable->{'format'} = $format;
-                $subtable->{'lookup'} = $lookup;
-            }
-
-            elsif ($type == 5) {    # insertion
-                my $stateTableStart = $fh->tell();
-                my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
-                
-                my %insertListHash;
-                my $insertLists;
-                foreach (@$entries) {
-                    my $flags = $_->{'flags'};
-                    my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f));
-                    my $actions = $_->{'actions'};
-                    foreach (0 .. 1) {
-                        if ($insertCount[$_] > 0) {
-                            $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET);
-                            $fh->read($dat, $insertCount[$_] * 2);
-                            if (not defined $insertListHash{$dat}) {
-                                push @$insertLists, [unpack("n*", $dat)];
-                                $insertListHash{$dat} = $#$insertLists;
-                            }
-                            $actions->[$_] = $insertListHash{$dat};
-                        }
-                        else {
-                            $actions->[$_] = undef;
-                        }
-                    }
-                }
-
-                $subtable->{'classes'} = $classes;
-                $subtable->{'states'} = $states;
-                $subtable->{'insertLists'} = $insertLists;
-            }
-
-            else {
-                die "unknown subtable type";
-            }
-            
-            push @$subtables, $subtable;
-            $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
-        }
-        
-        push @$chains,    {
-                            'defaultFlags'        => $defaultFlags,
-                            'featureEntries'    => $featureEntries,
-                            'subtables'            => $subtables
-                        };
-        $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
-    }
-
-    $self->{'chains'} = $chains;
-
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    my $chains = $self->{'chains'};
-    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains));
-
-    foreach (@$chains) {
-        my $chainStart = $fh->tell();
-        my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'});
-        $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length
-        
-        foreach (@$featureEntries) {
-            $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}));
-        }
-        
-        foreach (@$subtables) {
-            my $subtableStart = $fh->tell();
-            my $type = $_->{'type'};
-            my $coverage = $type;
-            $coverage += 0x4000 if $_->{'direction'} eq 'RL';
-            $coverage += 0x2000 if $_->{'orientation'} eq 'VH';
-            $coverage += 0x8000 if $_->{'orientation'} eq 'V';
-            
-            $fh->print(TTF_Pack("SSL", 0, $coverage, $_->{'subFeatureFlags'}));    # placeholder for length
-            
-            if ($type == 0) {    # rearrangement
-                AAT_write_state_table($fh, $_->{'classes'}, $_->{'states'}, 0);
-            }
-            
-            elsif ($type == 1) {    # contextual
-                my $stHeader = $fh->tell();
-                $fh->print(pack("nnnnn", (0) x 5));    # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables
-                
-                my $classTable = $fh->tell() - $stHeader;
-                my $classes = $_->{'classes'};
-                AAT_write_classes($fh, $classes);
-                
-                my $stateArray = $fh->tell() - $stHeader;
-                my $states = $_->{'states'};
-                my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, 
-                        sub {
-                            my $actions = $_->{'actions'};
-                            ( $_->{'flags'}, @$actions )
-                        }
-                    );
-
-                my $entryTable = $fh->tell() - $stHeader;
-                my $offset = ($entryTable + 8 * @$entries) / 2;
-                foreach (@$entries) {
-                    my ($nextState, $flags, @parts) = split /,/;
-                    $fh->print(pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts));
-                }
-
-                my $mappingTables = $fh->tell() - $stHeader;
-                my $mappings = $_->{'mappings'};
-                $fh->print(pack("n*", @$mappings));
-                
-                my $loc = $fh->tell();
-                $fh->seek($stHeader, IO::File::SEEK_SET);
-                $fh->print(pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables));
-                $fh->seek($loc, IO::File::SEEK_SET);
-            }
-            
-            elsif ($type == 2) {    # ligature
-                my $stHeader = $fh->tell();
-                $fh->print(pack("nnnnnnn", (0) x 7));    # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures
-            
-                my $classTable = $fh->tell() - $stHeader;
-                my $classes = $_->{'classes'};
-                AAT_write_classes($fh, $classes);
-                
-                my $stateArray = $fh->tell() - $stHeader;
-                my $states = $_->{'states'};
-                
-                my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states,
-                        sub {
-                            ( $_->{'flags'} & 0xc000, $_->{'actions'} )
-                        }
-                    );
-                
-                my $actionLists = $_->{'actionLists'};
-                my %actionListOffset;
-                my $actionListDataLength = 0;
-                my @actionListEntries;
-                foreach (0 .. $#$entries) {
-                    my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]);
-                    if ($offset eq "") {
-                        $offset = undef;
-                    }
-                    else {
-                        if (defined $actionListOffset{$offset}) {
-                            $offset = $actionListOffset{$offset};
-                        }
-                        else {
-                            $actionListOffset{$offset} = $actionListDataLength;
-                            my $list = $actionLists->[$offset];
-                            $actionListDataLength += 4 * @$list;
-                            push @actionListEntries, $list;
-                            $offset = $actionListOffset{$offset};
-                        }
-                    }
-                    $entries->[$_] = [ $nextState, $flags, $offset ];
-                }
-                my $entryTable = $fh->tell() - $stHeader;
-                my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3;
-                foreach (@$entries) {
-                    $_->[2] += $ligActionLists if defined $_->[2];
-                    $fh->print(pack("nn", $_->[0], $_->[1] + $_->[2]));
-                }
-                $fh->print(pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4)));
-                
-                die "internal error" if $fh->tell() != $ligActionLists + $stHeader;
-                
-                my $componentTable = $fh->tell() - $stHeader + $actionListDataLength;
-                my $actionList;
-                foreach $actionList (@actionListEntries) {
-                    foreach (0 .. $#$actionList) {
-                        my $action = $actionList->[$_];
-                        my $val = $action->{'component'} + $componentTable / 2;
-                        $val += 0x40000000 if $val < 0;
-                        $val &= 0x3fffffff;
-                        $val |= 0x40000000 if $action->{'store'};
-                        $val |= 0x80000000 if $_ == $#$actionList;
-                        $fh->print(pack("N", $val));
-                    }
-                }
-
-                die "internal error" if $fh->tell() != $componentTable + $stHeader;
-
-                my $components = $_->{'components'};
-                my $ligatureTable = $componentTable + @$components * 2;
-                $fh->print(pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components));
-                
-                my $ligatures = $_->{'ligatures'};
-                $fh->print(pack("n*", @$ligatures));
-                
-                my $loc = $fh->tell();
-                $fh->seek($stHeader, IO::File::SEEK_SET);
-                $fh->print(pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable));
-                $fh->seek($loc, IO::File::SEEK_SET);
-            }
-            
-            elsif ($type == 4) {    # non-contextual
-                AAT_write_lookup($fh, $_->{'format'}, $_->{'lookup'}, 2, undef);
-            }
-            
-            elsif ($type == 5) {    # insertion
-            }
-            
-            else {
-                die "unknown subtable type";
-            }
-            
-            my $length = $fh->tell() - $subtableStart;
-            my $padBytes = (4 - ($length & 3)) & 3;
-            $fh->print(pack("C*", (0) x $padBytes));
-            $length += $padBytes;
-            $fh->seek($subtableStart, IO::File::SEEK_SET);
-            $fh->print(pack("n", $length));
-            $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
-        }
-        
-        my $chainLength = $fh->tell() - $chainStart;
-        $fh->seek($chainStart + 4, IO::File::SEEK_SET);
-        $fh->print(pack("N", $chainLength));
-        $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
-    }
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    
-    $self->read;
-    my $feat = $self->{' PARENT'}->{'feat'};
-    $feat->read;
-    my $post = $self->{' PARENT'}->{'post'};
-    $post->read;
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $fh->printf("version %f\n", $self->{'version'});
-    
-    my $chains = $self->{'chains'};
-    foreach (@$chains) {
-        my $defaultFlags = $_->{'defaultFlags'};
-        $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags);
-        
-        my $featureEntries = $_->{'featureEntries'};
-        foreach (@$featureEntries) {
-            $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n",
-                        $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'},
-                        $feat->settingName($_->{'type'}, $_->{'setting'}));
-        }
-        
-        my $subtables = $_->{'subtables'};
-        foreach (@$subtables) {
-            my $type = $_->{'type'};
-            my $subFeatureFlags = $_->{'subFeatureFlags'};
-            $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
-                        subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
-                        "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
-                        join(", ",
-                            map {
-                                join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
-                            } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
-                        ) );
-            
-            if ($type == 0) {    # rearrangement
-                print_classes_($fh, $_, $post);
-
-                $fh->print("\n");
-                my $states = $_->{'states'};
-                my @verbs = (    "0", "Ax->xA", "xD->Dx", "AxD->DxA",
-                                "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx",
-                                "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA",
-                                "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA");
-                foreach (0 .. $#$states) {
-                    $fh->printf("\t\tState %d:", $_);
-                    my $state = $states->[$_];
-                    foreach (@$state) {
-                        my $flags;
-                        $flags .= "!" if ($_->{'flags'} & 0x4000);
-                        $flags .= "<" if ($_->{'flags'} & 0x8000);
-                        $flags .= ">" if ($_->{'flags'} & 0x2000);
-                        $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]);
-                    }
-                    $fh->print("\n");
-                }
-            }
-            
-            elsif ($type == 1) {    # contextual
-                print_classes_($fh, $_, $post);
-                
-                $fh->print("\n");
-                my $states = $_->{'states'};
-                foreach (0 .. $#$states) {
-                    $fh->printf("\t\tState %d:", $_);
-                    my $state = $states->[$_];
-                    foreach (@$state) {
-                        my $flags;
-                        $flags .= "!" if ($_->{'flags'} & 0x4000);
-                        $flags .= "*" if ($_->{'flags'} & 0x8000);
-                        my $actions = $_->{'actions'};
-                        $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
-                    }
-                    $fh->print("\n");
-                }
-
-                $fh->print("\n");
-                my $mappings = $_->{'mappings'};
-                foreach (0 .. $#$mappings) {
-                    $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]);
-                }
-            }
-            
-            elsif ($type == 2) {    # ligature
-                print_classes_($fh, $_, $post);
-                
-                $fh->print("\n");
-                my $states = $_->{'states'};
-                foreach (0 .. $#$states) {
-                    $fh->printf("\t\tState %d:", $_);
-                    my $state = $states->[$_];
-                    foreach (@$state) {
-                        my $flags;
-                        $flags .= "!" if ($_->{'flags'} & 0x4000);
-                        $flags .= "*" if ($_->{'flags'} & 0x8000);
-                        $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "=");
-                    }
-                    $fh->print("\n");
-                }
-
-                $fh->print("\n");
-                my $actionLists = $_->{'actionLists'};
-                foreach (0 .. $#$actionLists) {
-                    $fh->printf("\t\tList %d:\t", $_);
-                    my $actionList = $actionLists->[$_];
-                    $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList));
-                }
-
-                my $ligatureTable = $_->{'ligatureTable'};
-
-                $fh->print("\n");
-                my $components = $_->{'components'};
-                foreach (0 .. $#$components) {
-                    $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]);
-                }
-                
-                $fh->print("\n");
-                my $ligatures = $_->{'ligatures'};
-                foreach (0 .. $#$ligatures) {
-                    $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]);
-                }
-            }
-            
-            elsif ($type == 4) {    # non-contextual
-                my $lookup = $_->{'lookup'};
-                $fh->printf("\t\tLookup format %d\n", $_->{'format'});
-                if (defined $lookup) {
-                    foreach (sort { $a <=> $b } keys %$lookup) {
-                        $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]);
-                    }
-                }
-            }
-            
-            elsif ($type == 5) {    # insertion
-                print_classes_($fh, $_, $post);
-                
-                $fh->print("\n");
-                my $states = $_->{'states'};
-                foreach (0 .. $#$states) {
-                    $fh->printf("\t\tState %d:", $_);
-                    my $state = $states->[$_];
-                    foreach (@$state) {
-                        my $flags;
-                        $flags .= "!" if ($_->{'flags'} & 0x4000);
-                        $flags .= "*" if ($_->{'flags'} & 0x8000);
-                        my $actions = $_->{'actions'};
-                        $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
-                    }
-                    $fh->print("\n");
-                }
-
-                $fh->print("\n");
-                my $insertLists = $_->{'insertLists'};
-                foreach (0 .. $#$insertLists) {
-                    my $insertList = $insertLists->[$_];
-                    $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList));
-                }
-            }
-            
-            else {
-                # unknown
-            }
-        }
-    }
-}
-
-sub print_classes_
-{
-    my ($fh, $subtable, $post) = @_;
-    
-    my $classes = $subtable->{'classes'};
-    foreach (0 .. $#$classes) {
-        my $class = $classes->[$_];
-        if (defined $class) {
-            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
-        }
-    }
-}
-
-sub subtable_type_
-{
-    my ($val) = @_;
-    my ($res);
-    
-    my @types =    (
-                    'Rearrangement',
-                    'Contextual',
-                    'Ligature',
-                    undef,
-                    'Non-contextual',
-                    'Insertion',
-                );
-    $res = $types[$val] or ('Undefined (' . $val . ')');
-    
-    $res;
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::OldMort;
+
+=head1 NAME
+
+Font::TTF::OldMort - Glyph Metamorphosis table in a font
+
+=head1 DESCRIPTION
+
+=head1 INSTANCE VARIABLES
+
+=item version
+
+table version number (Fixed: currently 1.0)
+
+=item chains
+
+list of metamorphosis chains, each of which has its own fields:
+
+=over
+
+=item defaultFlags
+
+chain's default subfeature flags (UInt32)
+
+=item featureEntries
+
+list of feature entries, each of which has fields:
+
+=over
+
+=item type
+
+=item setting
+
+=item enable
+
+=item disable
+
+=back
+
+=item subtables
+
+list of metamorphosis subtables, each of which has fields:
+
+=over
+
+=item type
+
+subtable type (0: rearrangement; 1: contextual substitution; 2: ligature;
+4: non-contextual substitution; 5: insertion)
+
+=item direction
+
+processing direction ('LR' or 'RL')
+
+=item orientation
+
+applies to text in which orientation ('VH', 'V', or 'H')
+
+=item subFeatureFlags
+
+the subfeature flags controlling whether the table is used (UInt32)
+
+=back
+
+Further fields depend on the type of subtable:
+
+=over
+
+Rearrangement table:
+
+=over
+
+=item classes
+
+array of lists of glyphs
+
+=item states
+
+array of arrays of hashes{'nextState', 'flags'}
+
+=back
+
+Contextual substitution table:
+
+=over
+
+=item classes
+
+array of lists of glyphs
+
+=item states
+
+array of array of hashes{'nextState', 'flags', 'actions'}, where C<actions>
+is an array of two elements which are offsets to be added to [marked, current]
+glyph to get index into C<mappings> (or C<undef> if no mapping to be applied)
+
+=item mappings
+
+list of glyph codes mapped to through the state table mappings
+
+=back
+
+Ligature table:
+
+Non-contextual substitution table:
+
+Insertion table:
+
+=back
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $fh, $numChains);
+    
+    $self->SUPER::read or return $self;
+
+    $fh = $self->{' INFILE'};
+
+    $fh->read($dat, 8);
+    ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat);
+    
+    my $chains = [];
+    foreach (1 .. $numChains) {
+        my $chainStart = $fh->tell();
+        $fh->read($dat, 12);
+        my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat);
+        my $featureEntries = [];
+        foreach (1 .. $nFeatureEntries) {
+            $fh->read($dat, 12);
+            my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat);
+            push @$featureEntries,    {
+                                        'type'        => $featureType,
+                                        'setting'    => $featureSetting,
+                                        'enable'    => $enableFlags,
+                                        'disable'    => $disableFlags
+                                    };
+        }
+        my $subtables = [];
+        foreach (1 .. $nSubtables) {
+            my $subtableStart = $fh->tell();
+            $fh->read($dat, 8);
+            my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat);
+            my $type = $coverage & 0x0007;
+
+            my $subtable =    {
+                                'type'                => $type,
+                                'direction'            => (($coverage & 0x4000) ? 'RL' : 'LR'),
+                                'orientation'        => (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'),
+                                'subFeatureFlags'    => $subFeatureFlags
+                            };
+
+            if ($type == 0) {    # rearrangement
+                my ($classes, $states) = AAT_read_state_table($fh, 0);
+                $subtable->{'classes'} = $classes;
+                $subtable->{'states'} = $states;
+            }
+
+            elsif ($type == 1) {    # contextual
+                my $stateTableStart = $fh->tell();
+                my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
+
+                $fh->seek($stateTableStart, IO::File::SEEK_SET);
+                $fh->read($dat, 10);
+                my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat);
+                my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $length - 8];
+
+                foreach (@$entries) {
+                    my $actions = $_->{'actions'};
+                    foreach (@$actions) {
+                        $_ = $_ ? $_ - ($mappingTables / 2) : undef;
+                    }
+                }
+                
+                $subtable->{'classes'} = $classes;
+                $subtable->{'states'} = $states;
+                $subtable->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))];
+            }
+
+            elsif ($type == 2) {    # ligature
+                my $stateTableStart = $fh->tell();
+                my ($classes, $states, $entries) = AAT_read_state_table($fh, 0);
+                
+                $fh->seek($stateTableStart, IO::File::SEEK_SET);
+                $fh->read($dat, 14);
+                my ($stateSize, $classTable, $stateArray, $entryTable,
+                    $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat);
+                my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $length - 8];
+                
+                my %actions;
+                my $actionLists;
+                foreach (@$entries) {
+                    my $offset = $_->{'flags'} & 0x3fff;
+                    $_->{'flags'} &= ~0x3fff;
+                    if ($offset != 0) {
+                        if (not defined $actions{$offset}) {
+                            $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET);
+                            my $actionList;
+                            while (1) {
+                                $fh->read($dat, 4);
+                                my $action = unpack("N", $dat);
+                                my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff));
+                                $component -= 0x40000000 if $component > 0x1fffffff;
+                                $component -= $componentTable / 2;
+                                push @$actionList, { 'store' => $store, 'component' => $component };
+                                last if $last;
+                            }
+                            push @$actionLists, $actionList;
+                            $actions{$offset} = $#$actionLists;
+                        }
+                        $_->{'actions'} = $actions{$offset};
+                    }
+                }
+                
+                $subtable->{'componentTable'} = $componentTable;
+                my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))];
+                foreach (@$components) {
+                    $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable;
+                }
+                $subtable->{'components'} = $components;
+                
+                $subtable->{'ligatureTable'} = $ligatureTable;
+                $subtable->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))];
+                
+                $subtable->{'classes'} = $classes;
+                $subtable->{'states'} = $states;
+                $subtable->{'actionLists'} = $actionLists;
+            }
+
+            elsif ($type == 4) {    # non-contextual
+                my ($format, $lookup) = AAT_read_lookup($fh, 2, $length - 8, undef);
+                $subtable->{'format'} = $format;
+                $subtable->{'lookup'} = $lookup;
+            }
+
+            elsif ($type == 5) {    # insertion
+                my $stateTableStart = $fh->tell();
+                my ($classes, $states, $entries) = AAT_read_state_table($fh, 2);
+                
+                my %insertListHash;
+                my $insertLists;
+                foreach (@$entries) {
+                    my $flags = $_->{'flags'};
+                    my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f));
+                    my $actions = $_->{'actions'};
+                    foreach (0 .. 1) {
+                        if ($insertCount[$_] > 0) {
+                            $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET);
+                            $fh->read($dat, $insertCount[$_] * 2);
+                            if (not defined $insertListHash{$dat}) {
+                                push @$insertLists, [unpack("n*", $dat)];
+                                $insertListHash{$dat} = $#$insertLists;
+                            }
+                            $actions->[$_] = $insertListHash{$dat};
+                        }
+                        else {
+                            $actions->[$_] = undef;
+                        }
+                    }
+                }
+
+                $subtable->{'classes'} = $classes;
+                $subtable->{'states'} = $states;
+                $subtable->{'insertLists'} = $insertLists;
+            }
+
+            else {
+                die "unknown subtable type";
+            }
+            
+            push @$subtables, $subtable;
+            $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
+        }
+        
+        push @$chains,    {
+                            'defaultFlags'        => $defaultFlags,
+                            'featureEntries'    => $featureEntries,
+                            'subtables'            => $subtables
+                        };
+        $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
+    }
+
+    $self->{'chains'} = $chains;
+
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    my $chains = $self->{'chains'};
+    $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains));
+
+    foreach (@$chains) {
+        my $chainStart = $fh->tell();
+        my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'});
+        $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length
+        
+        foreach (@$featureEntries) {
+            $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}));
+        }
+        
+        foreach (@$subtables) {
+            my $subtableStart = $fh->tell();
+            my $type = $_->{'type'};
+            my $coverage = $type;
+            $coverage += 0x4000 if $_->{'direction'} eq 'RL';
+            $coverage += 0x2000 if $_->{'orientation'} eq 'VH';
+            $coverage += 0x8000 if $_->{'orientation'} eq 'V';
+            
+            $fh->print(TTF_Pack("SSL", 0, $coverage, $_->{'subFeatureFlags'}));    # placeholder for length
+            
+            if ($type == 0) {    # rearrangement
+                AAT_write_state_table($fh, $_->{'classes'}, $_->{'states'}, 0);
+            }
+            
+            elsif ($type == 1) {    # contextual
+                my $stHeader = $fh->tell();
+                $fh->print(pack("nnnnn", (0) x 5));    # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables
+                
+                my $classTable = $fh->tell() - $stHeader;
+                my $classes = $_->{'classes'};
+                AAT_write_classes($fh, $classes);
+                
+                my $stateArray = $fh->tell() - $stHeader;
+                my $states = $_->{'states'};
+                my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, 
+                        sub {
+                            my $actions = $_->{'actions'};
+                            ( $_->{'flags'}, @$actions )
+                        }
+                    );
+
+                my $entryTable = $fh->tell() - $stHeader;
+                my $offset = ($entryTable + 8 * @$entries) / 2;
+                foreach (@$entries) {
+                    my ($nextState, $flags, @parts) = split /,/;
+                    $fh->print(pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts));
+                }
+
+                my $mappingTables = $fh->tell() - $stHeader;
+                my $mappings = $_->{'mappings'};
+                $fh->print(pack("n*", @$mappings));
+                
+                my $loc = $fh->tell();
+                $fh->seek($stHeader, IO::File::SEEK_SET);
+                $fh->print(pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables));
+                $fh->seek($loc, IO::File::SEEK_SET);
+            }
+            
+            elsif ($type == 2) {    # ligature
+                my $stHeader = $fh->tell();
+                $fh->print(pack("nnnnnnn", (0) x 7));    # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures
+            
+                my $classTable = $fh->tell() - $stHeader;
+                my $classes = $_->{'classes'};
+                AAT_write_classes($fh, $classes);
+                
+                my $stateArray = $fh->tell() - $stHeader;
+                my $states = $_->{'states'};
+                
+                my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states,
+                        sub {
+                            ( $_->{'flags'} & 0xc000, $_->{'actions'} )
+                        }
+                    );
+                
+                my $actionLists = $_->{'actionLists'};
+                my %actionListOffset;
+                my $actionListDataLength = 0;
+                my @actionListEntries;
+                foreach (0 .. $#$entries) {
+                    my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]);
+                    if ($offset eq "") {
+                        $offset = undef;
+                    }
+                    else {
+                        if (defined $actionListOffset{$offset}) {
+                            $offset = $actionListOffset{$offset};
+                        }
+                        else {
+                            $actionListOffset{$offset} = $actionListDataLength;
+                            my $list = $actionLists->[$offset];
+                            $actionListDataLength += 4 * @$list;
+                            push @actionListEntries, $list;
+                            $offset = $actionListOffset{$offset};
+                        }
+                    }
+                    $entries->[$_] = [ $nextState, $flags, $offset ];
+                }
+                my $entryTable = $fh->tell() - $stHeader;
+                my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3;
+                foreach (@$entries) {
+                    $_->[2] += $ligActionLists if defined $_->[2];
+                    $fh->print(pack("nn", $_->[0], $_->[1] + $_->[2]));
+                }
+                $fh->print(pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4)));
+                
+                die "internal error" if $fh->tell() != $ligActionLists + $stHeader;
+                
+                my $componentTable = $fh->tell() - $stHeader + $actionListDataLength;
+                my $actionList;
+                foreach $actionList (@actionListEntries) {
+                    foreach (0 .. $#$actionList) {
+                        my $action = $actionList->[$_];
+                        my $val = $action->{'component'} + $componentTable / 2;
+                        $val += 0x40000000 if $val < 0;
+                        $val &= 0x3fffffff;
+                        $val |= 0x40000000 if $action->{'store'};
+                        $val |= 0x80000000 if $_ == $#$actionList;
+                        $fh->print(pack("N", $val));
+                    }
+                }
+
+                die "internal error" if $fh->tell() != $componentTable + $stHeader;
+
+                my $components = $_->{'components'};
+                my $ligatureTable = $componentTable + @$components * 2;
+                $fh->print(pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components));
+                
+                my $ligatures = $_->{'ligatures'};
+                $fh->print(pack("n*", @$ligatures));
+                
+                my $loc = $fh->tell();
+                $fh->seek($stHeader, IO::File::SEEK_SET);
+                $fh->print(pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable));
+                $fh->seek($loc, IO::File::SEEK_SET);
+            }
+            
+            elsif ($type == 4) {    # non-contextual
+                AAT_write_lookup($fh, $_->{'format'}, $_->{'lookup'}, 2, undef);
+            }
+            
+            elsif ($type == 5) {    # insertion
+            }
+            
+            else {
+                die "unknown subtable type";
+            }
+            
+            my $length = $fh->tell() - $subtableStart;
+            my $padBytes = (4 - ($length & 3)) & 3;
+            $fh->print(pack("C*", (0) x $padBytes));
+            $length += $padBytes;
+            $fh->seek($subtableStart, IO::File::SEEK_SET);
+            $fh->print(pack("n", $length));
+            $fh->seek($subtableStart + $length, IO::File::SEEK_SET);
+        }
+        
+        my $chainLength = $fh->tell() - $chainStart;
+        $fh->seek($chainStart + 4, IO::File::SEEK_SET);
+        $fh->print(pack("N", $chainLength));
+        $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET);
+    }
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    
+    $self->read;
+    my $feat = $self->{' PARENT'}->{'feat'};
+    $feat->read;
+    my $post = $self->{' PARENT'}->{'post'};
+    $post->read;
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $fh->printf("version %f\n", $self->{'version'});
+    
+    my $chains = $self->{'chains'};
+    foreach (@$chains) {
+        my $defaultFlags = $_->{'defaultFlags'};
+        $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags);
+        
+        my $featureEntries = $_->{'featureEntries'};
+        foreach (@$featureEntries) {
+            $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n",
+                        $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'},
+                        $feat->settingName($_->{'type'}, $_->{'setting'}));
+        }
+        
+        my $subtables = $_->{'subtables'};
+        foreach (@$subtables) {
+            my $type = $_->{'type'};
+            my $subFeatureFlags = $_->{'subFeatureFlags'};
+            $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n",
+                        subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags,
+                        "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"),
+                        join(", ",
+                            map {
+                                join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) )
+                            } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries
+                        ) );
+            
+            if ($type == 0) {    # rearrangement
+                print_classes_($fh, $_, $post);
+
+                $fh->print("\n");
+                my $states = $_->{'states'};
+                my @verbs = (    "0", "Ax->xA", "xD->Dx", "AxD->DxA",
+                                "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx",
+                                "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA",
+                                "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA");
+                foreach (0 .. $#$states) {
+                    $fh->printf("\t\tState %d:", $_);
+                    my $state = $states->[$_];
+                    foreach (@$state) {
+                        my $flags;
+                        $flags .= "!" if ($_->{'flags'} & 0x4000);
+                        $flags .= "<" if ($_->{'flags'} & 0x8000);
+                        $flags .= ">" if ($_->{'flags'} & 0x2000);
+                        $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]);
+                    }
+                    $fh->print("\n");
+                }
+            }
+            
+            elsif ($type == 1) {    # contextual
+                print_classes_($fh, $_, $post);
+                
+                $fh->print("\n");
+                my $states = $_->{'states'};
+                foreach (0 .. $#$states) {
+                    $fh->printf("\t\tState %d:", $_);
+                    my $state = $states->[$_];
+                    foreach (@$state) {
+                        my $flags;
+                        $flags .= "!" if ($_->{'flags'} & 0x4000);
+                        $flags .= "*" if ($_->{'flags'} & 0x8000);
+                        my $actions = $_->{'actions'};
+                        $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
+                    }
+                    $fh->print("\n");
+                }
+
+                $fh->print("\n");
+                my $mappings = $_->{'mappings'};
+                foreach (0 .. $#$mappings) {
+                    $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]);
+                }
+            }
+            
+            elsif ($type == 2) {    # ligature
+                print_classes_($fh, $_, $post);
+                
+                $fh->print("\n");
+                my $states = $_->{'states'};
+                foreach (0 .. $#$states) {
+                    $fh->printf("\t\tState %d:", $_);
+                    my $state = $states->[$_];
+                    foreach (@$state) {
+                        my $flags;
+                        $flags .= "!" if ($_->{'flags'} & 0x4000);
+                        $flags .= "*" if ($_->{'flags'} & 0x8000);
+                        $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "=");
+                    }
+                    $fh->print("\n");
+                }
+
+                $fh->print("\n");
+                my $actionLists = $_->{'actionLists'};
+                foreach (0 .. $#$actionLists) {
+                    $fh->printf("\t\tList %d:\t", $_);
+                    my $actionList = $actionLists->[$_];
+                    $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList));
+                }
+
+                my $ligatureTable = $_->{'ligatureTable'};
+
+                $fh->print("\n");
+                my $components = $_->{'components'};
+                foreach (0 .. $#$components) {
+                    $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]);
+                }
+                
+                $fh->print("\n");
+                my $ligatures = $_->{'ligatures'};
+                foreach (0 .. $#$ligatures) {
+                    $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]);
+                }
+            }
+            
+            elsif ($type == 4) {    # non-contextual
+                my $lookup = $_->{'lookup'};
+                $fh->printf("\t\tLookup format %d\n", $_->{'format'});
+                if (defined $lookup) {
+                    foreach (sort { $a <=> $b } keys %$lookup) {
+                        $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]);
+                    }
+                }
+            }
+            
+            elsif ($type == 5) {    # insertion
+                print_classes_($fh, $_, $post);
+                
+                $fh->print("\n");
+                my $states = $_->{'states'};
+                foreach (0 .. $#$states) {
+                    $fh->printf("\t\tState %d:", $_);
+                    my $state = $states->[$_];
+                    foreach (@$state) {
+                        my $flags;
+                        $flags .= "!" if ($_->{'flags'} & 0x4000);
+                        $flags .= "*" if ($_->{'flags'} & 0x8000);
+                        my $actions = $_->{'actions'};
+                        $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions);
+                    }
+                    $fh->print("\n");
+                }
+
+                $fh->print("\n");
+                my $insertLists = $_->{'insertLists'};
+                foreach (0 .. $#$insertLists) {
+                    my $insertList = $insertLists->[$_];
+                    $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList));
+                }
+            }
+            
+            else {
+                # unknown
+            }
+        }
+    }
+}
+
+sub print_classes_
+{
+    my ($fh, $subtable, $post) = @_;
+    
+    my $classes = $subtable->{'classes'};
+    foreach (0 .. $#$classes) {
+        my $class = $classes->[$_];
+        if (defined $class) {
+            $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class));
+        }
+    }
+}
+
+sub subtable_type_
+{
+    my ($val) = @_;
+    my ($res);
+    
+    my @types =    (
+                    'Rearrangement',
+                    'Contextual',
+                    'Ligature',
+                    undef,
+                    'Non-contextual',
+                    'Insertion',
+                );
+    $res = $types[$val] or ('Undefined (' . $val . ')');
+    
+    $res;
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/PCLT.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/PCLT.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/PCLT.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,121 +1,121 @@
-package Font::TTF::PCLT;
-
-=head1 NAME
-
-Font::TTF::Pclt - PCLT TrueType font table
-
-=head1 DESCRIPTION
-
-The PCLT table holds various pieces HP-PCL specific information. Information
-here is generally not used by other software, except for the xHeight and
-CapHeight which are stored here (if the table exists in a font).
-
-=head1 INSTANCE VARIABLES
-
-Only from table and the standard:
-
-    version
-    FontNumber
-    Pitch
-    xHeight
-    Style
-    TypeFamily
-    CapHeight
-    SymbolSet
-    Typeface
-    CharacterComplement
-    FileName
-    StrokeWeight
-    WidthType
-    SerifStyle
-
-Notice that C<Typeface>, C<CharacterComplement> and C<FileName> return arrays
-of unsigned characters of the appropriate length
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-
-require Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'version' => 'f',
-    'FontNumber' => 'L',
-    'Pitch' => 'S',
-    'xHeight' => 'S',
-    'Style' => 'S',
-    'TypeFamily' => 'S',
-    'CapHeight' => 'S',
-    'SymbolSet' => 'S',
-    'Typeface' => 'C16',
-    'CharacterComplement' => 'C8',
-    'FileName' => 'C6',
-    'StrokeWeight' => 'C',
-    'WidthType' => 'C',
-    'SerifStyle' => 'c');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory thanks to some utility functions
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read || return $self;
-
-    init unless defined $fields{'xHeight'};
-    $self->{' INFILE'}->read($dat, 54);
-
-    TTF_Read_Fields($self, $dat, \%fields);
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-    $fh->print(TTF_Out_Fields($self, \%fields, 54));
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::PCLT;
+
+=head1 NAME
+
+Font::TTF::Pclt - PCLT TrueType font table
+
+=head1 DESCRIPTION
+
+The PCLT table holds various pieces HP-PCL specific information. Information
+here is generally not used by other software, except for the xHeight and
+CapHeight which are stored here (if the table exists in a font).
+
+=head1 INSTANCE VARIABLES
+
+Only from table and the standard:
+
+    version
+    FontNumber
+    Pitch
+    xHeight
+    Style
+    TypeFamily
+    CapHeight
+    SymbolSet
+    Typeface
+    CharacterComplement
+    FileName
+    StrokeWeight
+    WidthType
+    SerifStyle
+
+Notice that C<Typeface>, C<CharacterComplement> and C<FileName> return arrays
+of unsigned characters of the appropriate length
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+
+require Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'version' => 'f',
+    'FontNumber' => 'L',
+    'Pitch' => 'S',
+    'xHeight' => 'S',
+    'Style' => 'S',
+    'TypeFamily' => 'S',
+    'CapHeight' => 'S',
+    'SymbolSet' => 'S',
+    'Typeface' => 'C16',
+    'CharacterComplement' => 'C8',
+    'FileName' => 'C6',
+    'StrokeWeight' => 'C',
+    'WidthType' => 'C',
+    'SerifStyle' => 'c');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory thanks to some utility functions
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read || return $self;
+
+    init unless defined $fields{'xHeight'};
+    $self->{' INFILE'}->read($dat, 54);
+
+    TTF_Read_Fields($self, $dat, \%fields);
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+    $fh->print(TTF_Out_Fields($self, \%fields, 54));
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/PSNames.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/PSNames.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/PSNames.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,910 +1,4439 @@
-package Font::TTF::PSNames;
-
-use strict;
-use vars qw(%names %doubles);
-
-%names = (
-    '0020' => 'space',
-    '0021' => 'exclam',
-    '0022' => 'quotedbl',
-    '0023' => 'numbersign',
-    '0024' => 'dollar',
-    '0025' => 'percent',
-    '0026' => 'ampersand',
-    '0027' => 'quotesingle',
-    '0028' => 'parenleft',
-    '0029' => 'parenright',
-    '002A' => 'asterisk',
-    '002B' => 'plus',
-    '002C' => 'comma',
-    '002D' => 'hyphen',
-    '002E' => 'period',
-    '002F' => 'slash',
-    '0030' => 'zero',
-    '0031' => 'one',
-    '0032' => 'two',
-    '0033' => 'three',
-    '0034' => 'four',
-    '0035' => 'five',
-    '0036' => 'six',
-    '0037' => 'seven',
-    '0038' => 'eight',
-    '0039' => 'nine',
-    '003A' => 'colon',
-    '003B' => 'semicolon',
-    '003C' => 'less',
-    '003D' => 'equal',
-    '003E' => 'greater',
-    '003F' => 'question',
-    '0040' => 'at',
-    '0041' => 'A',
-    '0042' => 'B',
-    '0043' => 'C',
-    '0044' => 'D',
-    '0045' => 'E',
-    '0046' => 'F',
-    '0047' => 'G',
-    '0048' => 'H',
-    '0049' => 'I',
-    '004A' => 'J',
-    '004B' => 'K',
-    '004C' => 'L',
-    '004D' => 'M',
-    '004E' => 'N',
-    '004F' => 'O',
-    '0050' => 'P',
-    '0051' => 'Q',
-    '0052' => 'R',
-    '0053' => 'S',
-    '0054' => 'T',
-    '0055' => 'U',
-    '0056' => 'V',
-    '0057' => 'W',
-    '0058' => 'X',
-    '0059' => 'Y',
-    '005A' => 'Z',
-    '005B' => 'bracketleft',
-    '005C' => 'backslash',
-    '005D' => 'bracketright',
-    '005E' => 'asciicircum',
-    '005F' => 'underscore',
-    '0060' => 'grave',
-    '0061' => 'a',
-    '0062' => 'b',
-    '0063' => 'c',
-    '0064' => 'd',
-    '0065' => 'e',
-    '0066' => 'f',
-    '0067' => 'g',
-    '0068' => 'h',
-    '0069' => 'i',
-    '006A' => 'j',
-    '006B' => 'k',
-    '006C' => 'l',
-    '006D' => 'm',
-    '006E' => 'n',
-    '006F' => 'o',
-    '0070' => 'p',
-    '0071' => 'q',
-    '0072' => 'r',
-    '0073' => 's',
-    '0074' => 't',
-    '0075' => 'u',
-    '0076' => 'v',
-    '0077' => 'w',
-    '0078' => 'x',
-    '0079' => 'y',
-    '007A' => 'z',
-    '007B' => 'braceleft',
-    '007C' => 'bar',
-    '007D' => 'braceright',
-    '007E' => 'asciitilde',
-#    '00A0' => 'space',
-    '00A1' => 'exclamdown',
-    '00A2' => 'cent',
-    '00A3' => 'sterling',
-    '00A4' => 'currency',
-    '00A5' => 'yen',
-    '00A6' => 'brokenbar',
-    '00A7' => 'section',
-    '00A8' => 'dieresis',
-    '00A9' => 'copyright',
-    '00AA' => 'ordfeminine',
-    '00AB' => 'guillemotleft',
-    '00AC' => 'logicalnot',
-#    '00AD' => 'hyphen',
-    '00AE' => 'registered',
-    '00AF' => 'macron',
-    '00B0' => 'degree',
-    '00B1' => 'plusminus',
-    '00B2' => 'twosuperior',
-    '00B3' => 'threesuperior',
-    '00B4' => 'acute',
-    '00B5' => 'mu',
-    '00B6' => 'paragraph',
-    '00B7' => 'periodcentered',
-    '00B8' => 'cedilla',
-    '00B9' => 'onesuperior',
-    '00BA' => 'ordmasculine',
-    '00BB' => 'guillemotright',
-    '00BC' => 'onequarter',
-    '00BD' => 'onehalf',
-    '00BE' => 'threequarters',
-    '00BF' => 'questiondown',
-    '00C0' => 'Agrave',
-    '00C1' => 'Aacute',
-    '00C2' => 'Acircumflex',
-    '00C3' => 'Atilde',
-    '00C4' => 'Adieresis',
-    '00C5' => 'Aring',
-    '00C6' => 'AE',
-    '00C7' => 'Ccedilla',
-    '00C8' => 'Egrave',
-    '00C9' => 'Eacute',
-    '00CA' => 'Ecircumflex',
-    '00CB' => 'Edieresis',
-    '00CC' => 'Igrave',
-    '00CD' => 'Iacute',
-    '00CE' => 'Icircumflex',
-    '00CF' => 'Idieresis',
-    '00D0' => 'Eth',
-    '00D1' => 'Ntilde',
-    '00D2' => 'Ograve',
-    '00D3' => 'Oacute',
-    '00D4' => 'Ocircumflex',
-    '00D5' => 'Otilde',
-    '00D6' => 'Odieresis',
-    '00D7' => 'multiply',
-    '00D8' => 'Oslash',
-    '00D9' => 'Ugrave',
-    '00DA' => 'Uacute',
-    '00DB' => 'Ucircumflex',
-    '00DC' => 'Udieresis',
-    '00DD' => 'Yacute',
-    '00DE' => 'Thorn',
-    '00DF' => 'germandbls',
-    '00E0' => 'agrave',
-    '00E1' => 'aacute',
-    '00E2' => 'acircumflex',
-    '00E3' => 'atilde',
-    '00E4' => 'adieresis',
-    '00E5' => 'aring',
-    '00E6' => 'ae',
-    '00E7' => 'ccedilla',
-    '00E8' => 'egrave',
-    '00E9' => 'eacute',
-    '00EA' => 'ecircumflex',
-    '00EB' => 'edieresis',
-    '00EC' => 'igrave',
-    '00ED' => 'iacute',
-    '00EE' => 'icircumflex',
-    '00EF' => 'idieresis',
-    '00F0' => 'eth',
-    '00F1' => 'ntilde',
-    '00F2' => 'ograve',
-    '00F3' => 'oacute',
-    '00F4' => 'ocircumflex',
-    '00F5' => 'otilde',
-    '00F6' => 'odieresis',
-    '00F7' => 'divide',
-    '00F8' => 'oslash',
-    '00F9' => 'ugrave',
-    '00FA' => 'uacute',
-    '00FB' => 'ucircumflex',
-    '00FC' => 'udieresis',
-    '00FD' => 'yacute',
-    '00FE' => 'thorn',
-    '00FF' => 'ydieresis',
-    '0100' => 'Amacron',
-    '0101' => 'amacron',
-    '0102' => 'Abreve',
-    '0103' => 'abreve',
-    '0104' => 'Aogonek',
-    '0105' => 'aogonek',
-    '0106' => 'Cacute',
-    '0107' => 'cacute',
-    '0108' => 'Ccircumflex',
-    '0109' => 'ccircumflex',
-    '010A' => 'Cdotaccent',
-    '010B' => 'cdotaccent',
-    '010C' => 'Ccaron',
-    '010D' => 'ccaron',
-    '010E' => 'Dcaron',
-    '010F' => 'dcaron',
-    '0110' => 'Dcroat',
-    '0111' => 'dcroat',
-    '0112' => 'Emacron',
-    '0113' => 'emacron',
-    '0114' => 'Ebreve',
-    '0115' => 'ebreve',
-    '0116' => 'Edotaccent',
-    '0117' => 'edotaccent',
-    '0118' => 'Eogonek',
-    '0119' => 'eogonek',
-    '011A' => 'Ecaron',
-    '011B' => 'ecaron',
-    '011C' => 'Gcircumflex',
-    '011D' => 'gcircumflex',
-    '011E' => 'Gbreve',
-    '011F' => 'gbreve',
-    '0120' => 'Gdotaccent',
-    '0121' => 'gdotaccent',
-    '0122' => 'Gcommaaccent',
-    '0123' => 'gcommaaccent',
-    '0124' => 'Hcircumflex',
-    '0125' => 'hcircumflex',
-    '0126' => 'Hbar',
-    '0127' => 'hbar',
-    '0128' => 'Itilde',
-    '0129' => 'itilde',
-    '012A' => 'Imacron',
-    '012B' => 'imacron',
-    '012C' => 'Ibreve',
-    '012D' => 'ibreve',
-    '012E' => 'Iogonek',
-    '012F' => 'iogonek',
-    '0130' => 'Idotaccent',
-    '0131' => 'dotlessi',
-    '0132' => 'IJ',
-    '0133' => 'ij',
-    '0134' => 'Jcircumflex',
-    '0135' => 'jcircumflex',
-    '0136' => 'Kcommaaccent',
-    '0137' => 'kcommaaccent',
-    '0138' => 'kgreenlandic',
-    '0139' => 'Lacute',
-    '013A' => 'lacute',
-    '013B' => 'Lcommaaccent',
-    '013C' => 'lcommaaccent',
-    '013D' => 'Lcaron',
-    '013E' => 'lcaron',
-    '013F' => 'Ldot',
-    '0140' => 'ldot',
-    '0141' => 'Lslash',
-    '0142' => 'lslash',
-    '0143' => 'Nacute',
-    '0144' => 'nacute',
-    '0145' => 'Ncommaaccent',
-    '0146' => 'ncommaaccent',
-    '0147' => 'Ncaron',
-    '0148' => 'ncaron',
-    '0149' => 'napostrophe',
-    '014A' => 'Eng',
-    '014B' => 'eng',
-    '014C' => 'Omacron',
-    '014D' => 'omacron',
-    '014E' => 'Obreve',
-    '014F' => 'obreve',
-    '0150' => 'Ohungarumlaut',
-    '0151' => 'ohungarumlaut',
-    '0152' => 'OE',
-    '0153' => 'oe',
-    '0154' => 'Racute',
-    '0155' => 'racute',
-    '0156' => 'Rcommaaccent',
-    '0157' => 'rcommaaccent',
-    '0158' => 'Rcaron',
-    '0159' => 'rcaron',
-    '015A' => 'Sacute',
-    '015B' => 'sacute',
-    '015C' => 'Scircumflex',
-    '015D' => 'scircumflex',
-    '015E' => 'Scedilla',
-    '015F' => 'scedilla',
-    '0160' => 'Scaron',
-    '0161' => 'scaron',
-    '0162' => 'Tcommaaccent',
-    '0163' => 'tcommaaccent',
-    '0164' => 'Tcaron',
-    '0165' => 'tcaron',
-    '0166' => 'Tbar',
-    '0167' => 'tbar',
-    '0168' => 'Utilde',
-    '0169' => 'utilde',
-    '016A' => 'Umacron',
-    '016B' => 'umacron',
-    '016C' => 'Ubreve',
-    '016D' => 'ubreve',
-    '016E' => 'Uring',
-    '016F' => 'uring',
-    '0170' => 'Uhungarumlaut',
-    '0171' => 'uhungarumlaut',
-    '0172' => 'Uogonek',
-    '0173' => 'uogonek',
-    '0174' => 'Wcircumflex',
-    '0175' => 'wcircumflex',
-    '0176' => 'Ycircumflex',
-    '0177' => 'ycircumflex',
-    '0178' => 'Ydieresis',
-    '0179' => 'Zacute',
-    '017A' => 'zacute',
-    '017B' => 'Zdotaccent',
-    '017C' => 'zdotaccent',
-    '017D' => 'Zcaron',
-    '017E' => 'zcaron',
-    '017F' => 'longs',
-    '0192' => 'florin',
-    '01A0' => 'Ohorn',
-    '01A1' => 'ohorn',
-    '01AF' => 'Uhorn',
-    '01B0' => 'uhorn',
-    '01E6' => 'Gcaron',
-    '01E7' => 'gcaron',
-    '01FA' => 'Aringacute',
-    '01FB' => 'aringacute',
-    '01FC' => 'AEacute',
-    '01FD' => 'aeacute',
-    '01FE' => 'Oslashacute',
-    '01FF' => 'oslashacute',
-    '0218' => 'Scommaaccent',
-    '0219' => 'scommaaccent',
-#    '021A' => 'Tcommaaccent',
-#    '021B' => 'tcommaaccent',
-    '02BC' => 'afii57929',
-    '02BD' => 'afii64937',
-    '02C6' => 'circumflex',
-    '02C7' => 'caron',
-#    '02C9' => 'macron',
-    '02D8' => 'breve',
-    '02D9' => 'dotaccent',
-    '02DA' => 'ring',
-    '02DB' => 'ogonek',
-    '02DC' => 'tilde',
-    '02DD' => 'hungarumlaut',
-    '0300' => 'gravecomb',
-    '0301' => 'acutecomb',
-    '0303' => 'tildecomb',
-    '0309' => 'hookabovecomb',
-    '0323' => 'dotbelowcomb',
-    '0384' => 'tonos',
-    '0385' => 'dieresistonos',
-    '0386' => 'Alphatonos',
-    '0387' => 'anoteleia',
-    '0388' => 'Epsilontonos',
-    '0389' => 'Etatonos',
-    '038A' => 'Iotatonos',
-    '038C' => 'Omicrontonos',
-    '038E' => 'Upsilontonos',
-    '038F' => 'Omegatonos',
-    '0390' => 'iotadieresistonos',
-    '0391' => 'Alpha',
-    '0392' => 'Beta',
-    '0393' => 'Gamma',
-#    '0394' => 'Delta',
-    '0395' => 'Epsilon',
-    '0396' => 'Zeta',
-    '0397' => 'Eta',
-    '0398' => 'Theta',
-    '0399' => 'Iota',
-    '039A' => 'Kappa',
-    '039B' => 'Lambda',
-    '039C' => 'Mu',
-    '039D' => 'Nu',
-    '039E' => 'Xi',
-    '039F' => 'Omicron',
-    '03A0' => 'Pi',
-    '03A1' => 'Rho',
-    '03A3' => 'Sigma',
-    '03A4' => 'Tau',
-    '03A5' => 'Upsilon',
-    '03A6' => 'Phi',
-    '03A7' => 'Chi',
-    '03A8' => 'Psi',
-#    '03A9' => 'Omega',
-    '03AA' => 'Iotadieresis',
-    '03AB' => 'Upsilondieresis',
-    '03AC' => 'alphatonos',
-    '03AD' => 'epsilontonos',
-    '03AE' => 'etatonos',
-    '03AF' => 'iotatonos',
-    '03B0' => 'upsilondieresistonos',
-    '03B1' => 'alpha',
-    '03B2' => 'beta',
-    '03B3' => 'gamma',
-    '03B4' => 'delta',
-    '03B5' => 'epsilon',
-    '03B6' => 'zeta',
-    '03B7' => 'eta',
-    '03B8' => 'theta',
-    '03B9' => 'iota',
-    '03BA' => 'kappa',
-    '03BB' => 'lambda',
-#    '03BC' => 'mu',
-    '03BD' => 'nu',
-    '03BE' => 'xi',
-    '03BF' => 'omicron',
-    '03C0' => 'pi',
-    '03C1' => 'rho',
-    '03C2' => 'sigma1',
-    '03C3' => 'sigma',
-    '03C4' => 'tau',
-    '03C5' => 'upsilon',
-    '03C6' => 'phi',
-    '03C7' => 'chi',
-    '03C8' => 'psi',
-    '03C9' => 'omega',
-    '03CA' => 'iotadieresis',
-    '03CB' => 'upsilondieresis',
-    '03CC' => 'omicrontonos',
-    '03CD' => 'upsilontonos',
-    '03CE' => 'omegatonos',
-    '03D1' => 'theta1',
-    '03D2' => 'Upsilon1',
-    '03D5' => 'phi1',
-    '03D6' => 'omega1',
-    '0401' => 'afii10023',
-    '0402' => 'afii10051',
-    '0403' => 'afii10052',
-    '0404' => 'afii10053',
-    '0405' => 'afii10054',
-    '0406' => 'afii10055',
-    '0407' => 'afii10056',
-    '0408' => 'afii10057',
-    '0409' => 'afii10058',
-    '040A' => 'afii10059',
-    '040B' => 'afii10060',
-    '040C' => 'afii10061',
-    '040E' => 'afii10062',
-    '040F' => 'afii10145',
-    '0410' => 'afii10017',
-    '0411' => 'afii10018',
-    '0412' => 'afii10019',
-    '0413' => 'afii10020',
-    '0414' => 'afii10021',
-    '0415' => 'afii10022',
-    '0416' => 'afii10024',
-    '0417' => 'afii10025',
-    '0418' => 'afii10026',
-    '0419' => 'afii10027',
-    '041A' => 'afii10028',
-    '041B' => 'afii10029',
-    '041C' => 'afii10030',
-    '041D' => 'afii10031',
-    '041E' => 'afii10032',
-    '041F' => 'afii10033',
-    '0420' => 'afii10034',
-    '0421' => 'afii10035',
-    '0422' => 'afii10036',
-    '0423' => 'afii10037',
-    '0424' => 'afii10038',
-    '0425' => 'afii10039',
-    '0426' => 'afii10040',
-    '0427' => 'afii10041',
-    '0428' => 'afii10042',
-    '0429' => 'afii10043',
-    '042A' => 'afii10044',
-    '042B' => 'afii10045',
-    '042C' => 'afii10046',
-    '042D' => 'afii10047',
-    '042E' => 'afii10048',
-    '042F' => 'afii10049',
-    '0430' => 'afii10065',
-    '0431' => 'afii10066',
-    '0432' => 'afii10067',
-    '0433' => 'afii10068',
-    '0434' => 'afii10069',
-    '0435' => 'afii10070',
-    '0436' => 'afii10072',
-    '0437' => 'afii10073',
-    '0438' => 'afii10074',
-    '0439' => 'afii10075',
-    '043A' => 'afii10076',
-    '043B' => 'afii10077',
-    '043C' => 'afii10078',
-    '043D' => 'afii10079',
-    '043E' => 'afii10080',
-    '043F' => 'afii10081',
-    '0440' => 'afii10082',
-    '0441' => 'afii10083',
-    '0442' => 'afii10084',
-    '0443' => 'afii10085',
-    '0444' => 'afii10086',
-    '0445' => 'afii10087',
-    '0446' => 'afii10088',
-    '0447' => 'afii10089',
-    '0448' => 'afii10090',
-    '0449' => 'afii10091',
-    '044A' => 'afii10092',
-    '044B' => 'afii10093',
-    '044C' => 'afii10094',
-    '044D' => 'afii10095',
-    '044E' => 'afii10096',
-    '044F' => 'afii10097',
-    '0451' => 'afii10071',
-    '0452' => 'afii10099',
-    '0453' => 'afii10100',
-    '0454' => 'afii10101',
-    '0455' => 'afii10102',
-    '0456' => 'afii10103',
-    '0457' => 'afii10104',
-    '0458' => 'afii10105',
-    '0459' => 'afii10106',
-    '045A' => 'afii10107',
-    '045B' => 'afii10108',
-    '045C' => 'afii10109',
-    '045E' => 'afii10110',
-    '045F' => 'afii10193',
-    '0462' => 'afii10146',
-    '0463' => 'afii10194',
-    '0472' => 'afii10147',
-    '0473' => 'afii10195',
-    '0474' => 'afii10148',
-    '0475' => 'afii10196',
-    '0490' => 'afii10050',
-    '0491' => 'afii10098',
-    '04D9' => 'afii10846',
-    '05B0' => 'afii57799',
-    '05B1' => 'afii57801',
-    '05B2' => 'afii57800',
-    '05B3' => 'afii57802',
-    '05B4' => 'afii57793',
-    '05B5' => 'afii57794',
-    '05B6' => 'afii57795',
-    '05B7' => 'afii57798',
-    '05B8' => 'afii57797',
-    '05B9' => 'afii57806',
-    '05BB' => 'afii57796',
-    '05BC' => 'afii57807',
-    '05BD' => 'afii57839',
-    '05BE' => 'afii57645',
-    '05BF' => 'afii57841',
-    '05C0' => 'afii57842',
-    '05C1' => 'afii57804',
-    '05C2' => 'afii57803',
-    '05C3' => 'afii57658',
-    '05D0' => 'afii57664',
-    '05D1' => 'afii57665',
-    '05D2' => 'afii57666',
-    '05D3' => 'afii57667',
-    '05D4' => 'afii57668',
-    '05D5' => 'afii57669',
-    '05D6' => 'afii57670',
-    '05D7' => 'afii57671',
-    '05D8' => 'afii57672',
-    '05D9' => 'afii57673',
-    '05DA' => 'afii57674',
-    '05DB' => 'afii57675',
-    '05DC' => 'afii57676',
-    '05DD' => 'afii57677',
-    '05DE' => 'afii57678',
-    '05DF' => 'afii57679',
-    '05E0' => 'afii57680',
-    '05E1' => 'afii57681',
-    '05E2' => 'afii57682',
-    '05E3' => 'afii57683',
-    '05E4' => 'afii57684',
-    '05E5' => 'afii57685',
-    '05E6' => 'afii57686',
-    '05E7' => 'afii57687',
-    '05E8' => 'afii57688',
-    '05E9' => 'afii57689',
-    '05EA' => 'afii57690',
-    '05F0' => 'afii57716',
-    '05F1' => 'afii57717',
-    '05F2' => 'afii57718',
-    '060C' => 'afii57388',
-    '061B' => 'afii57403',
-    '061F' => 'afii57407',
-    '0621' => 'afii57409',
-    '0622' => 'afii57410',
-    '0623' => 'afii57411',
-    '0624' => 'afii57412',
-    '0625' => 'afii57413',
-    '0626' => 'afii57414',
-    '0627' => 'afii57415',
-    '0628' => 'afii57416',
-    '0629' => 'afii57417',
-    '062A' => 'afii57418',
-    '062B' => 'afii57419',
-    '062C' => 'afii57420',
-    '062D' => 'afii57421',
-    '062E' => 'afii57422',
-    '062F' => 'afii57423',
-    '0630' => 'afii57424',
-    '0631' => 'afii57425',
-    '0632' => 'afii57426',
-    '0633' => 'afii57427',
-    '0634' => 'afii57428',
-    '0635' => 'afii57429',
-    '0636' => 'afii57430',
-    '0637' => 'afii57431',
-    '0638' => 'afii57432',
-    '0639' => 'afii57433',
-    '063A' => 'afii57434',
-    '0640' => 'afii57440',
-    '0641' => 'afii57441',
-    '0642' => 'afii57442',
-    '0643' => 'afii57443',
-    '0644' => 'afii57444',
-    '0645' => 'afii57445',
-    '0646' => 'afii57446',
-    '0647' => 'afii57470',
-    '0648' => 'afii57448',
-    '0649' => 'afii57449',
-    '064A' => 'afii57450',
-    '064B' => 'afii57451',
-    '064C' => 'afii57452',
-    '064D' => 'afii57453',
-    '064E' => 'afii57454',
-    '064F' => 'afii57455',
-    '0650' => 'afii57456',
-    '0651' => 'afii57457',
-    '0652' => 'afii57458',
-    '0660' => 'afii57392',
-    '0661' => 'afii57393',
-    '0662' => 'afii57394',
-    '0663' => 'afii57395',
-    '0664' => 'afii57396',
-    '0665' => 'afii57397',
-    '0666' => 'afii57398',
-    '0667' => 'afii57399',
-    '0668' => 'afii57400',
-    '0669' => 'afii57401',
-    '066A' => 'afii57381',
-    '066D' => 'afii63167',
-    '0679' => 'afii57511',
-    '067E' => 'afii57506',
-    '0686' => 'afii57507',
-    '0688' => 'afii57512',
-    '0691' => 'afii57513',
-    '0698' => 'afii57508',
-    '06A4' => 'afii57505',
-    '06AF' => 'afii57509',
-    '06BA' => 'afii57514',
-    '06D2' => 'afii57519',
-    '06D5' => 'afii57534',
-    '1E80' => 'Wgrave',
-    '1E81' => 'wgrave',
-    '1E82' => 'Wacute',
-    '1E83' => 'wacute',
-    '1E84' => 'Wdieresis',
-    '1E85' => 'wdieresis',
-    '1EF2' => 'Ygrave',
-    '1EF3' => 'ygrave',
-    '200C' => 'afii61664',
-    '200D' => 'afii301',
-    '200E' => 'afii299',
-    '200F' => 'afii300',
-    '2012' => 'figuredash',
-    '2013' => 'endash',
-    '2014' => 'emdash',
-    '2015' => 'afii00208',
-    '2017' => 'underscoredbl',
-    '2018' => 'quoteleft',
-    '2019' => 'quoteright',
-    '201A' => 'quotesinglbase',
-    '201B' => 'quotereversed',
-    '201C' => 'quotedblleft',
-    '201D' => 'quotedblright',
-    '201E' => 'quotedblbase',
-    '2020' => 'dagger',
-    '2021' => 'daggerdbl',
-    '2022' => 'bullet',
-    '2024' => 'onedotenleader',
-    '2025' => 'twodotenleader',
-    '2026' => 'ellipsis',
-    '202C' => 'afii61573',
-    '202D' => 'afii61574',
-    '202E' => 'afii61575',
-    '2030' => 'perthousand',
-    '2032' => 'minute',
-    '2033' => 'second',
-    '2039' => 'guilsinglleft',
-    '203A' => 'guilsinglright',
-    '203C' => 'exclamdbl',
-    '2044' => 'fraction',
-#    '2070' => 'zerosuperior',
-#    '2074' => 'foursuperior',
-#    '2075' => 'fivesuperior',
-#    '2076' => 'sixsuperior',
-#    '2077' => 'sevensuperior',
-#    '2078' => 'eightsuperior',
-#    '2079' => 'ninesuperior',
-#    '207D' => 'parenleftsuperior',
-#    '207E' => 'parenrightsuperior',
-#    '207F' => 'nsuperior',
-#    '2080' => 'zeroinferior',
-#    '2081' => 'oneinferior',
-#    '2082' => 'twoinferior',
-#    '2083' => 'threeinferior',
-#    '2084' => 'fourinferior',
-#    '2085' => 'fiveinferior',
-#    '2086' => 'sixinferior',
-#    '2087' => 'seveninferior',
-#    '2088' => 'eightinferior',
-#    '2089' => 'nineinferior',
-#    '208D' => 'parenleftinferior',
-#    '208E' => 'parenrightinferior',
-    '20A1' => 'colonmonetary',
-    '20A3' => 'franc',
-    '20A4' => 'lira',
-    '20A7' => 'peseta',
-    '20AA' => 'afii57636',
-    '20AB' => 'dong',
-    '20AC' => 'Euro',
-    '2105' => 'afii61248',
-    '2111' => 'Ifraktur',
-    '2113' => 'afii61289',
-    '2116' => 'afii61352',
-    '2118' => 'weierstrass',
-    '211C' => 'Rfraktur',
-    '211E' => 'prescription',
-    '2122' => 'trademark',
-    '2126' => 'Omega',
-    '212E' => 'estimated',
-    '2135' => 'aleph',
-    '2153' => 'onethird',
-    '2154' => 'twothirds',
-    '215B' => 'oneeighth',
-    '215C' => 'threeeighths',
-    '215D' => 'fiveeighths',
-    '215E' => 'seveneighths',
-    '2190' => 'arrowleft',
-    '2191' => 'arrowup',
-    '2192' => 'arrowright',
-    '2193' => 'arrowdown',
-    '2194' => 'arrowboth',
-    '2195' => 'arrowupdn',
-    '21A8' => 'arrowupdnbse',
-    '21B5' => 'carriagereturn',
-    '21D0' => 'arrowdblleft',
-    '21D1' => 'arrowdblup',
-    '21D2' => 'arrowdblright',
-    '21D3' => 'arrowdbldown',
-    '21D4' => 'arrowdblboth',
-    '2200' => 'universal',
-    '2202' => 'partialdiff',
-    '2203' => 'existential',
-    '2205' => 'emptyset',
-    '2206' => 'Delta',
-    '2207' => 'gradient',
-    '2208' => 'element',
-    '2209' => 'notelement',
-    '220B' => 'suchthat',
-    '220F' => 'product',
-    '2211' => 'summation',
-    '2212' => 'minus',
-#    '2215' => 'fraction',
-    '2217' => 'asteriskmath',
-#    '2219' => 'periodcentered',
-    '221A' => 'radical',
-    '221D' => 'proportional',
-    '221E' => 'infinity',
-    '221F' => 'orthogonal',
-    '2220' => 'angle',
-    '2227' => 'logicaland',
-    '2228' => 'logicalor',
-    '2229' => 'intersection',
-    '222A' => 'union',
-    '222B' => 'integral',
-    '2234' => 'therefore',
-    '223C' => 'similar',
-    '2245' => 'congruent',
-    '2248' => 'approxequal',
-    '2260' => 'notequal',
-    '2261' => 'equivalence',
-    '2264' => 'lessequal',
-    '2265' => 'greaterequal',
-    '2282' => 'propersubset',
-    '2283' => 'propersuperset',
-    '2284' => 'notsubset',
-    '2286' => 'reflexsubset',
-    '2287' => 'reflexsuperset',
-    '2295' => 'circleplus',
-    '2297' => 'circlemultiply',
-    '22A5' => 'perpendicular',
-    '22C5' => 'dotmath',
-    '2302' => 'house',
-    '2310' => 'revlogicalnot',
-    '2320' => 'integraltp',
-    '2321' => 'integralbt',
-    '2329' => 'angleleft',
-    '232A' => 'angleright',
-    '2500' => 'SF100000',
-    '2502' => 'SF110000',
-    '250C' => 'SF010000',
-    '2510' => 'SF030000',
-    '2514' => 'SF020000',
-    '2518' => 'SF040000',
-    '251C' => 'SF080000',
-    '2524' => 'SF090000',
-    '252C' => 'SF060000',
-    '2534' => 'SF070000',
-    '253C' => 'SF050000',
-    '2550' => 'SF430000',
-    '2551' => 'SF240000',
-    '2552' => 'SF510000',
-    '2553' => 'SF520000',
-    '2554' => 'SF390000',
-    '2555' => 'SF220000',
-    '2556' => 'SF210000',
-    '2557' => 'SF250000',
-    '2558' => 'SF500000',
-    '2559' => 'SF490000',
-    '255A' => 'SF380000',
-    '255B' => 'SF280000',
-    '255C' => 'SF270000',
-    '255D' => 'SF260000',
-    '255E' => 'SF360000',
-    '255F' => 'SF370000',
-    '2560' => 'SF420000',
-    '2561' => 'SF190000',
-    '2562' => 'SF200000',
-    '2563' => 'SF230000',
-    '2564' => 'SF470000',
-    '2565' => 'SF480000',
-    '2566' => 'SF410000',
-    '2567' => 'SF450000',
-    '2568' => 'SF460000',
-    '2569' => 'SF400000',
-    '256A' => 'SF540000',
-    '256B' => 'SF530000',
-    '256C' => 'SF440000',
-    '2580' => 'upblock',
-    '2584' => 'dnblock',
-    '2588' => 'block',
-    '258C' => 'lfblock',
-    '2590' => 'rtblock',
-    '2591' => 'ltshade',
-    '2592' => 'shade',
-    '2593' => 'dkshade',
-    '25A0' => 'filledbox',
-    '25A1' => 'H22073',
-    '25AA' => 'H18543',
-    '25AB' => 'H18551',
-    '25AC' => 'filledrect',
-    '25B2' => 'triagup',
-    '25BA' => 'triagrt',
-    '25BC' => 'triagdn',
-    '25C4' => 'triaglf',
-    '25CA' => 'lozenge',
-    '25CB' => 'circle',
-    '25CF' => 'H18533',
-    '25D8' => 'invbullet',
-    '25D9' => 'invcircle',
-    '25E6' => 'openbullet',
-    '263A' => 'smileface',
-    '263B' => 'invsmileface',
-    '263C' => 'sun',
-    '2640' => 'female',
-    '2642' => 'male',
-    '2660' => 'spade',
-    '2663' => 'club',
-    '2665' => 'heart',
-    '2666' => 'diamond',
-    '266A' => 'musicalnote',
-    '266B' => 'musicalnotedbl',
-    'FB00' => 'ff',
-    'FB01' => 'fi',
-    'FB02' => 'fl',
-    'FB03' => 'ffi',
-    'FB04' => 'ffl',
-    'FB1F' => 'afii57705',
-    'FB2A' => 'afii57694',
-    'FB2B' => 'afii57695',
-    'FB35' => 'afii57723',
-    'FB4B' => 'afii57700',
-);
-
-# %doubles = (map{$_ => "uni$_"} qw(0394 03A9 0162 2215 00AD 02C9 03BC 2219 00A0 0163));
-
-sub lookup
-{
-    my ($num, $noalt) = @_;
-    my ($val) = sprintf("%04X", $num);
-
-    if (defined $names{$val})
-    {
-        return $names{$val};
-#        return $names{$val} if ($noalt);
-#        return $doubles{$val} || $names{$val};
-    }
-    elsif ($num > 0xFFFF)
-    { return "u$val"; }
-    elsif ($num)
-    { return "uni$val"; }
-    else
-    { return ".notdef"; }
-}
-
-1;
+package Font::TTF::PSNames;
+
+=head1 NAME
+
+Font::TTF::PSNames - Utilities for Postscript glyph name processing
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(%names %agl @EXPORT_OK);
+use Exporter qw( import );
+ at EXPORT_OK = qw( parse lookup);
+
+# Adobe Glyph List for New Fonts	
+# from http://partners.adobe.com/asn/tech/type/aglfn13.txt
+
+%names = (
+    '0020' => 'space',
+    '0021' => 'exclam',
+    '0022' => 'quotedbl',
+    '0023' => 'numbersign',
+    '0024' => 'dollar',
+    '0025' => 'percent',
+    '0026' => 'ampersand',
+    '0027' => 'quotesingle',
+    '0028' => 'parenleft',
+    '0029' => 'parenright',
+    '002A' => 'asterisk',
+    '002B' => 'plus',
+    '002C' => 'comma',
+    '002D' => 'hyphen',
+    '002E' => 'period',
+    '002F' => 'slash',
+    '0030' => 'zero',
+    '0031' => 'one',
+    '0032' => 'two',
+    '0033' => 'three',
+    '0034' => 'four',
+    '0035' => 'five',
+    '0036' => 'six',
+    '0037' => 'seven',
+    '0038' => 'eight',
+    '0039' => 'nine',
+    '003A' => 'colon',
+    '003B' => 'semicolon',
+    '003C' => 'less',
+    '003D' => 'equal',
+    '003E' => 'greater',
+    '003F' => 'question',
+    '0040' => 'at',
+    '0041' => 'A',
+    '0042' => 'B',
+    '0043' => 'C',
+    '0044' => 'D',
+    '0045' => 'E',
+    '0046' => 'F',
+    '0047' => 'G',
+    '0048' => 'H',
+    '0049' => 'I',
+    '004A' => 'J',
+    '004B' => 'K',
+    '004C' => 'L',
+    '004D' => 'M',
+    '004E' => 'N',
+    '004F' => 'O',
+    '0050' => 'P',
+    '0051' => 'Q',
+    '0052' => 'R',
+    '0053' => 'S',
+    '0054' => 'T',
+    '0055' => 'U',
+    '0056' => 'V',
+    '0057' => 'W',
+    '0058' => 'X',
+    '0059' => 'Y',
+    '005A' => 'Z',
+    '005B' => 'bracketleft',
+    '005C' => 'backslash',
+    '005D' => 'bracketright',
+    '005E' => 'asciicircum',
+    '005F' => 'underscore',
+    '0060' => 'grave',
+    '0061' => 'a',
+    '0062' => 'b',
+    '0063' => 'c',
+    '0064' => 'd',
+    '0065' => 'e',
+    '0066' => 'f',
+    '0067' => 'g',
+    '0068' => 'h',
+    '0069' => 'i',
+    '006A' => 'j',
+    '006B' => 'k',
+    '006C' => 'l',
+    '006D' => 'm',
+    '006E' => 'n',
+    '006F' => 'o',
+    '0070' => 'p',
+    '0071' => 'q',
+    '0072' => 'r',
+    '0073' => 's',
+    '0074' => 't',
+    '0075' => 'u',
+    '0076' => 'v',
+    '0077' => 'w',
+    '0078' => 'x',
+    '0079' => 'y',
+    '007A' => 'z',
+    '007B' => 'braceleft',
+    '007C' => 'bar',
+    '007D' => 'braceright',
+    '007E' => 'asciitilde',
+#    '00A0' => 'space',
+    '00A1' => 'exclamdown',
+    '00A2' => 'cent',
+    '00A3' => 'sterling',
+    '00A4' => 'currency',
+    '00A5' => 'yen',
+    '00A6' => 'brokenbar',
+    '00A7' => 'section',
+    '00A8' => 'dieresis',
+    '00A9' => 'copyright',
+    '00AA' => 'ordfeminine',
+    '00AB' => 'guillemotleft',
+    '00AC' => 'logicalnot',
+#    '00AD' => 'hyphen',
+    '00AE' => 'registered',
+    '00AF' => 'macron',
+    '00B0' => 'degree',
+    '00B1' => 'plusminus',
+    '00B2' => 'twosuperior',
+    '00B3' => 'threesuperior',
+    '00B4' => 'acute',
+    '00B5' => 'mu',
+    '00B6' => 'paragraph',
+    '00B7' => 'periodcentered',
+    '00B8' => 'cedilla',
+    '00B9' => 'onesuperior',
+    '00BA' => 'ordmasculine',
+    '00BB' => 'guillemotright',
+    '00BC' => 'onequarter',
+    '00BD' => 'onehalf',
+    '00BE' => 'threequarters',
+    '00BF' => 'questiondown',
+    '00C0' => 'Agrave',
+    '00C1' => 'Aacute',
+    '00C2' => 'Acircumflex',
+    '00C3' => 'Atilde',
+    '00C4' => 'Adieresis',
+    '00C5' => 'Aring',
+    '00C6' => 'AE',
+    '00C7' => 'Ccedilla',
+    '00C8' => 'Egrave',
+    '00C9' => 'Eacute',
+    '00CA' => 'Ecircumflex',
+    '00CB' => 'Edieresis',
+    '00CC' => 'Igrave',
+    '00CD' => 'Iacute',
+    '00CE' => 'Icircumflex',
+    '00CF' => 'Idieresis',
+    '00D0' => 'Eth',
+    '00D1' => 'Ntilde',
+    '00D2' => 'Ograve',
+    '00D3' => 'Oacute',
+    '00D4' => 'Ocircumflex',
+    '00D5' => 'Otilde',
+    '00D6' => 'Odieresis',
+    '00D7' => 'multiply',
+    '00D8' => 'Oslash',
+    '00D9' => 'Ugrave',
+    '00DA' => 'Uacute',
+    '00DB' => 'Ucircumflex',
+    '00DC' => 'Udieresis',
+    '00DD' => 'Yacute',
+    '00DE' => 'Thorn',
+    '00DF' => 'germandbls',
+    '00E0' => 'agrave',
+    '00E1' => 'aacute',
+    '00E2' => 'acircumflex',
+    '00E3' => 'atilde',
+    '00E4' => 'adieresis',
+    '00E5' => 'aring',
+    '00E6' => 'ae',
+    '00E7' => 'ccedilla',
+    '00E8' => 'egrave',
+    '00E9' => 'eacute',
+    '00EA' => 'ecircumflex',
+    '00EB' => 'edieresis',
+    '00EC' => 'igrave',
+    '00ED' => 'iacute',
+    '00EE' => 'icircumflex',
+    '00EF' => 'idieresis',
+    '00F0' => 'eth',
+    '00F1' => 'ntilde',
+    '00F2' => 'ograve',
+    '00F3' => 'oacute',
+    '00F4' => 'ocircumflex',
+    '00F5' => 'otilde',
+    '00F6' => 'odieresis',
+    '00F7' => 'divide',
+    '00F8' => 'oslash',
+    '00F9' => 'ugrave',
+    '00FA' => 'uacute',
+    '00FB' => 'ucircumflex',
+    '00FC' => 'udieresis',
+    '00FD' => 'yacute',
+    '00FE' => 'thorn',
+    '00FF' => 'ydieresis',
+    '0100' => 'Amacron',
+    '0101' => 'amacron',
+    '0102' => 'Abreve',
+    '0103' => 'abreve',
+    '0104' => 'Aogonek',
+    '0105' => 'aogonek',
+    '0106' => 'Cacute',
+    '0107' => 'cacute',
+    '0108' => 'Ccircumflex',
+    '0109' => 'ccircumflex',
+    '010A' => 'Cdotaccent',
+    '010B' => 'cdotaccent',
+    '010C' => 'Ccaron',
+    '010D' => 'ccaron',
+    '010E' => 'Dcaron',
+    '010F' => 'dcaron',
+    '0110' => 'Dcroat',
+    '0111' => 'dcroat',
+    '0112' => 'Emacron',
+    '0113' => 'emacron',
+    '0114' => 'Ebreve',
+    '0115' => 'ebreve',
+    '0116' => 'Edotaccent',
+    '0117' => 'edotaccent',
+    '0118' => 'Eogonek',
+    '0119' => 'eogonek',
+    '011A' => 'Ecaron',
+    '011B' => 'ecaron',
+    '011C' => 'Gcircumflex',
+    '011D' => 'gcircumflex',
+    '011E' => 'Gbreve',
+    '011F' => 'gbreve',
+    '0120' => 'Gdotaccent',
+    '0121' => 'gdotaccent',
+    '0122' => 'Gcommaaccent',
+    '0123' => 'gcommaaccent',
+    '0124' => 'Hcircumflex',
+    '0125' => 'hcircumflex',
+    '0126' => 'Hbar',
+    '0127' => 'hbar',
+    '0128' => 'Itilde',
+    '0129' => 'itilde',
+    '012A' => 'Imacron',
+    '012B' => 'imacron',
+    '012C' => 'Ibreve',
+    '012D' => 'ibreve',
+    '012E' => 'Iogonek',
+    '012F' => 'iogonek',
+    '0130' => 'Idotaccent',
+    '0131' => 'dotlessi',
+    '0132' => 'IJ',
+    '0133' => 'ij',
+    '0134' => 'Jcircumflex',
+    '0135' => 'jcircumflex',
+    '0136' => 'Kcommaaccent',
+    '0137' => 'kcommaaccent',
+    '0138' => 'kgreenlandic',
+    '0139' => 'Lacute',
+    '013A' => 'lacute',
+    '013B' => 'Lcommaaccent',
+    '013C' => 'lcommaaccent',
+    '013D' => 'Lcaron',
+    '013E' => 'lcaron',
+    '013F' => 'Ldot',
+    '0140' => 'ldot',
+    '0141' => 'Lslash',
+    '0142' => 'lslash',
+    '0143' => 'Nacute',
+    '0144' => 'nacute',
+    '0145' => 'Ncommaaccent',
+    '0146' => 'ncommaaccent',
+    '0147' => 'Ncaron',
+    '0148' => 'ncaron',
+    '0149' => 'napostrophe',
+    '014A' => 'Eng',
+    '014B' => 'eng',
+    '014C' => 'Omacron',
+    '014D' => 'omacron',
+    '014E' => 'Obreve',
+    '014F' => 'obreve',
+    '0150' => 'Ohungarumlaut',
+    '0151' => 'ohungarumlaut',
+    '0152' => 'OE',
+    '0153' => 'oe',
+    '0154' => 'Racute',
+    '0155' => 'racute',
+    '0156' => 'Rcommaaccent',
+    '0157' => 'rcommaaccent',
+    '0158' => 'Rcaron',
+    '0159' => 'rcaron',
+    '015A' => 'Sacute',
+    '015B' => 'sacute',
+    '015C' => 'Scircumflex',
+    '015D' => 'scircumflex',
+    '015E' => 'Scedilla',
+    '015F' => 'scedilla',
+    '0160' => 'Scaron',
+    '0161' => 'scaron',
+    '0162' => 'Tcommaaccent',
+    '0163' => 'tcommaaccent',
+    '0164' => 'Tcaron',
+    '0165' => 'tcaron',
+    '0166' => 'Tbar',
+    '0167' => 'tbar',
+    '0168' => 'Utilde',
+    '0169' => 'utilde',
+    '016A' => 'Umacron',
+    '016B' => 'umacron',
+    '016C' => 'Ubreve',
+    '016D' => 'ubreve',
+    '016E' => 'Uring',
+    '016F' => 'uring',
+    '0170' => 'Uhungarumlaut',
+    '0171' => 'uhungarumlaut',
+    '0172' => 'Uogonek',
+    '0173' => 'uogonek',
+    '0174' => 'Wcircumflex',
+    '0175' => 'wcircumflex',
+    '0176' => 'Ycircumflex',
+    '0177' => 'ycircumflex',
+    '0178' => 'Ydieresis',
+    '0179' => 'Zacute',
+    '017A' => 'zacute',
+    '017B' => 'Zdotaccent',
+    '017C' => 'zdotaccent',
+    '017D' => 'Zcaron',
+    '017E' => 'zcaron',
+    '017F' => 'longs',
+    '0192' => 'florin',
+    '01A0' => 'Ohorn',
+    '01A1' => 'ohorn',
+    '01AF' => 'Uhorn',
+    '01B0' => 'uhorn',
+    '01E6' => 'Gcaron',
+    '01E7' => 'gcaron',
+    '01FA' => 'Aringacute',
+    '01FB' => 'aringacute',
+    '01FC' => 'AEacute',
+    '01FD' => 'aeacute',
+    '01FE' => 'Oslashacute',
+    '01FF' => 'oslashacute',
+    '0218' => 'Scommaaccent',
+    '0219' => 'scommaaccent',
+#    '021A' => 'Tcommaaccent',
+#    '021B' => 'tcommaaccent',
+    '02BC' => 'afii57929',
+    '02BD' => 'afii64937',
+    '02C6' => 'circumflex',
+    '02C7' => 'caron',
+#    '02C9' => 'macron',
+    '02D8' => 'breve',
+    '02D9' => 'dotaccent',
+    '02DA' => 'ring',
+    '02DB' => 'ogonek',
+    '02DC' => 'tilde',
+    '02DD' => 'hungarumlaut',
+    '0300' => 'gravecomb',
+    '0301' => 'acutecomb',
+    '0303' => 'tildecomb',
+    '0309' => 'hookabovecomb',
+    '0323' => 'dotbelowcomb',
+    '0384' => 'tonos',
+    '0385' => 'dieresistonos',
+    '0386' => 'Alphatonos',
+    '0387' => 'anoteleia',
+    '0388' => 'Epsilontonos',
+    '0389' => 'Etatonos',
+    '038A' => 'Iotatonos',
+    '038C' => 'Omicrontonos',
+    '038E' => 'Upsilontonos',
+    '038F' => 'Omegatonos',
+    '0390' => 'iotadieresistonos',
+    '0391' => 'Alpha',
+    '0392' => 'Beta',
+    '0393' => 'Gamma',
+#    '0394' => 'Delta',
+    '0395' => 'Epsilon',
+    '0396' => 'Zeta',
+    '0397' => 'Eta',
+    '0398' => 'Theta',
+    '0399' => 'Iota',
+    '039A' => 'Kappa',
+    '039B' => 'Lambda',
+    '039C' => 'Mu',
+    '039D' => 'Nu',
+    '039E' => 'Xi',
+    '039F' => 'Omicron',
+    '03A0' => 'Pi',
+    '03A1' => 'Rho',
+    '03A3' => 'Sigma',
+    '03A4' => 'Tau',
+    '03A5' => 'Upsilon',
+    '03A6' => 'Phi',
+    '03A7' => 'Chi',
+    '03A8' => 'Psi',
+#    '03A9' => 'Omega',
+    '03AA' => 'Iotadieresis',
+    '03AB' => 'Upsilondieresis',
+    '03AC' => 'alphatonos',
+    '03AD' => 'epsilontonos',
+    '03AE' => 'etatonos',
+    '03AF' => 'iotatonos',
+    '03B0' => 'upsilondieresistonos',
+    '03B1' => 'alpha',
+    '03B2' => 'beta',
+    '03B3' => 'gamma',
+    '03B4' => 'delta',
+    '03B5' => 'epsilon',
+    '03B6' => 'zeta',
+    '03B7' => 'eta',
+    '03B8' => 'theta',
+    '03B9' => 'iota',
+    '03BA' => 'kappa',
+    '03BB' => 'lambda',
+#    '03BC' => 'mu',
+    '03BD' => 'nu',
+    '03BE' => 'xi',
+    '03BF' => 'omicron',
+    '03C0' => 'pi',
+    '03C1' => 'rho',
+    '03C2' => 'sigma1',
+    '03C3' => 'sigma',
+    '03C4' => 'tau',
+    '03C5' => 'upsilon',
+    '03C6' => 'phi',
+    '03C7' => 'chi',
+    '03C8' => 'psi',
+    '03C9' => 'omega',
+    '03CA' => 'iotadieresis',
+    '03CB' => 'upsilondieresis',
+    '03CC' => 'omicrontonos',
+    '03CD' => 'upsilontonos',
+    '03CE' => 'omegatonos',
+    '03D1' => 'theta1',
+    '03D2' => 'Upsilon1',
+    '03D5' => 'phi1',
+    '03D6' => 'omega1',
+    '0401' => 'afii10023',
+    '0402' => 'afii10051',
+    '0403' => 'afii10052',
+    '0404' => 'afii10053',
+    '0405' => 'afii10054',
+    '0406' => 'afii10055',
+    '0407' => 'afii10056',
+    '0408' => 'afii10057',
+    '0409' => 'afii10058',
+    '040A' => 'afii10059',
+    '040B' => 'afii10060',
+    '040C' => 'afii10061',
+    '040E' => 'afii10062',
+    '040F' => 'afii10145',
+    '0410' => 'afii10017',
+    '0411' => 'afii10018',
+    '0412' => 'afii10019',
+    '0413' => 'afii10020',
+    '0414' => 'afii10021',
+    '0415' => 'afii10022',
+    '0416' => 'afii10024',
+    '0417' => 'afii10025',
+    '0418' => 'afii10026',
+    '0419' => 'afii10027',
+    '041A' => 'afii10028',
+    '041B' => 'afii10029',
+    '041C' => 'afii10030',
+    '041D' => 'afii10031',
+    '041E' => 'afii10032',
+    '041F' => 'afii10033',
+    '0420' => 'afii10034',
+    '0421' => 'afii10035',
+    '0422' => 'afii10036',
+    '0423' => 'afii10037',
+    '0424' => 'afii10038',
+    '0425' => 'afii10039',
+    '0426' => 'afii10040',
+    '0427' => 'afii10041',
+    '0428' => 'afii10042',
+    '0429' => 'afii10043',
+    '042A' => 'afii10044',
+    '042B' => 'afii10045',
+    '042C' => 'afii10046',
+    '042D' => 'afii10047',
+    '042E' => 'afii10048',
+    '042F' => 'afii10049',
+    '0430' => 'afii10065',
+    '0431' => 'afii10066',
+    '0432' => 'afii10067',
+    '0433' => 'afii10068',
+    '0434' => 'afii10069',
+    '0435' => 'afii10070',
+    '0436' => 'afii10072',
+    '0437' => 'afii10073',
+    '0438' => 'afii10074',
+    '0439' => 'afii10075',
+    '043A' => 'afii10076',
+    '043B' => 'afii10077',
+    '043C' => 'afii10078',
+    '043D' => 'afii10079',
+    '043E' => 'afii10080',
+    '043F' => 'afii10081',
+    '0440' => 'afii10082',
+    '0441' => 'afii10083',
+    '0442' => 'afii10084',
+    '0443' => 'afii10085',
+    '0444' => 'afii10086',
+    '0445' => 'afii10087',
+    '0446' => 'afii10088',
+    '0447' => 'afii10089',
+    '0448' => 'afii10090',
+    '0449' => 'afii10091',
+    '044A' => 'afii10092',
+    '044B' => 'afii10093',
+    '044C' => 'afii10094',
+    '044D' => 'afii10095',
+    '044E' => 'afii10096',
+    '044F' => 'afii10097',
+    '0451' => 'afii10071',
+    '0452' => 'afii10099',
+    '0453' => 'afii10100',
+    '0454' => 'afii10101',
+    '0455' => 'afii10102',
+    '0456' => 'afii10103',
+    '0457' => 'afii10104',
+    '0458' => 'afii10105',
+    '0459' => 'afii10106',
+    '045A' => 'afii10107',
+    '045B' => 'afii10108',
+    '045C' => 'afii10109',
+    '045E' => 'afii10110',
+    '045F' => 'afii10193',
+    '0462' => 'afii10146',
+    '0463' => 'afii10194',
+    '0472' => 'afii10147',
+    '0473' => 'afii10195',
+    '0474' => 'afii10148',
+    '0475' => 'afii10196',
+    '0490' => 'afii10050',
+    '0491' => 'afii10098',
+    '04D9' => 'afii10846',
+    '05B0' => 'afii57799',
+    '05B1' => 'afii57801',
+    '05B2' => 'afii57800',
+    '05B3' => 'afii57802',
+    '05B4' => 'afii57793',
+    '05B5' => 'afii57794',
+    '05B6' => 'afii57795',
+    '05B7' => 'afii57798',
+    '05B8' => 'afii57797',
+    '05B9' => 'afii57806',
+    '05BB' => 'afii57796',
+    '05BC' => 'afii57807',
+    '05BD' => 'afii57839',
+    '05BE' => 'afii57645',
+    '05BF' => 'afii57841',
+    '05C0' => 'afii57842',
+    '05C1' => 'afii57804',
+    '05C2' => 'afii57803',
+    '05C3' => 'afii57658',
+    '05D0' => 'afii57664',
+    '05D1' => 'afii57665',
+    '05D2' => 'afii57666',
+    '05D3' => 'afii57667',
+    '05D4' => 'afii57668',
+    '05D5' => 'afii57669',
+    '05D6' => 'afii57670',
+    '05D7' => 'afii57671',
+    '05D8' => 'afii57672',
+    '05D9' => 'afii57673',
+    '05DA' => 'afii57674',
+    '05DB' => 'afii57675',
+    '05DC' => 'afii57676',
+    '05DD' => 'afii57677',
+    '05DE' => 'afii57678',
+    '05DF' => 'afii57679',
+    '05E0' => 'afii57680',
+    '05E1' => 'afii57681',
+    '05E2' => 'afii57682',
+    '05E3' => 'afii57683',
+    '05E4' => 'afii57684',
+    '05E5' => 'afii57685',
+    '05E6' => 'afii57686',
+    '05E7' => 'afii57687',
+    '05E8' => 'afii57688',
+    '05E9' => 'afii57689',
+    '05EA' => 'afii57690',
+    '05F0' => 'afii57716',
+    '05F1' => 'afii57717',
+    '05F2' => 'afii57718',
+    '060C' => 'afii57388',
+    '061B' => 'afii57403',
+    '061F' => 'afii57407',
+    '0621' => 'afii57409',
+    '0622' => 'afii57410',
+    '0623' => 'afii57411',
+    '0624' => 'afii57412',
+    '0625' => 'afii57413',
+    '0626' => 'afii57414',
+    '0627' => 'afii57415',
+    '0628' => 'afii57416',
+    '0629' => 'afii57417',
+    '062A' => 'afii57418',
+    '062B' => 'afii57419',
+    '062C' => 'afii57420',
+    '062D' => 'afii57421',
+    '062E' => 'afii57422',
+    '062F' => 'afii57423',
+    '0630' => 'afii57424',
+    '0631' => 'afii57425',
+    '0632' => 'afii57426',
+    '0633' => 'afii57427',
+    '0634' => 'afii57428',
+    '0635' => 'afii57429',
+    '0636' => 'afii57430',
+    '0637' => 'afii57431',
+    '0638' => 'afii57432',
+    '0639' => 'afii57433',
+    '063A' => 'afii57434',
+    '0640' => 'afii57440',
+    '0641' => 'afii57441',
+    '0642' => 'afii57442',
+    '0643' => 'afii57443',
+    '0644' => 'afii57444',
+    '0645' => 'afii57445',
+    '0646' => 'afii57446',
+    '0647' => 'afii57470',
+    '0648' => 'afii57448',
+    '0649' => 'afii57449',
+    '064A' => 'afii57450',
+    '064B' => 'afii57451',
+    '064C' => 'afii57452',
+    '064D' => 'afii57453',
+    '064E' => 'afii57454',
+    '064F' => 'afii57455',
+    '0650' => 'afii57456',
+    '0651' => 'afii57457',
+    '0652' => 'afii57458',
+    '0660' => 'afii57392',
+    '0661' => 'afii57393',
+    '0662' => 'afii57394',
+    '0663' => 'afii57395',
+    '0664' => 'afii57396',
+    '0665' => 'afii57397',
+    '0666' => 'afii57398',
+    '0667' => 'afii57399',
+    '0668' => 'afii57400',
+    '0669' => 'afii57401',
+    '066A' => 'afii57381',
+    '066D' => 'afii63167',
+    '0679' => 'afii57511',
+    '067E' => 'afii57506',
+    '0686' => 'afii57507',
+    '0688' => 'afii57512',
+    '0691' => 'afii57513',
+    '0698' => 'afii57508',
+    '06A4' => 'afii57505',
+    '06AF' => 'afii57509',
+    '06BA' => 'afii57514',
+    '06D2' => 'afii57519',
+    '06D5' => 'afii57534',
+    '1E80' => 'Wgrave',
+    '1E81' => 'wgrave',
+    '1E82' => 'Wacute',
+    '1E83' => 'wacute',
+    '1E84' => 'Wdieresis',
+    '1E85' => 'wdieresis',
+    '1EF2' => 'Ygrave',
+    '1EF3' => 'ygrave',
+    '200C' => 'afii61664',
+    '200D' => 'afii301',
+    '200E' => 'afii299',
+    '200F' => 'afii300',
+    '2012' => 'figuredash',
+    '2013' => 'endash',
+    '2014' => 'emdash',
+    '2015' => 'afii00208',
+    '2017' => 'underscoredbl',
+    '2018' => 'quoteleft',
+    '2019' => 'quoteright',
+    '201A' => 'quotesinglbase',
+    '201B' => 'quotereversed',
+    '201C' => 'quotedblleft',
+    '201D' => 'quotedblright',
+    '201E' => 'quotedblbase',
+    '2020' => 'dagger',
+    '2021' => 'daggerdbl',
+    '2022' => 'bullet',
+    '2024' => 'onedotenleader',
+    '2025' => 'twodotenleader',
+    '2026' => 'ellipsis',
+    '202C' => 'afii61573',
+    '202D' => 'afii61574',
+    '202E' => 'afii61575',
+    '2030' => 'perthousand',
+    '2032' => 'minute',
+    '2033' => 'second',
+    '2039' => 'guilsinglleft',
+    '203A' => 'guilsinglright',
+    '203C' => 'exclamdbl',
+    '2044' => 'fraction',
+#    '2070' => 'zerosuperior',
+#    '2074' => 'foursuperior',
+#    '2075' => 'fivesuperior',
+#    '2076' => 'sixsuperior',
+#    '2077' => 'sevensuperior',
+#    '2078' => 'eightsuperior',
+#    '2079' => 'ninesuperior',
+#    '207D' => 'parenleftsuperior',
+#    '207E' => 'parenrightsuperior',
+#    '207F' => 'nsuperior',
+#    '2080' => 'zeroinferior',
+#    '2081' => 'oneinferior',
+#    '2082' => 'twoinferior',
+#    '2083' => 'threeinferior',
+#    '2084' => 'fourinferior',
+#    '2085' => 'fiveinferior',
+#    '2086' => 'sixinferior',
+#    '2087' => 'seveninferior',
+#    '2088' => 'eightinferior',
+#    '2089' => 'nineinferior',
+#    '208D' => 'parenleftinferior',
+#    '208E' => 'parenrightinferior',
+    '20A1' => 'colonmonetary',
+    '20A3' => 'franc',
+    '20A4' => 'lira',
+    '20A7' => 'peseta',
+    '20AA' => 'afii57636',
+    '20AB' => 'dong',
+    '20AC' => 'Euro',
+    '2105' => 'afii61248',
+    '2111' => 'Ifraktur',
+    '2113' => 'afii61289',
+    '2116' => 'afii61352',
+    '2118' => 'weierstrass',
+    '211C' => 'Rfraktur',
+    '211E' => 'prescription',
+    '2122' => 'trademark',
+    '2126' => 'Omega',
+    '212E' => 'estimated',
+    '2135' => 'aleph',
+    '2153' => 'onethird',
+    '2154' => 'twothirds',
+    '215B' => 'oneeighth',
+    '215C' => 'threeeighths',
+    '215D' => 'fiveeighths',
+    '215E' => 'seveneighths',
+    '2190' => 'arrowleft',
+    '2191' => 'arrowup',
+    '2192' => 'arrowright',
+    '2193' => 'arrowdown',
+    '2194' => 'arrowboth',
+    '2195' => 'arrowupdn',
+    '21A8' => 'arrowupdnbse',
+    '21B5' => 'carriagereturn',
+    '21D0' => 'arrowdblleft',
+    '21D1' => 'arrowdblup',
+    '21D2' => 'arrowdblright',
+    '21D3' => 'arrowdbldown',
+    '21D4' => 'arrowdblboth',
+    '2200' => 'universal',
+    '2202' => 'partialdiff',
+    '2203' => 'existential',
+    '2205' => 'emptyset',
+    '2206' => 'Delta',
+    '2207' => 'gradient',
+    '2208' => 'element',
+    '2209' => 'notelement',
+    '220B' => 'suchthat',
+    '220F' => 'product',
+    '2211' => 'summation',
+    '2212' => 'minus',
+#    '2215' => 'fraction',
+    '2217' => 'asteriskmath',
+#    '2219' => 'periodcentered',
+    '221A' => 'radical',
+    '221D' => 'proportional',
+    '221E' => 'infinity',
+    '221F' => 'orthogonal',
+    '2220' => 'angle',
+    '2227' => 'logicaland',
+    '2228' => 'logicalor',
+    '2229' => 'intersection',
+    '222A' => 'union',
+    '222B' => 'integral',
+    '2234' => 'therefore',
+    '223C' => 'similar',
+    '2245' => 'congruent',
+    '2248' => 'approxequal',
+    '2260' => 'notequal',
+    '2261' => 'equivalence',
+    '2264' => 'lessequal',
+    '2265' => 'greaterequal',
+    '2282' => 'propersubset',
+    '2283' => 'propersuperset',
+    '2284' => 'notsubset',
+    '2286' => 'reflexsubset',
+    '2287' => 'reflexsuperset',
+    '2295' => 'circleplus',
+    '2297' => 'circlemultiply',
+    '22A5' => 'perpendicular',
+    '22C5' => 'dotmath',
+    '2302' => 'house',
+    '2310' => 'revlogicalnot',
+    '2320' => 'integraltp',
+    '2321' => 'integralbt',
+    '2329' => 'angleleft',
+    '232A' => 'angleright',
+    '2500' => 'SF100000',
+    '2502' => 'SF110000',
+    '250C' => 'SF010000',
+    '2510' => 'SF030000',
+    '2514' => 'SF020000',
+    '2518' => 'SF040000',
+    '251C' => 'SF080000',
+    '2524' => 'SF090000',
+    '252C' => 'SF060000',
+    '2534' => 'SF070000',
+    '253C' => 'SF050000',
+    '2550' => 'SF430000',
+    '2551' => 'SF240000',
+    '2552' => 'SF510000',
+    '2553' => 'SF520000',
+    '2554' => 'SF390000',
+    '2555' => 'SF220000',
+    '2556' => 'SF210000',
+    '2557' => 'SF250000',
+    '2558' => 'SF500000',
+    '2559' => 'SF490000',
+    '255A' => 'SF380000',
+    '255B' => 'SF280000',
+    '255C' => 'SF270000',
+    '255D' => 'SF260000',
+    '255E' => 'SF360000',
+    '255F' => 'SF370000',
+    '2560' => 'SF420000',
+    '2561' => 'SF190000',
+    '2562' => 'SF200000',
+    '2563' => 'SF230000',
+    '2564' => 'SF470000',
+    '2565' => 'SF480000',
+    '2566' => 'SF410000',
+    '2567' => 'SF450000',
+    '2568' => 'SF460000',
+    '2569' => 'SF400000',
+    '256A' => 'SF540000',
+    '256B' => 'SF530000',
+    '256C' => 'SF440000',
+    '2580' => 'upblock',
+    '2584' => 'dnblock',
+    '2588' => 'block',
+    '258C' => 'lfblock',
+    '2590' => 'rtblock',
+    '2591' => 'ltshade',
+    '2592' => 'shade',
+    '2593' => 'dkshade',
+    '25A0' => 'filledbox',
+    '25A1' => 'H22073',
+    '25AA' => 'H18543',
+    '25AB' => 'H18551',
+    '25AC' => 'filledrect',
+    '25B2' => 'triagup',
+    '25BA' => 'triagrt',
+    '25BC' => 'triagdn',
+    '25C4' => 'triaglf',
+    '25CA' => 'lozenge',
+    '25CB' => 'circle',
+    '25CF' => 'H18533',
+    '25D8' => 'invbullet',
+    '25D9' => 'invcircle',
+    '25E6' => 'openbullet',
+    '263A' => 'smileface',
+    '263B' => 'invsmileface',
+    '263C' => 'sun',
+    '2640' => 'female',
+    '2642' => 'male',
+    '2660' => 'spade',
+    '2663' => 'club',
+    '2665' => 'heart',
+    '2666' => 'diamond',
+    '266A' => 'musicalnote',
+    '266B' => 'musicalnotedbl',
+    'FB00' => 'ff',
+    'FB01' => 'fi',
+    'FB02' => 'fl',
+    'FB03' => 'ffi',
+    'FB04' => 'ffl',
+    'FB1F' => 'afii57705',
+    'FB2A' => 'afii57694',
+    'FB2B' => 'afii57695',
+    'FB35' => 'afii57723',
+    'FB4B' => 'afii57700',
+);
+
+# Adobe Glyph List 2.0 (sans those in glyph list for *new* fonts) -- thus
+# these are all historic names that could occur in fonts
+# from http://partners.adobe.com/asn/tech/type/glyphlist.txt
+
+%agl = (
+	'AEmacron' => "\x{01E2}",
+	'AEsmall' => "\x{F7E6}",
+	'Aacutesmall' => "\x{F7E1}",
+	'Abreveacute' => "\x{1EAE}",
+	'Abrevecyrillic' => "\x{04D0}",
+	'Abrevedotbelow' => "\x{1EB6}",
+	'Abrevegrave' => "\x{1EB0}",
+	'Abrevehookabove' => "\x{1EB2}",
+	'Abrevetilde' => "\x{1EB4}",
+	'Acaron' => "\x{01CD}",
+	'Acircle' => "\x{24B6}",
+	'Acircumflexacute' => "\x{1EA4}",
+	'Acircumflexdotbelow' => "\x{1EAC}",
+	'Acircumflexgrave' => "\x{1EA6}",
+	'Acircumflexhookabove' => "\x{1EA8}",
+	'Acircumflexsmall' => "\x{F7E2}",
+	'Acircumflextilde' => "\x{1EAA}",
+	'Acute' => "\x{F6C9}",
+	'Acutesmall' => "\x{F7B4}",
+	'Acyrillic' => "\x{0410}",
+	'Adblgrave' => "\x{0200}",
+	'Adieresiscyrillic' => "\x{04D2}",
+	'Adieresismacron' => "\x{01DE}",
+	'Adieresissmall' => "\x{F7E4}",
+	'Adotbelow' => "\x{1EA0}",
+	'Adotmacron' => "\x{01E0}",
+	'Agravesmall' => "\x{F7E0}",
+	'Ahookabove' => "\x{1EA2}",
+	'Aiecyrillic' => "\x{04D4}",
+	'Ainvertedbreve' => "\x{0202}",
+	'Amonospace' => "\x{FF21}",
+	'Aringbelow' => "\x{1E00}",
+	'Aringsmall' => "\x{F7E5}",
+	'Asmall' => "\x{F761}",
+	'Atildesmall' => "\x{F7E3}",
+	'Aybarmenian' => "\x{0531}",
+	'Bcircle' => "\x{24B7}",
+	'Bdotaccent' => "\x{1E02}",
+	'Bdotbelow' => "\x{1E04}",
+	'Becyrillic' => "\x{0411}",
+	'Benarmenian' => "\x{0532}",
+	'Bhook' => "\x{0181}",
+	'Blinebelow' => "\x{1E06}",
+	'Bmonospace' => "\x{FF22}",
+	'Brevesmall' => "\x{F6F4}",
+	'Bsmall' => "\x{F762}",
+	'Btopbar' => "\x{0182}",
+	'Caarmenian' => "\x{053E}",
+	'Caron' => "\x{F6CA}",
+	'Caronsmall' => "\x{F6F5}",
+	'Ccedillaacute' => "\x{1E08}",
+	'Ccedillasmall' => "\x{F7E7}",
+	'Ccircle' => "\x{24B8}",
+	'Cdot' => "\x{010A}",
+	'Cedillasmall' => "\x{F7B8}",
+	'Chaarmenian' => "\x{0549}",
+	'Cheabkhasiancyrillic' => "\x{04BC}",
+	'Checyrillic' => "\x{0427}",
+	'Chedescenderabkhasiancyrillic' => "\x{04BE}",
+	'Chedescendercyrillic' => "\x{04B6}",
+	'Chedieresiscyrillic' => "\x{04F4}",
+	'Cheharmenian' => "\x{0543}",
+	'Chekhakassiancyrillic' => "\x{04CB}",
+	'Cheverticalstrokecyrillic' => "\x{04B8}",
+	'Chook' => "\x{0187}",
+	'Circumflexsmall' => "\x{F6F6}",
+	'Cmonospace' => "\x{FF23}",
+	'Coarmenian' => "\x{0551}",
+	'Csmall' => "\x{F763}",
+	'DZ' => "\x{01F1}",
+	'DZcaron' => "\x{01C4}",
+	'Daarmenian' => "\x{0534}",
+	'Dafrican' => "\x{0189}",
+	'Dcedilla' => "\x{1E10}",
+	'Dcircle' => "\x{24B9}",
+	'Dcircumflexbelow' => "\x{1E12}",
+	'Ddotaccent' => "\x{1E0A}",
+	'Ddotbelow' => "\x{1E0C}",
+	'Decyrillic' => "\x{0414}",
+	'Deicoptic' => "\x{03EE}",
+	'Deltagreek' => "\x{0394}",
+	'Dhook' => "\x{018A}",
+	'Dieresis' => "\x{F6CB}",
+	'DieresisAcute' => "\x{F6CC}",
+	'DieresisGrave' => "\x{F6CD}",
+	'Dieresissmall' => "\x{F7A8}",
+	'Digammagreek' => "\x{03DC}",
+	'Djecyrillic' => "\x{0402}",
+	'Dlinebelow' => "\x{1E0E}",
+	'Dmonospace' => "\x{FF24}",
+	'Dotaccentsmall' => "\x{F6F7}",
+	'Dslash' => "\x{0110}",
+	'Dsmall' => "\x{F764}",
+	'Dtopbar' => "\x{018B}",
+	'Dz' => "\x{01F2}",
+	'Dzcaron' => "\x{01C5}",
+	'Dzeabkhasiancyrillic' => "\x{04E0}",
+	'Dzecyrillic' => "\x{0405}",
+	'Dzhecyrillic' => "\x{040F}",
+	'Eacutesmall' => "\x{F7E9}",
+	'Ecedillabreve' => "\x{1E1C}",
+	'Echarmenian' => "\x{0535}",
+	'Ecircle' => "\x{24BA}",
+	'Ecircumflexacute' => "\x{1EBE}",
+	'Ecircumflexbelow' => "\x{1E18}",
+	'Ecircumflexdotbelow' => "\x{1EC6}",
+	'Ecircumflexgrave' => "\x{1EC0}",
+	'Ecircumflexhookabove' => "\x{1EC2}",
+	'Ecircumflexsmall' => "\x{F7EA}",
+	'Ecircumflextilde' => "\x{1EC4}",
+	'Ecyrillic' => "\x{0404}",
+	'Edblgrave' => "\x{0204}",
+	'Edieresissmall' => "\x{F7EB}",
+	'Edot' => "\x{0116}",
+	'Edotbelow' => "\x{1EB8}",
+	'Efcyrillic' => "\x{0424}",
+	'Egravesmall' => "\x{F7E8}",
+	'Eharmenian' => "\x{0537}",
+	'Ehookabove' => "\x{1EBA}",
+	'Eightroman' => "\x{2167}",
+	'Einvertedbreve' => "\x{0206}",
+	'Eiotifiedcyrillic' => "\x{0464}",
+	'Elcyrillic' => "\x{041B}",
+	'Elevenroman' => "\x{216A}",
+	'Emacronacute' => "\x{1E16}",
+	'Emacrongrave' => "\x{1E14}",
+	'Emcyrillic' => "\x{041C}",
+	'Emonospace' => "\x{FF25}",
+	'Encyrillic' => "\x{041D}",
+	'Endescendercyrillic' => "\x{04A2}",
+	'Enghecyrillic' => "\x{04A4}",
+	'Enhookcyrillic' => "\x{04C7}",
+	'Eopen' => "\x{0190}",
+	'Ercyrillic' => "\x{0420}",
+	'Ereversed' => "\x{018E}",
+	'Ereversedcyrillic' => "\x{042D}",
+	'Escyrillic' => "\x{0421}",
+	'Esdescendercyrillic' => "\x{04AA}",
+	'Esh' => "\x{01A9}",
+	'Esmall' => "\x{F765}",
+	'Etarmenian' => "\x{0538}",
+	'Ethsmall' => "\x{F7F0}",
+	'Etilde' => "\x{1EBC}",
+	'Etildebelow' => "\x{1E1A}",
+	'Ezh' => "\x{01B7}",
+	'Ezhcaron' => "\x{01EE}",
+	'Ezhreversed' => "\x{01B8}",
+	'Fcircle' => "\x{24BB}",
+	'Fdotaccent' => "\x{1E1E}",
+	'Feharmenian' => "\x{0556}",
+	'Feicoptic' => "\x{03E4}",
+	'Fhook' => "\x{0191}",
+	'Fitacyrillic' => "\x{0472}",
+	'Fiveroman' => "\x{2164}",
+	'Fmonospace' => "\x{FF26}",
+	'Fourroman' => "\x{2163}",
+	'Fsmall' => "\x{F766}",
+	'GBsquare' => "\x{3387}",
+	'Gacute' => "\x{01F4}",
+	'Gammaafrican' => "\x{0194}",
+	'Gangiacoptic' => "\x{03EA}",
+	'Gcedilla' => "\x{0122}",
+	'Gcircle' => "\x{24BC}",
+	'Gdot' => "\x{0120}",
+	'Gecyrillic' => "\x{0413}",
+	'Ghadarmenian' => "\x{0542}",
+	'Ghemiddlehookcyrillic' => "\x{0494}",
+	'Ghestrokecyrillic' => "\x{0492}",
+	'Gheupturncyrillic' => "\x{0490}",
+	'Ghook' => "\x{0193}",
+	'Gimarmenian' => "\x{0533}",
+	'Gjecyrillic' => "\x{0403}",
+	'Gmacron' => "\x{1E20}",
+	'Gmonospace' => "\x{FF27}",
+	'Grave' => "\x{F6CE}",
+	'Gravesmall' => "\x{F760}",
+	'Gsmall' => "\x{F767}",
+	'Gsmallhook' => "\x{029B}",
+	'Gstroke' => "\x{01E4}",
+	'HPsquare' => "\x{33CB}",
+	'Haabkhasiancyrillic' => "\x{04A8}",
+	'Hadescendercyrillic' => "\x{04B2}",
+	'Hardsigncyrillic' => "\x{042A}",
+	'Hbrevebelow' => "\x{1E2A}",
+	'Hcedilla' => "\x{1E28}",
+	'Hcircle' => "\x{24BD}",
+	'Hdieresis' => "\x{1E26}",
+	'Hdotaccent' => "\x{1E22}",
+	'Hdotbelow' => "\x{1E24}",
+	'Hmonospace' => "\x{FF28}",
+	'Hoarmenian' => "\x{0540}",
+	'Horicoptic' => "\x{03E8}",
+	'Hsmall' => "\x{F768}",
+	'Hungarumlaut' => "\x{F6CF}",
+	'Hungarumlautsmall' => "\x{F6F8}",
+	'Hzsquare' => "\x{3390}",
+	'IAcyrillic' => "\x{042F}",
+	'IUcyrillic' => "\x{042E}",
+	'Iacutesmall' => "\x{F7ED}",
+	'Icaron' => "\x{01CF}",
+	'Icircle' => "\x{24BE}",
+	'Icircumflexsmall' => "\x{F7EE}",
+	'Icyrillic' => "\x{0406}",
+	'Idblgrave' => "\x{0208}",
+	'Idieresisacute' => "\x{1E2E}",
+	'Idieresiscyrillic' => "\x{04E4}",
+	'Idieresissmall' => "\x{F7EF}",
+	'Idot' => "\x{0130}",
+	'Idotbelow' => "\x{1ECA}",
+	'Iebrevecyrillic' => "\x{04D6}",
+	'Iecyrillic' => "\x{0415}",
+	'Igravesmall' => "\x{F7EC}",
+	'Ihookabove' => "\x{1EC8}",
+	'Iicyrillic' => "\x{0418}",
+	'Iinvertedbreve' => "\x{020A}",
+	'Iishortcyrillic' => "\x{0419}",
+	'Imacroncyrillic' => "\x{04E2}",
+	'Imonospace' => "\x{FF29}",
+	'Iniarmenian' => "\x{053B}",
+	'Iocyrillic' => "\x{0401}",
+	'Iotaafrican' => "\x{0196}",
+	'Ismall' => "\x{F769}",
+	'Istroke' => "\x{0197}",
+	'Itildebelow' => "\x{1E2C}",
+	'Izhitsacyrillic' => "\x{0474}",
+	'Izhitsadblgravecyrillic' => "\x{0476}",
+	'Jaarmenian' => "\x{0541}",
+	'Jcircle' => "\x{24BF}",
+	'Jecyrillic' => "\x{0408}",
+	'Jheharmenian' => "\x{054B}",
+	'Jmonospace' => "\x{FF2A}",
+	'Jsmall' => "\x{F76A}",
+	'KBsquare' => "\x{3385}",
+	'KKsquare' => "\x{33CD}",
+	'Kabashkircyrillic' => "\x{04A0}",
+	'Kacute' => "\x{1E30}",
+	'Kacyrillic' => "\x{041A}",
+	'Kadescendercyrillic' => "\x{049A}",
+	'Kahookcyrillic' => "\x{04C3}",
+	'Kastrokecyrillic' => "\x{049E}",
+	'Kaverticalstrokecyrillic' => "\x{049C}",
+	'Kcaron' => "\x{01E8}",
+	'Kcedilla' => "\x{0136}",
+	'Kcircle' => "\x{24C0}",
+	'Kdotbelow' => "\x{1E32}",
+	'Keharmenian' => "\x{0554}",
+	'Kenarmenian' => "\x{053F}",
+	'Khacyrillic' => "\x{0425}",
+	'Kheicoptic' => "\x{03E6}",
+	'Khook' => "\x{0198}",
+	'Kjecyrillic' => "\x{040C}",
+	'Klinebelow' => "\x{1E34}",
+	'Kmonospace' => "\x{FF2B}",
+	'Koppacyrillic' => "\x{0480}",
+	'Koppagreek' => "\x{03DE}",
+	'Ksicyrillic' => "\x{046E}",
+	'Ksmall' => "\x{F76B}",
+	'LJ' => "\x{01C7}",
+	'LL' => "\x{F6BF}",
+	'Lcedilla' => "\x{013B}",
+	'Lcircle' => "\x{24C1}",
+	'Lcircumflexbelow' => "\x{1E3C}",
+	'Ldotaccent' => "\x{013F}",
+	'Ldotbelow' => "\x{1E36}",
+	'Ldotbelowmacron' => "\x{1E38}",
+	'Liwnarmenian' => "\x{053C}",
+	'Lj' => "\x{01C8}",
+	'Ljecyrillic' => "\x{0409}",
+	'Llinebelow' => "\x{1E3A}",
+	'Lmonospace' => "\x{FF2C}",
+	'Lslashsmall' => "\x{F6F9}",
+	'Lsmall' => "\x{F76C}",
+	'MBsquare' => "\x{3386}",
+	'Macron' => "\x{F6D0}",
+	'Macronsmall' => "\x{F7AF}",
+	'Macute' => "\x{1E3E}",
+	'Mcircle' => "\x{24C2}",
+	'Mdotaccent' => "\x{1E40}",
+	'Mdotbelow' => "\x{1E42}",
+	'Menarmenian' => "\x{0544}",
+	'Mmonospace' => "\x{FF2D}",
+	'Msmall' => "\x{F76D}",
+	'Mturned' => "\x{019C}",
+	'NJ' => "\x{01CA}",
+	'Ncedilla' => "\x{0145}",
+	'Ncircle' => "\x{24C3}",
+	'Ncircumflexbelow' => "\x{1E4A}",
+	'Ndotaccent' => "\x{1E44}",
+	'Ndotbelow' => "\x{1E46}",
+	'Nhookleft' => "\x{019D}",
+	'Nineroman' => "\x{2168}",
+	'Nj' => "\x{01CB}",
+	'Njecyrillic' => "\x{040A}",
+	'Nlinebelow' => "\x{1E48}",
+	'Nmonospace' => "\x{FF2E}",
+	'Nowarmenian' => "\x{0546}",
+	'Nsmall' => "\x{F76E}",
+	'Ntildesmall' => "\x{F7F1}",
+	'OEsmall' => "\x{F6FA}",
+	'Oacutesmall' => "\x{F7F3}",
+	'Obarredcyrillic' => "\x{04E8}",
+	'Obarreddieresiscyrillic' => "\x{04EA}",
+	'Ocaron' => "\x{01D1}",
+	'Ocenteredtilde' => "\x{019F}",
+	'Ocircle' => "\x{24C4}",
+	'Ocircumflexacute' => "\x{1ED0}",
+	'Ocircumflexdotbelow' => "\x{1ED8}",
+	'Ocircumflexgrave' => "\x{1ED2}",
+	'Ocircumflexhookabove' => "\x{1ED4}",
+	'Ocircumflexsmall' => "\x{F7F4}",
+	'Ocircumflextilde' => "\x{1ED6}",
+	'Ocyrillic' => "\x{041E}",
+	'Odblacute' => "\x{0150}",
+	'Odblgrave' => "\x{020C}",
+	'Odieresiscyrillic' => "\x{04E6}",
+	'Odieresissmall' => "\x{F7F6}",
+	'Odotbelow' => "\x{1ECC}",
+	'Ogoneksmall' => "\x{F6FB}",
+	'Ogravesmall' => "\x{F7F2}",
+	'Oharmenian' => "\x{0555}",
+	'Ohm' => "\x{2126}",
+	'Ohookabove' => "\x{1ECE}",
+	'Ohornacute' => "\x{1EDA}",
+	'Ohorndotbelow' => "\x{1EE2}",
+	'Ohorngrave' => "\x{1EDC}",
+	'Ohornhookabove' => "\x{1EDE}",
+	'Ohorntilde' => "\x{1EE0}",
+	'Oi' => "\x{01A2}",
+	'Oinvertedbreve' => "\x{020E}",
+	'Omacronacute' => "\x{1E52}",
+	'Omacrongrave' => "\x{1E50}",
+	'Omegacyrillic' => "\x{0460}",
+	'Omegagreek' => "\x{03A9}",
+	'Omegaroundcyrillic' => "\x{047A}",
+	'Omegatitlocyrillic' => "\x{047C}",
+	'Omonospace' => "\x{FF2F}",
+	'Oneroman' => "\x{2160}",
+	'Oogonek' => "\x{01EA}",
+	'Oogonekmacron' => "\x{01EC}",
+	'Oopen' => "\x{0186}",
+	'Oslashsmall' => "\x{F7F8}",
+	'Osmall' => "\x{F76F}",
+	'Ostrokeacute' => "\x{01FE}",
+	'Otcyrillic' => "\x{047E}",
+	'Otildeacute' => "\x{1E4C}",
+	'Otildedieresis' => "\x{1E4E}",
+	'Otildesmall' => "\x{F7F5}",
+	'Pacute' => "\x{1E54}",
+	'Pcircle' => "\x{24C5}",
+	'Pdotaccent' => "\x{1E56}",
+	'Pecyrillic' => "\x{041F}",
+	'Peharmenian' => "\x{054A}",
+	'Pemiddlehookcyrillic' => "\x{04A6}",
+	'Phook' => "\x{01A4}",
+	'Piwrarmenian' => "\x{0553}",
+	'Pmonospace' => "\x{FF30}",
+	'Psicyrillic' => "\x{0470}",
+	'Psmall' => "\x{F770}",
+	'Qcircle' => "\x{24C6}",
+	'Qmonospace' => "\x{FF31}",
+	'Qsmall' => "\x{F771}",
+	'Raarmenian' => "\x{054C}",
+	'Rcedilla' => "\x{0156}",
+	'Rcircle' => "\x{24C7}",
+	'Rdblgrave' => "\x{0210}",
+	'Rdotaccent' => "\x{1E58}",
+	'Rdotbelow' => "\x{1E5A}",
+	'Rdotbelowmacron' => "\x{1E5C}",
+	'Reharmenian' => "\x{0550}",
+	'Ringsmall' => "\x{F6FC}",
+	'Rinvertedbreve' => "\x{0212}",
+	'Rlinebelow' => "\x{1E5E}",
+	'Rmonospace' => "\x{FF32}",
+	'Rsmall' => "\x{F772}",
+	'Rsmallinverted' => "\x{0281}",
+	'Rsmallinvertedsuperior' => "\x{02B6}",
+	'Sacutedotaccent' => "\x{1E64}",
+	'Sampigreek' => "\x{03E0}",
+	'Scarondotaccent' => "\x{1E66}",
+	'Scaronsmall' => "\x{F6FD}",
+	'Schwa' => "\x{018F}",
+	'Schwacyrillic' => "\x{04D8}",
+	'Schwadieresiscyrillic' => "\x{04DA}",
+	'Scircle' => "\x{24C8}",
+	'Sdotaccent' => "\x{1E60}",
+	'Sdotbelow' => "\x{1E62}",
+	'Sdotbelowdotaccent' => "\x{1E68}",
+	'Seharmenian' => "\x{054D}",
+	'Sevenroman' => "\x{2166}",
+	'Shaarmenian' => "\x{0547}",
+	'Shacyrillic' => "\x{0428}",
+	'Shchacyrillic' => "\x{0429}",
+	'Sheicoptic' => "\x{03E2}",
+	'Shhacyrillic' => "\x{04BA}",
+	'Shimacoptic' => "\x{03EC}",
+	'Sixroman' => "\x{2165}",
+	'Smonospace' => "\x{FF33}",
+	'Softsigncyrillic' => "\x{042C}",
+	'Ssmall' => "\x{F773}",
+	'Stigmagreek' => "\x{03DA}",
+	'Tcedilla' => "\x{0162}",
+	'Tcircle' => "\x{24C9}",
+	'Tcircumflexbelow' => "\x{1E70}",
+	'Tdotaccent' => "\x{1E6A}",
+	'Tdotbelow' => "\x{1E6C}",
+	'Tecyrillic' => "\x{0422}",
+	'Tedescendercyrillic' => "\x{04AC}",
+	'Tenroman' => "\x{2169}",
+	'Tetsecyrillic' => "\x{04B4}",
+	'Thook' => "\x{01AC}",
+	'Thornsmall' => "\x{F7FE}",
+	'Threeroman' => "\x{2162}",
+	'Tildesmall' => "\x{F6FE}",
+	'Tiwnarmenian' => "\x{054F}",
+	'Tlinebelow' => "\x{1E6E}",
+	'Tmonospace' => "\x{FF34}",
+	'Toarmenian' => "\x{0539}",
+	'Tonefive' => "\x{01BC}",
+	'Tonesix' => "\x{0184}",
+	'Tonetwo' => "\x{01A7}",
+	'Tretroflexhook' => "\x{01AE}",
+	'Tsecyrillic' => "\x{0426}",
+	'Tshecyrillic' => "\x{040B}",
+	'Tsmall' => "\x{F774}",
+	'Twelveroman' => "\x{216B}",
+	'Tworoman' => "\x{2161}",
+	'Uacutesmall' => "\x{F7FA}",
+	'Ucaron' => "\x{01D3}",
+	'Ucircle' => "\x{24CA}",
+	'Ucircumflexbelow' => "\x{1E76}",
+	'Ucircumflexsmall' => "\x{F7FB}",
+	'Ucyrillic' => "\x{0423}",
+	'Udblacute' => "\x{0170}",
+	'Udblgrave' => "\x{0214}",
+	'Udieresisacute' => "\x{01D7}",
+	'Udieresisbelow' => "\x{1E72}",
+	'Udieresiscaron' => "\x{01D9}",
+	'Udieresiscyrillic' => "\x{04F0}",
+	'Udieresisgrave' => "\x{01DB}",
+	'Udieresismacron' => "\x{01D5}",
+	'Udieresissmall' => "\x{F7FC}",
+	'Udotbelow' => "\x{1EE4}",
+	'Ugravesmall' => "\x{F7F9}",
+	'Uhookabove' => "\x{1EE6}",
+	'Uhornacute' => "\x{1EE8}",
+	'Uhorndotbelow' => "\x{1EF0}",
+	'Uhorngrave' => "\x{1EEA}",
+	'Uhornhookabove' => "\x{1EEC}",
+	'Uhorntilde' => "\x{1EEE}",
+	'Uhungarumlautcyrillic' => "\x{04F2}",
+	'Uinvertedbreve' => "\x{0216}",
+	'Ukcyrillic' => "\x{0478}",
+	'Umacroncyrillic' => "\x{04EE}",
+	'Umacrondieresis' => "\x{1E7A}",
+	'Umonospace' => "\x{FF35}",
+	'Upsilonacutehooksymbolgreek' => "\x{03D3}",
+	'Upsilonafrican' => "\x{01B1}",
+	'Upsilondieresishooksymbolgreek' => "\x{03D4}",
+	'Upsilonhooksymbol' => "\x{03D2}",
+	'Ushortcyrillic' => "\x{040E}",
+	'Usmall' => "\x{F775}",
+	'Ustraightcyrillic' => "\x{04AE}",
+	'Ustraightstrokecyrillic' => "\x{04B0}",
+	'Utildeacute' => "\x{1E78}",
+	'Utildebelow' => "\x{1E74}",
+	'Vcircle' => "\x{24CB}",
+	'Vdotbelow' => "\x{1E7E}",
+	'Vecyrillic' => "\x{0412}",
+	'Vewarmenian' => "\x{054E}",
+	'Vhook' => "\x{01B2}",
+	'Vmonospace' => "\x{FF36}",
+	'Voarmenian' => "\x{0548}",
+	'Vsmall' => "\x{F776}",
+	'Vtilde' => "\x{1E7C}",
+	'Wcircle' => "\x{24CC}",
+	'Wdotaccent' => "\x{1E86}",
+	'Wdotbelow' => "\x{1E88}",
+	'Wmonospace' => "\x{FF37}",
+	'Wsmall' => "\x{F777}",
+	'Xcircle' => "\x{24CD}",
+	'Xdieresis' => "\x{1E8C}",
+	'Xdotaccent' => "\x{1E8A}",
+	'Xeharmenian' => "\x{053D}",
+	'Xmonospace' => "\x{FF38}",
+	'Xsmall' => "\x{F778}",
+	'Yacutesmall' => "\x{F7FD}",
+	'Yatcyrillic' => "\x{0462}",
+	'Ycircle' => "\x{24CE}",
+	'Ydieresissmall' => "\x{F7FF}",
+	'Ydotaccent' => "\x{1E8E}",
+	'Ydotbelow' => "\x{1EF4}",
+	'Yericyrillic' => "\x{042B}",
+	'Yerudieresiscyrillic' => "\x{04F8}",
+	'Yhook' => "\x{01B3}",
+	'Yhookabove' => "\x{1EF6}",
+	'Yiarmenian' => "\x{0545}",
+	'Yicyrillic' => "\x{0407}",
+	'Yiwnarmenian' => "\x{0552}",
+	'Ymonospace' => "\x{FF39}",
+	'Ysmall' => "\x{F779}",
+	'Ytilde' => "\x{1EF8}",
+	'Yusbigcyrillic' => "\x{046A}",
+	'Yusbigiotifiedcyrillic' => "\x{046C}",
+	'Yuslittlecyrillic' => "\x{0466}",
+	'Yuslittleiotifiedcyrillic' => "\x{0468}",
+	'Zaarmenian' => "\x{0536}",
+	'Zcaronsmall' => "\x{F6FF}",
+	'Zcircle' => "\x{24CF}",
+	'Zcircumflex' => "\x{1E90}",
+	'Zdot' => "\x{017B}",
+	'Zdotbelow' => "\x{1E92}",
+	'Zecyrillic' => "\x{0417}",
+	'Zedescendercyrillic' => "\x{0498}",
+	'Zedieresiscyrillic' => "\x{04DE}",
+	'Zhearmenian' => "\x{053A}",
+	'Zhebrevecyrillic' => "\x{04C1}",
+	'Zhecyrillic' => "\x{0416}",
+	'Zhedescendercyrillic' => "\x{0496}",
+	'Zhedieresiscyrillic' => "\x{04DC}",
+	'Zlinebelow' => "\x{1E94}",
+	'Zmonospace' => "\x{FF3A}",
+	'Zsmall' => "\x{F77A}",
+	'Zstroke' => "\x{01B5}",
+	'aabengali' => "\x{0986}",
+	'aadeva' => "\x{0906}",
+	'aagujarati' => "\x{0A86}",
+	'aagurmukhi' => "\x{0A06}",
+	'aamatragurmukhi' => "\x{0A3E}",
+	'aarusquare' => "\x{3303}",
+	'aavowelsignbengali' => "\x{09BE}",
+	'aavowelsigndeva' => "\x{093E}",
+	'aavowelsigngujarati' => "\x{0ABE}",
+	'abbreviationmarkarmenian' => "\x{055F}",
+	'abbreviationsigndeva' => "\x{0970}",
+	'abengali' => "\x{0985}",
+	'abopomofo' => "\x{311A}",
+	'abreveacute' => "\x{1EAF}",
+	'abrevecyrillic' => "\x{04D1}",
+	'abrevedotbelow' => "\x{1EB7}",
+	'abrevegrave' => "\x{1EB1}",
+	'abrevehookabove' => "\x{1EB3}",
+	'abrevetilde' => "\x{1EB5}",
+	'acaron' => "\x{01CE}",
+	'acircle' => "\x{24D0}",
+	'acircumflexacute' => "\x{1EA5}",
+	'acircumflexdotbelow' => "\x{1EAD}",
+	'acircumflexgrave' => "\x{1EA7}",
+	'acircumflexhookabove' => "\x{1EA9}",
+	'acircumflextilde' => "\x{1EAB}",
+	'acutebelowcmb' => "\x{0317}",
+	'acutecmb' => "\x{0301}",
+	'acutedeva' => "\x{0954}",
+	'acutelowmod' => "\x{02CF}",
+	'acutetonecmb' => "\x{0341}",
+	'acyrillic' => "\x{0430}",
+	'adblgrave' => "\x{0201}",
+	'addakgurmukhi' => "\x{0A71}",
+	'adeva' => "\x{0905}",
+	'adieresiscyrillic' => "\x{04D3}",
+	'adieresismacron' => "\x{01DF}",
+	'adotbelow' => "\x{1EA1}",
+	'adotmacron' => "\x{01E1}",
+	'aekorean' => "\x{3150}",
+	'aemacron' => "\x{01E3}",
+	'afii08941' => "\x{20A4}",
+	'afii10063' => "\x{F6C4}",
+	'afii10064' => "\x{F6C5}",
+	'afii10192' => "\x{F6C6}",
+	'afii10831' => "\x{F6C7}",
+	'afii10832' => "\x{F6C8}",
+	'agujarati' => "\x{0A85}",
+	'agurmukhi' => "\x{0A05}",
+	'ahiragana' => "\x{3042}",
+	'ahookabove' => "\x{1EA3}",
+	'aibengali' => "\x{0990}",
+	'aibopomofo' => "\x{311E}",
+	'aideva' => "\x{0910}",
+	'aiecyrillic' => "\x{04D5}",
+	'aigujarati' => "\x{0A90}",
+	'aigurmukhi' => "\x{0A10}",
+	'aimatragurmukhi' => "\x{0A48}",
+	'ainarabic' => "\x{0639}",
+	'ainfinalarabic' => "\x{FECA}",
+	'aininitialarabic' => "\x{FECB}",
+	'ainmedialarabic' => "\x{FECC}",
+	'ainvertedbreve' => "\x{0203}",
+	'aivowelsignbengali' => "\x{09C8}",
+	'aivowelsigndeva' => "\x{0948}",
+	'aivowelsigngujarati' => "\x{0AC8}",
+	'akatakana' => "\x{30A2}",
+	'akatakanahalfwidth' => "\x{FF71}",
+	'akorean' => "\x{314F}",
+	'alef' => "\x{05D0}",
+	'alefarabic' => "\x{0627}",
+	'alefdageshhebrew' => "\x{FB30}",
+	'aleffinalarabic' => "\x{FE8E}",
+	'alefhamzaabovearabic' => "\x{0623}",
+	'alefhamzaabovefinalarabic' => "\x{FE84}",
+	'alefhamzabelowarabic' => "\x{0625}",
+	'alefhamzabelowfinalarabic' => "\x{FE88}",
+	'alefhebrew' => "\x{05D0}",
+	'aleflamedhebrew' => "\x{FB4F}",
+	'alefmaddaabovearabic' => "\x{0622}",
+	'alefmaddaabovefinalarabic' => "\x{FE82}",
+	'alefmaksuraarabic' => "\x{0649}",
+	'alefmaksurafinalarabic' => "\x{FEF0}",
+	'alefmaksurainitialarabic' => "\x{FEF3}",
+	'alefmaksuramedialarabic' => "\x{FEF4}",
+	'alefpatahhebrew' => "\x{FB2E}",
+	'alefqamatshebrew' => "\x{FB2F}",
+	'allequal' => "\x{224C}",
+	'amonospace' => "\x{FF41}",
+	'ampersandmonospace' => "\x{FF06}",
+	'ampersandsmall' => "\x{F726}",
+	'amsquare' => "\x{33C2}",
+	'anbopomofo' => "\x{3122}",
+	'angbopomofo' => "\x{3124}",
+	'angkhankhuthai' => "\x{0E5A}",
+	'anglebracketleft' => "\x{3008}",
+	'anglebracketleftvertical' => "\x{FE3F}",
+	'anglebracketright' => "\x{3009}",
+	'anglebracketrightvertical' => "\x{FE40}",
+	'angstrom' => "\x{212B}",
+	'anudattadeva' => "\x{0952}",
+	'anusvarabengali' => "\x{0982}",
+	'anusvaradeva' => "\x{0902}",
+	'anusvaragujarati' => "\x{0A82}",
+	'apaatosquare' => "\x{3300}",
+	'aparen' => "\x{249C}",
+	'apostrophearmenian' => "\x{055A}",
+	'apostrophemod' => "\x{02BC}",
+	'apple' => "\x{F8FF}",
+	'approaches' => "\x{2250}",
+	'approxequalorimage' => "\x{2252}",
+	'approximatelyequal' => "\x{2245}",
+	'araeaekorean' => "\x{318E}",
+	'araeakorean' => "\x{318D}",
+	'arc' => "\x{2312}",
+	'arighthalfring' => "\x{1E9A}",
+	'aringbelow' => "\x{1E01}",
+	'arrowdashdown' => "\x{21E3}",
+	'arrowdashleft' => "\x{21E0}",
+	'arrowdashright' => "\x{21E2}",
+	'arrowdashup' => "\x{21E1}",
+	'arrowdownleft' => "\x{2199}",
+	'arrowdownright' => "\x{2198}",
+	'arrowdownwhite' => "\x{21E9}",
+	'arrowheaddownmod' => "\x{02C5}",
+	'arrowheadleftmod' => "\x{02C2}",
+	'arrowheadrightmod' => "\x{02C3}",
+	'arrowheadupmod' => "\x{02C4}",
+	'arrowhorizex' => "\x{F8E7}",
+	'arrowleftdbl' => "\x{21D0}",
+	'arrowleftdblstroke' => "\x{21CD}",
+	'arrowleftoverright' => "\x{21C6}",
+	'arrowleftwhite' => "\x{21E6}",
+	'arrowrightdblstroke' => "\x{21CF}",
+	'arrowrightheavy' => "\x{279E}",
+	'arrowrightoverleft' => "\x{21C4}",
+	'arrowrightwhite' => "\x{21E8}",
+	'arrowtableft' => "\x{21E4}",
+	'arrowtabright' => "\x{21E5}",
+	'arrowupdownbase' => "\x{21A8}",
+	'arrowupleft' => "\x{2196}",
+	'arrowupleftofdown' => "\x{21C5}",
+	'arrowupright' => "\x{2197}",
+	'arrowupwhite' => "\x{21E7}",
+	'arrowvertex' => "\x{F8E6}",
+	'asciicircummonospace' => "\x{FF3E}",
+	'asciitildemonospace' => "\x{FF5E}",
+	'ascript' => "\x{0251}",
+	'ascriptturned' => "\x{0252}",
+	'asmallhiragana' => "\x{3041}",
+	'asmallkatakana' => "\x{30A1}",
+	'asmallkatakanahalfwidth' => "\x{FF67}",
+	'asteriskaltonearabic' => "\x{066D}",
+	'asteriskarabic' => "\x{066D}",
+	'asteriskmonospace' => "\x{FF0A}",
+	'asterisksmall' => "\x{FE61}",
+	'asterism' => "\x{2042}",
+	'asuperior' => "\x{F6E9}",
+	'asymptoticallyequal' => "\x{2243}",
+	'atmonospace' => "\x{FF20}",
+	'atsmall' => "\x{FE6B}",
+	'aturned' => "\x{0250}",
+	'aubengali' => "\x{0994}",
+	'aubopomofo' => "\x{3120}",
+	'audeva' => "\x{0914}",
+	'augujarati' => "\x{0A94}",
+	'augurmukhi' => "\x{0A14}",
+	'aulengthmarkbengali' => "\x{09D7}",
+	'aumatragurmukhi' => "\x{0A4C}",
+	'auvowelsignbengali' => "\x{09CC}",
+	'auvowelsigndeva' => "\x{094C}",
+	'auvowelsigngujarati' => "\x{0ACC}",
+	'avagrahadeva' => "\x{093D}",
+	'aybarmenian' => "\x{0561}",
+	'ayin' => "\x{05E2}",
+	'ayinaltonehebrew' => "\x{FB20}",
+	'ayinhebrew' => "\x{05E2}",
+	'babengali' => "\x{09AC}",
+	'backslashmonospace' => "\x{FF3C}",
+	'badeva' => "\x{092C}",
+	'bagujarati' => "\x{0AAC}",
+	'bagurmukhi' => "\x{0A2C}",
+	'bahiragana' => "\x{3070}",
+	'bahtthai' => "\x{0E3F}",
+	'bakatakana' => "\x{30D0}",
+	'barmonospace' => "\x{FF5C}",
+	'bbopomofo' => "\x{3105}",
+	'bcircle' => "\x{24D1}",
+	'bdotaccent' => "\x{1E03}",
+	'bdotbelow' => "\x{1E05}",
+	'beamedsixteenthnotes' => "\x{266C}",
+	'because' => "\x{2235}",
+	'becyrillic' => "\x{0431}",
+	'beharabic' => "\x{0628}",
+	'behfinalarabic' => "\x{FE90}",
+	'behinitialarabic' => "\x{FE91}",
+	'behiragana' => "\x{3079}",
+	'behmedialarabic' => "\x{FE92}",
+	'behmeeminitialarabic' => "\x{FC9F}",
+	'behmeemisolatedarabic' => "\x{FC08}",
+	'behnoonfinalarabic' => "\x{FC6D}",
+	'bekatakana' => "\x{30D9}",
+	'benarmenian' => "\x{0562}",
+	'bet' => "\x{05D1}",
+	'betasymbolgreek' => "\x{03D0}",
+	'betdagesh' => "\x{FB31}",
+	'betdageshhebrew' => "\x{FB31}",
+	'bethebrew' => "\x{05D1}",
+	'betrafehebrew' => "\x{FB4C}",
+	'bhabengali' => "\x{09AD}",
+	'bhadeva' => "\x{092D}",
+	'bhagujarati' => "\x{0AAD}",
+	'bhagurmukhi' => "\x{0A2D}",
+	'bhook' => "\x{0253}",
+	'bihiragana' => "\x{3073}",
+	'bikatakana' => "\x{30D3}",
+	'bilabialclick' => "\x{0298}",
+	'bindigurmukhi' => "\x{0A02}",
+	'birusquare' => "\x{3331}",
+	'blackcircle' => "\x{25CF}",
+	'blackdiamond' => "\x{25C6}",
+	'blackdownpointingtriangle' => "\x{25BC}",
+	'blackleftpointingpointer' => "\x{25C4}",
+	'blackleftpointingtriangle' => "\x{25C0}",
+	'blacklenticularbracketleft' => "\x{3010}",
+	'blacklenticularbracketleftvertical' => "\x{FE3B}",
+	'blacklenticularbracketright' => "\x{3011}",
+	'blacklenticularbracketrightvertical' => "\x{FE3C}",
+	'blacklowerlefttriangle' => "\x{25E3}",
+	'blacklowerrighttriangle' => "\x{25E2}",
+	'blackrectangle' => "\x{25AC}",
+	'blackrightpointingpointer' => "\x{25BA}",
+	'blackrightpointingtriangle' => "\x{25B6}",
+	'blacksmallsquare' => "\x{25AA}",
+	'blacksmilingface' => "\x{263B}",
+	'blacksquare' => "\x{25A0}",
+	'blackstar' => "\x{2605}",
+	'blackupperlefttriangle' => "\x{25E4}",
+	'blackupperrighttriangle' => "\x{25E5}",
+	'blackuppointingsmalltriangle' => "\x{25B4}",
+	'blackuppointingtriangle' => "\x{25B2}",
+	'blank' => "\x{2423}",
+	'blinebelow' => "\x{1E07}",
+	'bmonospace' => "\x{FF42}",
+	'bobaimaithai' => "\x{0E1A}",
+	'bohiragana' => "\x{307C}",
+	'bokatakana' => "\x{30DC}",
+	'bparen' => "\x{249D}",
+	'bqsquare' => "\x{33C3}",
+	'braceex' => "\x{F8F4}",
+	'braceleftbt' => "\x{F8F3}",
+	'braceleftmid' => "\x{F8F2}",
+	'braceleftmonospace' => "\x{FF5B}",
+	'braceleftsmall' => "\x{FE5B}",
+	'bracelefttp' => "\x{F8F1}",
+	'braceleftvertical' => "\x{FE37}",
+	'bracerightbt' => "\x{F8FE}",
+	'bracerightmid' => "\x{F8FD}",
+	'bracerightmonospace' => "\x{FF5D}",
+	'bracerightsmall' => "\x{FE5C}",
+	'bracerighttp' => "\x{F8FC}",
+	'bracerightvertical' => "\x{FE38}",
+	'bracketleftbt' => "\x{F8F0}",
+	'bracketleftex' => "\x{F8EF}",
+	'bracketleftmonospace' => "\x{FF3B}",
+	'bracketlefttp' => "\x{F8EE}",
+	'bracketrightbt' => "\x{F8FB}",
+	'bracketrightex' => "\x{F8FA}",
+	'bracketrightmonospace' => "\x{FF3D}",
+	'bracketrighttp' => "\x{F8F9}",
+	'brevebelowcmb' => "\x{032E}",
+	'brevecmb' => "\x{0306}",
+	'breveinvertedbelowcmb' => "\x{032F}",
+	'breveinvertedcmb' => "\x{0311}",
+	'breveinverteddoublecmb' => "\x{0361}",
+	'bridgebelowcmb' => "\x{032A}",
+	'bridgeinvertedbelowcmb' => "\x{033A}",
+	'bstroke' => "\x{0180}",
+	'bsuperior' => "\x{F6EA}",
+	'btopbar' => "\x{0183}",
+	'buhiragana' => "\x{3076}",
+	'bukatakana' => "\x{30D6}",
+	'bulletinverse' => "\x{25D8}",
+	'bulletoperator' => "\x{2219}",
+	'bullseye' => "\x{25CE}",
+	'caarmenian' => "\x{056E}",
+	'cabengali' => "\x{099A}",
+	'cadeva' => "\x{091A}",
+	'cagujarati' => "\x{0A9A}",
+	'cagurmukhi' => "\x{0A1A}",
+	'calsquare' => "\x{3388}",
+	'candrabindubengali' => "\x{0981}",
+	'candrabinducmb' => "\x{0310}",
+	'candrabindudeva' => "\x{0901}",
+	'candrabindugujarati' => "\x{0A81}",
+	'capslock' => "\x{21EA}",
+	'careof' => "\x{2105}",
+	'caronbelowcmb' => "\x{032C}",
+	'caroncmb' => "\x{030C}",
+	'cbopomofo' => "\x{3118}",
+	'ccedillaacute' => "\x{1E09}",
+	'ccircle' => "\x{24D2}",
+	'ccurl' => "\x{0255}",
+	'cdot' => "\x{010B}",
+	'cdsquare' => "\x{33C5}",
+	'cedillacmb' => "\x{0327}",
+	'centigrade' => "\x{2103}",
+	'centinferior' => "\x{F6DF}",
+	'centmonospace' => "\x{FFE0}",
+	'centoldstyle' => "\x{F7A2}",
+	'centsuperior' => "\x{F6E0}",
+	'chaarmenian' => "\x{0579}",
+	'chabengali' => "\x{099B}",
+	'chadeva' => "\x{091B}",
+	'chagujarati' => "\x{0A9B}",
+	'chagurmukhi' => "\x{0A1B}",
+	'chbopomofo' => "\x{3114}",
+	'cheabkhasiancyrillic' => "\x{04BD}",
+	'checkmark' => "\x{2713}",
+	'checyrillic' => "\x{0447}",
+	'chedescenderabkhasiancyrillic' => "\x{04BF}",
+	'chedescendercyrillic' => "\x{04B7}",
+	'chedieresiscyrillic' => "\x{04F5}",
+	'cheharmenian' => "\x{0573}",
+	'chekhakassiancyrillic' => "\x{04CC}",
+	'cheverticalstrokecyrillic' => "\x{04B9}",
+	'chieuchacirclekorean' => "\x{3277}",
+	'chieuchaparenkorean' => "\x{3217}",
+	'chieuchcirclekorean' => "\x{3269}",
+	'chieuchkorean' => "\x{314A}",
+	'chieuchparenkorean' => "\x{3209}",
+	'chochangthai' => "\x{0E0A}",
+	'chochanthai' => "\x{0E08}",
+	'chochingthai' => "\x{0E09}",
+	'chochoethai' => "\x{0E0C}",
+	'chook' => "\x{0188}",
+	'cieucacirclekorean' => "\x{3276}",
+	'cieucaparenkorean' => "\x{3216}",
+	'cieuccirclekorean' => "\x{3268}",
+	'cieuckorean' => "\x{3148}",
+	'cieucparenkorean' => "\x{3208}",
+	'cieucuparenkorean' => "\x{321C}",
+	'circleot' => "\x{2299}",
+	'circlepostalmark' => "\x{3036}",
+	'circlewithlefthalfblack' => "\x{25D0}",
+	'circlewithrighthalfblack' => "\x{25D1}",
+	'circumflexbelowcmb' => "\x{032D}",
+	'circumflexcmb' => "\x{0302}",
+	'clear' => "\x{2327}",
+	'clickalveolar' => "\x{01C2}",
+	'clickdental' => "\x{01C0}",
+	'clicklateral' => "\x{01C1}",
+	'clickretroflex' => "\x{01C3}",
+	'clubsuitblack' => "\x{2663}",
+	'clubsuitwhite' => "\x{2667}",
+	'cmcubedsquare' => "\x{33A4}",
+	'cmonospace' => "\x{FF43}",
+	'cmsquaredsquare' => "\x{33A0}",
+	'coarmenian' => "\x{0581}",
+	'colonmonospace' => "\x{FF1A}",
+	'colonsign' => "\x{20A1}",
+	'colonsmall' => "\x{FE55}",
+	'colontriangularhalfmod' => "\x{02D1}",
+	'colontriangularmod' => "\x{02D0}",
+	'commaabovecmb' => "\x{0313}",
+	'commaaboverightcmb' => "\x{0315}",
+	'commaaccent' => "\x{F6C3}",
+	'commaarabic' => "\x{060C}",
+	'commaarmenian' => "\x{055D}",
+	'commainferior' => "\x{F6E1}",
+	'commamonospace' => "\x{FF0C}",
+	'commareversedabovecmb' => "\x{0314}",
+	'commareversedmod' => "\x{02BD}",
+	'commasmall' => "\x{FE50}",
+	'commasuperior' => "\x{F6E2}",
+	'commaturnedabovecmb' => "\x{0312}",
+	'commaturnedmod' => "\x{02BB}",
+	'compass' => "\x{263C}",
+	'contourintegral' => "\x{222E}",
+	'control' => "\x{2303}",
+	'controlACK' => "\x{0006}",
+	'controlBEL' => "\x{0007}",
+	'controlBS' => "\x{0008}",
+	'controlCAN' => "\x{0018}",
+	'controlCR' => "\x{000D}",
+	'controlDC1' => "\x{0011}",
+	'controlDC2' => "\x{0012}",
+	'controlDC3' => "\x{0013}",
+	'controlDC4' => "\x{0014}",
+	'controlDEL' => "\x{007F}",
+	'controlDLE' => "\x{0010}",
+	'controlEM' => "\x{0019}",
+	'controlENQ' => "\x{0005}",
+	'controlEOT' => "\x{0004}",
+	'controlESC' => "\x{001B}",
+	'controlETB' => "\x{0017}",
+	'controlETX' => "\x{0003}",
+	'controlFF' => "\x{000C}",
+	'controlFS' => "\x{001C}",
+	'controlGS' => "\x{001D}",
+	'controlHT' => "\x{0009}",
+	'controlLF' => "\x{000A}",
+	'controlNAK' => "\x{0015}",
+	'controlRS' => "\x{001E}",
+	'controlSI' => "\x{000F}",
+	'controlSO' => "\x{000E}",
+	'controlSOT' => "\x{0002}",
+	'controlSTX' => "\x{0001}",
+	'controlSUB' => "\x{001A}",
+	'controlSYN' => "\x{0016}",
+	'controlUS' => "\x{001F}",
+	'controlVT' => "\x{000B}",
+	'copyrightsans' => "\x{F8E9}",
+	'copyrightserif' => "\x{F6D9}",
+	'cornerbracketleft' => "\x{300C}",
+	'cornerbracketlefthalfwidth' => "\x{FF62}",
+	'cornerbracketleftvertical' => "\x{FE41}",
+	'cornerbracketright' => "\x{300D}",
+	'cornerbracketrighthalfwidth' => "\x{FF63}",
+	'cornerbracketrightvertical' => "\x{FE42}",
+	'corporationsquare' => "\x{337F}",
+	'cosquare' => "\x{33C7}",
+	'coverkgsquare' => "\x{33C6}",
+	'cparen' => "\x{249E}",
+	'cruzeiro' => "\x{20A2}",
+	'cstretched' => "\x{0297}",
+	'curlyand' => "\x{22CF}",
+	'curlyor' => "\x{22CE}",
+	'cyrBreve' => "\x{F6D1}",
+	'cyrFlex' => "\x{F6D2}",
+	'cyrbreve' => "\x{F6D4}",
+	'cyrflex' => "\x{F6D5}",
+	'daarmenian' => "\x{0564}",
+	'dabengali' => "\x{09A6}",
+	'dadarabic' => "\x{0636}",
+	'dadeva' => "\x{0926}",
+	'dadfinalarabic' => "\x{FEBE}",
+	'dadinitialarabic' => "\x{FEBF}",
+	'dadmedialarabic' => "\x{FEC0}",
+	'dagesh' => "\x{05BC}",
+	'dageshhebrew' => "\x{05BC}",
+	'dagujarati' => "\x{0AA6}",
+	'dagurmukhi' => "\x{0A26}",
+	'dahiragana' => "\x{3060}",
+	'dakatakana' => "\x{30C0}",
+	'dalarabic' => "\x{062F}",
+	'dalet' => "\x{05D3}",
+	'daletdagesh' => "\x{FB33}",
+	'daletdageshhebrew' => "\x{FB33}",
+	'dalethatafpatah' => "\x{05D3}\x{05B2}",
+	'dalethatafpatahhebrew' => "\x{05D3}\x{05B2}",
+	'dalethatafsegol' => "\x{05D3}\x{05B1}",
+	'dalethatafsegolhebrew' => "\x{05D3}\x{05B1}",
+	'dalethebrew' => "\x{05D3}",
+	'dalethiriq' => "\x{05D3}\x{05B4}",
+	'dalethiriqhebrew' => "\x{05D3}\x{05B4}",
+	'daletholam' => "\x{05D3}\x{05B9}",
+	'daletholamhebrew' => "\x{05D3}\x{05B9}",
+	'daletpatah' => "\x{05D3}\x{05B7}",
+	'daletpatahhebrew' => "\x{05D3}\x{05B7}",
+	'daletqamats' => "\x{05D3}\x{05B8}",
+	'daletqamatshebrew' => "\x{05D3}\x{05B8}",
+	'daletqubuts' => "\x{05D3}\x{05BB}",
+	'daletqubutshebrew' => "\x{05D3}\x{05BB}",
+	'daletsegol' => "\x{05D3}\x{05B6}",
+	'daletsegolhebrew' => "\x{05D3}\x{05B6}",
+	'daletsheva' => "\x{05D3}\x{05B0}",
+	'daletshevahebrew' => "\x{05D3}\x{05B0}",
+	'dalettsere' => "\x{05D3}\x{05B5}",
+	'dalettserehebrew' => "\x{05D3}\x{05B5}",
+	'dalfinalarabic' => "\x{FEAA}",
+	'dammaarabic' => "\x{064F}",
+	'dammalowarabic' => "\x{064F}",
+	'dammatanaltonearabic' => "\x{064C}",
+	'dammatanarabic' => "\x{064C}",
+	'danda' => "\x{0964}",
+	'dargahebrew' => "\x{05A7}",
+	'dargalefthebrew' => "\x{05A7}",
+	'dasiapneumatacyrilliccmb' => "\x{0485}",
+	'dblGrave' => "\x{F6D3}",
+	'dblanglebracketleft' => "\x{300A}",
+	'dblanglebracketleftvertical' => "\x{FE3D}",
+	'dblanglebracketright' => "\x{300B}",
+	'dblanglebracketrightvertical' => "\x{FE3E}",
+	'dblarchinvertedbelowcmb' => "\x{032B}",
+	'dblarrowleft' => "\x{21D4}",
+	'dblarrowright' => "\x{21D2}",
+	'dbldanda' => "\x{0965}",
+	'dblgrave' => "\x{F6D6}",
+	'dblgravecmb' => "\x{030F}",
+	'dblintegral' => "\x{222C}",
+	'dbllowline' => "\x{2017}",
+	'dbllowlinecmb' => "\x{0333}",
+	'dbloverlinecmb' => "\x{033F}",
+	'dblprimemod' => "\x{02BA}",
+	'dblverticalbar' => "\x{2016}",
+	'dblverticallineabovecmb' => "\x{030E}",
+	'dbopomofo' => "\x{3109}",
+	'dbsquare' => "\x{33C8}",
+	'dcedilla' => "\x{1E11}",
+	'dcircle' => "\x{24D3}",
+	'dcircumflexbelow' => "\x{1E13}",
+	'ddabengali' => "\x{09A1}",
+	'ddadeva' => "\x{0921}",
+	'ddagujarati' => "\x{0AA1}",
+	'ddagurmukhi' => "\x{0A21}",
+	'ddalarabic' => "\x{0688}",
+	'ddalfinalarabic' => "\x{FB89}",
+	'dddhadeva' => "\x{095C}",
+	'ddhabengali' => "\x{09A2}",
+	'ddhadeva' => "\x{0922}",
+	'ddhagujarati' => "\x{0AA2}",
+	'ddhagurmukhi' => "\x{0A22}",
+	'ddotaccent' => "\x{1E0B}",
+	'ddotbelow' => "\x{1E0D}",
+	'decimalseparatorarabic' => "\x{066B}",
+	'decimalseparatorpersian' => "\x{066B}",
+	'decyrillic' => "\x{0434}",
+	'dehihebrew' => "\x{05AD}",
+	'dehiragana' => "\x{3067}",
+	'deicoptic' => "\x{03EF}",
+	'dekatakana' => "\x{30C7}",
+	'deleteleft' => "\x{232B}",
+	'deleteright' => "\x{2326}",
+	'deltaturned' => "\x{018D}",
+	'denominatorminusonenumeratorbengali' => "\x{09F8}",
+	'dezh' => "\x{02A4}",
+	'dhabengali' => "\x{09A7}",
+	'dhadeva' => "\x{0927}",
+	'dhagujarati' => "\x{0AA7}",
+	'dhagurmukhi' => "\x{0A27}",
+	'dhook' => "\x{0257}",
+	'dialytikatonos' => "\x{0385}",
+	'dialytikatonoscmb' => "\x{0344}",
+	'diamondsuitwhite' => "\x{2662}",
+	'dieresisacute' => "\x{F6D7}",
+	'dieresisbelowcmb' => "\x{0324}",
+	'dieresiscmb' => "\x{0308}",
+	'dieresisgrave' => "\x{F6D8}",
+	'dihiragana' => "\x{3062}",
+	'dikatakana' => "\x{30C2}",
+	'dittomark' => "\x{3003}",
+	'divides' => "\x{2223}",
+	'divisionslash' => "\x{2215}",
+	'djecyrillic' => "\x{0452}",
+	'dlinebelow' => "\x{1E0F}",
+	'dlsquare' => "\x{3397}",
+	'dmacron' => "\x{0111}",
+	'dmonospace' => "\x{FF44}",
+	'dochadathai' => "\x{0E0E}",
+	'dodekthai' => "\x{0E14}",
+	'dohiragana' => "\x{3069}",
+	'dokatakana' => "\x{30C9}",
+	'dollarinferior' => "\x{F6E3}",
+	'dollarmonospace' => "\x{FF04}",
+	'dollaroldstyle' => "\x{F724}",
+	'dollarsmall' => "\x{FE69}",
+	'dollarsuperior' => "\x{F6E4}",
+	'dorusquare' => "\x{3326}",
+	'dotaccentcmb' => "\x{0307}",
+	'dotbelowcmb' => "\x{0323}",
+	'dotkatakana' => "\x{30FB}",
+	'dotlessj' => "\x{F6BE}",
+	'dotlessjstrokehook' => "\x{0284}",
+	'dottedcircle' => "\x{25CC}",
+	'doubleyodpatah' => "\x{FB1F}",
+	'doubleyodpatahhebrew' => "\x{FB1F}",
+	'downtackbelowcmb' => "\x{031E}",
+	'downtackmod' => "\x{02D5}",
+	'dparen' => "\x{249F}",
+	'dsuperior' => "\x{F6EB}",
+	'dtail' => "\x{0256}",
+	'dtopbar' => "\x{018C}",
+	'duhiragana' => "\x{3065}",
+	'dukatakana' => "\x{30C5}",
+	'dz' => "\x{01F3}",
+	'dzaltone' => "\x{02A3}",
+	'dzcaron' => "\x{01C6}",
+	'dzcurl' => "\x{02A5}",
+	'dzeabkhasiancyrillic' => "\x{04E1}",
+	'dzecyrillic' => "\x{0455}",
+	'dzhecyrillic' => "\x{045F}",
+	'earth' => "\x{2641}",
+	'ebengali' => "\x{098F}",
+	'ebopomofo' => "\x{311C}",
+	'ecandradeva' => "\x{090D}",
+	'ecandragujarati' => "\x{0A8D}",
+	'ecandravowelsigndeva' => "\x{0945}",
+	'ecandravowelsigngujarati' => "\x{0AC5}",
+	'ecedillabreve' => "\x{1E1D}",
+	'echarmenian' => "\x{0565}",
+	'echyiwnarmenian' => "\x{0587}",
+	'ecircle' => "\x{24D4}",
+	'ecircumflexacute' => "\x{1EBF}",
+	'ecircumflexbelow' => "\x{1E19}",
+	'ecircumflexdotbelow' => "\x{1EC7}",
+	'ecircumflexgrave' => "\x{1EC1}",
+	'ecircumflexhookabove' => "\x{1EC3}",
+	'ecircumflextilde' => "\x{1EC5}",
+	'ecyrillic' => "\x{0454}",
+	'edblgrave' => "\x{0205}",
+	'edeva' => "\x{090F}",
+	'edot' => "\x{0117}",
+	'edotbelow' => "\x{1EB9}",
+	'eegurmukhi' => "\x{0A0F}",
+	'eematragurmukhi' => "\x{0A47}",
+	'efcyrillic' => "\x{0444}",
+	'egujarati' => "\x{0A8F}",
+	'eharmenian' => "\x{0567}",
+	'ehbopomofo' => "\x{311D}",
+	'ehiragana' => "\x{3048}",
+	'ehookabove' => "\x{1EBB}",
+	'eibopomofo' => "\x{311F}",
+	'eightarabic' => "\x{0668}",
+	'eightbengali' => "\x{09EE}",
+	'eightcircle' => "\x{2467}",
+	'eightcircleinversesansserif' => "\x{2791}",
+	'eightdeva' => "\x{096E}",
+	'eighteencircle' => "\x{2471}",
+	'eighteenparen' => "\x{2485}",
+	'eighteenperiod' => "\x{2499}",
+	'eightgujarati' => "\x{0AEE}",
+	'eightgurmukhi' => "\x{0A6E}",
+	'eighthackarabic' => "\x{0668}",
+	'eighthangzhou' => "\x{3028}",
+	'eighthnotebeamed' => "\x{266B}",
+	'eightideographicparen' => "\x{3227}",
+	'eightinferior' => "\x{2088}",
+	'eightmonospace' => "\x{FF18}",
+	'eightoldstyle' => "\x{F738}",
+	'eightparen' => "\x{247B}",
+	'eightperiod' => "\x{248F}",
+	'eightpersian' => "\x{06F8}",
+	'eightroman' => "\x{2177}",
+	'eightsuperior' => "\x{2078}",
+	'eightthai' => "\x{0E58}",
+	'einvertedbreve' => "\x{0207}",
+	'eiotifiedcyrillic' => "\x{0465}",
+	'ekatakana' => "\x{30A8}",
+	'ekatakanahalfwidth' => "\x{FF74}",
+	'ekonkargurmukhi' => "\x{0A74}",
+	'ekorean' => "\x{3154}",
+	'elcyrillic' => "\x{043B}",
+	'elevencircle' => "\x{246A}",
+	'elevenparen' => "\x{247E}",
+	'elevenperiod' => "\x{2492}",
+	'elevenroman' => "\x{217A}",
+	'ellipsisvertical' => "\x{22EE}",
+	'emacronacute' => "\x{1E17}",
+	'emacrongrave' => "\x{1E15}",
+	'emcyrillic' => "\x{043C}",
+	'emdashvertical' => "\x{FE31}",
+	'emonospace' => "\x{FF45}",
+	'emphasismarkarmenian' => "\x{055B}",
+	'enbopomofo' => "\x{3123}",
+	'encyrillic' => "\x{043D}",
+	'endashvertical' => "\x{FE32}",
+	'endescendercyrillic' => "\x{04A3}",
+	'engbopomofo' => "\x{3125}",
+	'enghecyrillic' => "\x{04A5}",
+	'enhookcyrillic' => "\x{04C8}",
+	'enspace' => "\x{2002}",
+	'eokorean' => "\x{3153}",
+	'eopen' => "\x{025B}",
+	'eopenclosed' => "\x{029A}",
+	'eopenreversed' => "\x{025C}",
+	'eopenreversedclosed' => "\x{025E}",
+	'eopenreversedhook' => "\x{025D}",
+	'eparen' => "\x{24A0}",
+	'equalmonospace' => "\x{FF1D}",
+	'equalsmall' => "\x{FE66}",
+	'equalsuperior' => "\x{207C}",
+	'erbopomofo' => "\x{3126}",
+	'ercyrillic' => "\x{0440}",
+	'ereversed' => "\x{0258}",
+	'ereversedcyrillic' => "\x{044D}",
+	'escyrillic' => "\x{0441}",
+	'esdescendercyrillic' => "\x{04AB}",
+	'esh' => "\x{0283}",
+	'eshcurl' => "\x{0286}",
+	'eshortdeva' => "\x{090E}",
+	'eshortvowelsigndeva' => "\x{0946}",
+	'eshreversedloop' => "\x{01AA}",
+	'eshsquatreversed' => "\x{0285}",
+	'esmallhiragana' => "\x{3047}",
+	'esmallkatakana' => "\x{30A7}",
+	'esmallkatakanahalfwidth' => "\x{FF6A}",
+	'esuperior' => "\x{F6EC}",
+	'etarmenian' => "\x{0568}",
+	'etilde' => "\x{1EBD}",
+	'etildebelow' => "\x{1E1B}",
+	'etnahtafoukhhebrew' => "\x{0591}",
+	'etnahtafoukhlefthebrew' => "\x{0591}",
+	'etnahtahebrew' => "\x{0591}",
+	'etnahtalefthebrew' => "\x{0591}",
+	'eturned' => "\x{01DD}",
+	'eukorean' => "\x{3161}",
+	'euro' => "\x{20AC}",
+	'evowelsignbengali' => "\x{09C7}",
+	'evowelsigndeva' => "\x{0947}",
+	'evowelsigngujarati' => "\x{0AC7}",
+	'exclamarmenian' => "\x{055C}",
+	'exclamdownsmall' => "\x{F7A1}",
+	'exclammonospace' => "\x{FF01}",
+	'exclamsmall' => "\x{F721}",
+	'ezh' => "\x{0292}",
+	'ezhcaron' => "\x{01EF}",
+	'ezhcurl' => "\x{0293}",
+	'ezhreversed' => "\x{01B9}",
+	'ezhtail' => "\x{01BA}",
+	'fadeva' => "\x{095E}",
+	'fagurmukhi' => "\x{0A5E}",
+	'fahrenheit' => "\x{2109}",
+	'fathaarabic' => "\x{064E}",
+	'fathalowarabic' => "\x{064E}",
+	'fathatanarabic' => "\x{064B}",
+	'fbopomofo' => "\x{3108}",
+	'fcircle' => "\x{24D5}",
+	'fdotaccent' => "\x{1E1F}",
+	'feharabic' => "\x{0641}",
+	'feharmenian' => "\x{0586}",
+	'fehfinalarabic' => "\x{FED2}",
+	'fehinitialarabic' => "\x{FED3}",
+	'fehmedialarabic' => "\x{FED4}",
+	'feicoptic' => "\x{03E5}",
+	'fifteencircle' => "\x{246E}",
+	'fifteenparen' => "\x{2482}",
+	'fifteenperiod' => "\x{2496}",
+	'finalkaf' => "\x{05DA}",
+	'finalkafdagesh' => "\x{FB3A}",
+	'finalkafdageshhebrew' => "\x{FB3A}",
+	'finalkafhebrew' => "\x{05DA}",
+	'finalkafqamats' => "\x{05DA}\x{05B8}",
+	'finalkafqamatshebrew' => "\x{05DA}\x{05B8}",
+	'finalkafsheva' => "\x{05DA}\x{05B0}",
+	'finalkafshevahebrew' => "\x{05DA}\x{05B0}",
+	'finalmem' => "\x{05DD}",
+	'finalmemhebrew' => "\x{05DD}",
+	'finalnun' => "\x{05DF}",
+	'finalnunhebrew' => "\x{05DF}",
+	'finalpe' => "\x{05E3}",
+	'finalpehebrew' => "\x{05E3}",
+	'finaltsadi' => "\x{05E5}",
+	'finaltsadihebrew' => "\x{05E5}",
+	'firsttonechinese' => "\x{02C9}",
+	'fisheye' => "\x{25C9}",
+	'fitacyrillic' => "\x{0473}",
+	'fivearabic' => "\x{0665}",
+	'fivebengali' => "\x{09EB}",
+	'fivecircle' => "\x{2464}",
+	'fivecircleinversesansserif' => "\x{278E}",
+	'fivedeva' => "\x{096B}",
+	'fivegujarati' => "\x{0AEB}",
+	'fivegurmukhi' => "\x{0A6B}",
+	'fivehackarabic' => "\x{0665}",
+	'fivehangzhou' => "\x{3025}",
+	'fiveideographicparen' => "\x{3224}",
+	'fiveinferior' => "\x{2085}",
+	'fivemonospace' => "\x{FF15}",
+	'fiveoldstyle' => "\x{F735}",
+	'fiveparen' => "\x{2478}",
+	'fiveperiod' => "\x{248C}",
+	'fivepersian' => "\x{06F5}",
+	'fiveroman' => "\x{2174}",
+	'fivesuperior' => "\x{2075}",
+	'fivethai' => "\x{0E55}",
+	'fmonospace' => "\x{FF46}",
+	'fmsquare' => "\x{3399}",
+	'fofanthai' => "\x{0E1F}",
+	'fofathai' => "\x{0E1D}",
+	'fongmanthai' => "\x{0E4F}",
+	'forall' => "\x{2200}",
+	'fourarabic' => "\x{0664}",
+	'fourbengali' => "\x{09EA}",
+	'fourcircle' => "\x{2463}",
+	'fourcircleinversesansserif' => "\x{278D}",
+	'fourdeva' => "\x{096A}",
+	'fourgujarati' => "\x{0AEA}",
+	'fourgurmukhi' => "\x{0A6A}",
+	'fourhackarabic' => "\x{0664}",
+	'fourhangzhou' => "\x{3024}",
+	'fourideographicparen' => "\x{3223}",
+	'fourinferior' => "\x{2084}",
+	'fourmonospace' => "\x{FF14}",
+	'fournumeratorbengali' => "\x{09F7}",
+	'fouroldstyle' => "\x{F734}",
+	'fourparen' => "\x{2477}",
+	'fourperiod' => "\x{248B}",
+	'fourpersian' => "\x{06F4}",
+	'fourroman' => "\x{2173}",
+	'foursuperior' => "\x{2074}",
+	'fourteencircle' => "\x{246D}",
+	'fourteenparen' => "\x{2481}",
+	'fourteenperiod' => "\x{2495}",
+	'fourthai' => "\x{0E54}",
+	'fourthtonechinese' => "\x{02CB}",
+	'fparen' => "\x{24A1}",
+	'gabengali' => "\x{0997}",
+	'gacute' => "\x{01F5}",
+	'gadeva' => "\x{0917}",
+	'gafarabic' => "\x{06AF}",
+	'gaffinalarabic' => "\x{FB93}",
+	'gafinitialarabic' => "\x{FB94}",
+	'gafmedialarabic' => "\x{FB95}",
+	'gagujarati' => "\x{0A97}",
+	'gagurmukhi' => "\x{0A17}",
+	'gahiragana' => "\x{304C}",
+	'gakatakana' => "\x{30AC}",
+	'gammalatinsmall' => "\x{0263}",
+	'gammasuperior' => "\x{02E0}",
+	'gangiacoptic' => "\x{03EB}",
+	'gbopomofo' => "\x{310D}",
+	'gcedilla' => "\x{0123}",
+	'gcircle' => "\x{24D6}",
+	'gdot' => "\x{0121}",
+	'gecyrillic' => "\x{0433}",
+	'gehiragana' => "\x{3052}",
+	'gekatakana' => "\x{30B2}",
+	'geometricallyequal' => "\x{2251}",
+	'gereshaccenthebrew' => "\x{059C}",
+	'gereshhebrew' => "\x{05F3}",
+	'gereshmuqdamhebrew' => "\x{059D}",
+	'gershayimaccenthebrew' => "\x{059E}",
+	'gershayimhebrew' => "\x{05F4}",
+	'getamark' => "\x{3013}",
+	'ghabengali' => "\x{0998}",
+	'ghadarmenian' => "\x{0572}",
+	'ghadeva' => "\x{0918}",
+	'ghagujarati' => "\x{0A98}",
+	'ghagurmukhi' => "\x{0A18}",
+	'ghainarabic' => "\x{063A}",
+	'ghainfinalarabic' => "\x{FECE}",
+	'ghaininitialarabic' => "\x{FECF}",
+	'ghainmedialarabic' => "\x{FED0}",
+	'ghemiddlehookcyrillic' => "\x{0495}",
+	'ghestrokecyrillic' => "\x{0493}",
+	'gheupturncyrillic' => "\x{0491}",
+	'ghhadeva' => "\x{095A}",
+	'ghhagurmukhi' => "\x{0A5A}",
+	'ghook' => "\x{0260}",
+	'ghzsquare' => "\x{3393}",
+	'gihiragana' => "\x{304E}",
+	'gikatakana' => "\x{30AE}",
+	'gimarmenian' => "\x{0563}",
+	'gimel' => "\x{05D2}",
+	'gimeldagesh' => "\x{FB32}",
+	'gimeldageshhebrew' => "\x{FB32}",
+	'gimelhebrew' => "\x{05D2}",
+	'gjecyrillic' => "\x{0453}",
+	'glottalinvertedstroke' => "\x{01BE}",
+	'glottalstop' => "\x{0294}",
+	'glottalstopinverted' => "\x{0296}",
+	'glottalstopmod' => "\x{02C0}",
+	'glottalstopreversed' => "\x{0295}",
+	'glottalstopreversedmod' => "\x{02C1}",
+	'glottalstopreversedsuperior' => "\x{02E4}",
+	'glottalstopstroke' => "\x{02A1}",
+	'glottalstopstrokereversed' => "\x{02A2}",
+	'gmacron' => "\x{1E21}",
+	'gmonospace' => "\x{FF47}",
+	'gohiragana' => "\x{3054}",
+	'gokatakana' => "\x{30B4}",
+	'gparen' => "\x{24A2}",
+	'gpasquare' => "\x{33AC}",
+	'gravebelowcmb' => "\x{0316}",
+	'gravecmb' => "\x{0300}",
+	'gravedeva' => "\x{0953}",
+	'gravelowmod' => "\x{02CE}",
+	'gravemonospace' => "\x{FF40}",
+	'gravetonecmb' => "\x{0340}",
+	'greaterequalorless' => "\x{22DB}",
+	'greatermonospace' => "\x{FF1E}",
+	'greaterorequivalent' => "\x{2273}",
+	'greaterorless' => "\x{2277}",
+	'greateroverequal' => "\x{2267}",
+	'greatersmall' => "\x{FE65}",
+	'gscript' => "\x{0261}",
+	'gstroke' => "\x{01E5}",
+	'guhiragana' => "\x{3050}",
+	'gukatakana' => "\x{30B0}",
+	'guramusquare' => "\x{3318}",
+	'gysquare' => "\x{33C9}",
+	'haabkhasiancyrillic' => "\x{04A9}",
+	'haaltonearabic' => "\x{06C1}",
+	'habengali' => "\x{09B9}",
+	'hadescendercyrillic' => "\x{04B3}",
+	'hadeva' => "\x{0939}",
+	'hagujarati' => "\x{0AB9}",
+	'hagurmukhi' => "\x{0A39}",
+	'haharabic' => "\x{062D}",
+	'hahfinalarabic' => "\x{FEA2}",
+	'hahinitialarabic' => "\x{FEA3}",
+	'hahiragana' => "\x{306F}",
+	'hahmedialarabic' => "\x{FEA4}",
+	'haitusquare' => "\x{332A}",
+	'hakatakana' => "\x{30CF}",
+	'hakatakanahalfwidth' => "\x{FF8A}",
+	'halantgurmukhi' => "\x{0A4D}",
+	'hamzaarabic' => "\x{0621}",
+	'hamzadammaarabic' => "\x{0621}\x{064F}",
+	'hamzadammatanarabic' => "\x{0621}\x{064C}",
+	'hamzafathaarabic' => "\x{0621}\x{064E}",
+	'hamzafathatanarabic' => "\x{0621}\x{064B}",
+	'hamzalowarabic' => "\x{0621}",
+	'hamzalowkasraarabic' => "\x{0621}\x{0650}",
+	'hamzalowkasratanarabic' => "\x{0621}\x{064D}",
+	'hamzasukunarabic' => "\x{0621}\x{0652}",
+	'hangulfiller' => "\x{3164}",
+	'hardsigncyrillic' => "\x{044A}",
+	'harpoonleftbarbup' => "\x{21BC}",
+	'harpoonrightbarbup' => "\x{21C0}",
+	'hasquare' => "\x{33CA}",
+	'hatafpatah' => "\x{05B2}",
+	'hatafpatah16' => "\x{05B2}",
+	'hatafpatah23' => "\x{05B2}",
+	'hatafpatah2f' => "\x{05B2}",
+	'hatafpatahhebrew' => "\x{05B2}",
+	'hatafpatahnarrowhebrew' => "\x{05B2}",
+	'hatafpatahquarterhebrew' => "\x{05B2}",
+	'hatafpatahwidehebrew' => "\x{05B2}",
+	'hatafqamats' => "\x{05B3}",
+	'hatafqamats1b' => "\x{05B3}",
+	'hatafqamats28' => "\x{05B3}",
+	'hatafqamats34' => "\x{05B3}",
+	'hatafqamatshebrew' => "\x{05B3}",
+	'hatafqamatsnarrowhebrew' => "\x{05B3}",
+	'hatafqamatsquarterhebrew' => "\x{05B3}",
+	'hatafqamatswidehebrew' => "\x{05B3}",
+	'hatafsegol' => "\x{05B1}",
+	'hatafsegol17' => "\x{05B1}",
+	'hatafsegol24' => "\x{05B1}",
+	'hatafsegol30' => "\x{05B1}",
+	'hatafsegolhebrew' => "\x{05B1}",
+	'hatafsegolnarrowhebrew' => "\x{05B1}",
+	'hatafsegolquarterhebrew' => "\x{05B1}",
+	'hatafsegolwidehebrew' => "\x{05B1}",
+	'hbopomofo' => "\x{310F}",
+	'hbrevebelow' => "\x{1E2B}",
+	'hcedilla' => "\x{1E29}",
+	'hcircle' => "\x{24D7}",
+	'hdieresis' => "\x{1E27}",
+	'hdotaccent' => "\x{1E23}",
+	'hdotbelow' => "\x{1E25}",
+	'he' => "\x{05D4}",
+	'heartsuitblack' => "\x{2665}",
+	'heartsuitwhite' => "\x{2661}",
+	'hedagesh' => "\x{FB34}",
+	'hedageshhebrew' => "\x{FB34}",
+	'hehaltonearabic' => "\x{06C1}",
+	'heharabic' => "\x{0647}",
+	'hehebrew' => "\x{05D4}",
+	'hehfinalaltonearabic' => "\x{FBA7}",
+	'hehfinalalttwoarabic' => "\x{FEEA}",
+	'hehfinalarabic' => "\x{FEEA}",
+	'hehhamzaabovefinalarabic' => "\x{FBA5}",
+	'hehhamzaaboveisolatedarabic' => "\x{FBA4}",
+	'hehinitialaltonearabic' => "\x{FBA8}",
+	'hehinitialarabic' => "\x{FEEB}",
+	'hehiragana' => "\x{3078}",
+	'hehmedialaltonearabic' => "\x{FBA9}",
+	'hehmedialarabic' => "\x{FEEC}",
+	'heiseierasquare' => "\x{337B}",
+	'hekatakana' => "\x{30D8}",
+	'hekatakanahalfwidth' => "\x{FF8D}",
+	'hekutaarusquare' => "\x{3336}",
+	'henghook' => "\x{0267}",
+	'herutusquare' => "\x{3339}",
+	'het' => "\x{05D7}",
+	'hethebrew' => "\x{05D7}",
+	'hhook' => "\x{0266}",
+	'hhooksuperior' => "\x{02B1}",
+	'hieuhacirclekorean' => "\x{327B}",
+	'hieuhaparenkorean' => "\x{321B}",
+	'hieuhcirclekorean' => "\x{326D}",
+	'hieuhkorean' => "\x{314E}",
+	'hieuhparenkorean' => "\x{320D}",
+	'hihiragana' => "\x{3072}",
+	'hikatakana' => "\x{30D2}",
+	'hikatakanahalfwidth' => "\x{FF8B}",
+	'hiriq' => "\x{05B4}",
+	'hiriq14' => "\x{05B4}",
+	'hiriq21' => "\x{05B4}",
+	'hiriq2d' => "\x{05B4}",
+	'hiriqhebrew' => "\x{05B4}",
+	'hiriqnarrowhebrew' => "\x{05B4}",
+	'hiriqquarterhebrew' => "\x{05B4}",
+	'hiriqwidehebrew' => "\x{05B4}",
+	'hlinebelow' => "\x{1E96}",
+	'hmonospace' => "\x{FF48}",
+	'hoarmenian' => "\x{0570}",
+	'hohipthai' => "\x{0E2B}",
+	'hohiragana' => "\x{307B}",
+	'hokatakana' => "\x{30DB}",
+	'hokatakanahalfwidth' => "\x{FF8E}",
+	'holam' => "\x{05B9}",
+	'holam19' => "\x{05B9}",
+	'holam26' => "\x{05B9}",
+	'holam32' => "\x{05B9}",
+	'holamhebrew' => "\x{05B9}",
+	'holamnarrowhebrew' => "\x{05B9}",
+	'holamquarterhebrew' => "\x{05B9}",
+	'holamwidehebrew' => "\x{05B9}",
+	'honokhukthai' => "\x{0E2E}",
+	'hookcmb' => "\x{0309}",
+	'hookpalatalizedbelowcmb' => "\x{0321}",
+	'hookretroflexbelowcmb' => "\x{0322}",
+	'hoonsquare' => "\x{3342}",
+	'horicoptic' => "\x{03E9}",
+	'horizontalbar' => "\x{2015}",
+	'horncmb' => "\x{031B}",
+	'hotsprings' => "\x{2668}",
+	'hparen' => "\x{24A3}",
+	'hsuperior' => "\x{02B0}",
+	'hturned' => "\x{0265}",
+	'huhiragana' => "\x{3075}",
+	'huiitosquare' => "\x{3333}",
+	'hukatakana' => "\x{30D5}",
+	'hukatakanahalfwidth' => "\x{FF8C}",
+	'hungarumlautcmb' => "\x{030B}",
+	'hv' => "\x{0195}",
+	'hypheninferior' => "\x{F6E5}",
+	'hyphenmonospace' => "\x{FF0D}",
+	'hyphensmall' => "\x{FE63}",
+	'hyphensuperior' => "\x{F6E6}",
+	'hyphentwo' => "\x{2010}",
+	'iacyrillic' => "\x{044F}",
+	'ibengali' => "\x{0987}",
+	'ibopomofo' => "\x{3127}",
+	'icaron' => "\x{01D0}",
+	'icircle' => "\x{24D8}",
+	'icyrillic' => "\x{0456}",
+	'idblgrave' => "\x{0209}",
+	'ideographearthcircle' => "\x{328F}",
+	'ideographfirecircle' => "\x{328B}",
+	'ideographicallianceparen' => "\x{323F}",
+	'ideographiccallparen' => "\x{323A}",
+	'ideographiccentrecircle' => "\x{32A5}",
+	'ideographicclose' => "\x{3006}",
+	'ideographiccomma' => "\x{3001}",
+	'ideographiccommaleft' => "\x{FF64}",
+	'ideographiccongratulationparen' => "\x{3237}",
+	'ideographiccorrectcircle' => "\x{32A3}",
+	'ideographicearthparen' => "\x{322F}",
+	'ideographicenterpriseparen' => "\x{323D}",
+	'ideographicexcellentcircle' => "\x{329D}",
+	'ideographicfestivalparen' => "\x{3240}",
+	'ideographicfinancialcircle' => "\x{3296}",
+	'ideographicfinancialparen' => "\x{3236}",
+	'ideographicfireparen' => "\x{322B}",
+	'ideographichaveparen' => "\x{3232}",
+	'ideographichighcircle' => "\x{32A4}",
+	'ideographiciterationmark' => "\x{3005}",
+	'ideographiclaborcircle' => "\x{3298}",
+	'ideographiclaborparen' => "\x{3238}",
+	'ideographicleftcircle' => "\x{32A7}",
+	'ideographiclowcircle' => "\x{32A6}",
+	'ideographicmedicinecircle' => "\x{32A9}",
+	'ideographicmetalparen' => "\x{322E}",
+	'ideographicmoonparen' => "\x{322A}",
+	'ideographicnameparen' => "\x{3234}",
+	'ideographicperiod' => "\x{3002}",
+	'ideographicprintcircle' => "\x{329E}",
+	'ideographicreachparen' => "\x{3243}",
+	'ideographicrepresentparen' => "\x{3239}",
+	'ideographicresourceparen' => "\x{323E}",
+	'ideographicrightcircle' => "\x{32A8}",
+	'ideographicsecretcircle' => "\x{3299}",
+	'ideographicselfparen' => "\x{3242}",
+	'ideographicsocietyparen' => "\x{3233}",
+	'ideographicspace' => "\x{3000}",
+	'ideographicspecialparen' => "\x{3235}",
+	'ideographicstockparen' => "\x{3231}",
+	'ideographicstudyparen' => "\x{323B}",
+	'ideographicsunparen' => "\x{3230}",
+	'ideographicsuperviseparen' => "\x{323C}",
+	'ideographicwaterparen' => "\x{322C}",
+	'ideographicwoodparen' => "\x{322D}",
+	'ideographiczero' => "\x{3007}",
+	'ideographmetalcircle' => "\x{328E}",
+	'ideographmooncircle' => "\x{328A}",
+	'ideographnamecircle' => "\x{3294}",
+	'ideographsuncircle' => "\x{3290}",
+	'ideographwatercircle' => "\x{328C}",
+	'ideographwoodcircle' => "\x{328D}",
+	'ideva' => "\x{0907}",
+	'idieresisacute' => "\x{1E2F}",
+	'idieresiscyrillic' => "\x{04E5}",
+	'idotbelow' => "\x{1ECB}",
+	'iebrevecyrillic' => "\x{04D7}",
+	'iecyrillic' => "\x{0435}",
+	'ieungacirclekorean' => "\x{3275}",
+	'ieungaparenkorean' => "\x{3215}",
+	'ieungcirclekorean' => "\x{3267}",
+	'ieungkorean' => "\x{3147}",
+	'ieungparenkorean' => "\x{3207}",
+	'igujarati' => "\x{0A87}",
+	'igurmukhi' => "\x{0A07}",
+	'ihiragana' => "\x{3044}",
+	'ihookabove' => "\x{1EC9}",
+	'iibengali' => "\x{0988}",
+	'iicyrillic' => "\x{0438}",
+	'iideva' => "\x{0908}",
+	'iigujarati' => "\x{0A88}",
+	'iigurmukhi' => "\x{0A08}",
+	'iimatragurmukhi' => "\x{0A40}",
+	'iinvertedbreve' => "\x{020B}",
+	'iishortcyrillic' => "\x{0439}",
+	'iivowelsignbengali' => "\x{09C0}",
+	'iivowelsigndeva' => "\x{0940}",
+	'iivowelsigngujarati' => "\x{0AC0}",
+	'ikatakana' => "\x{30A4}",
+	'ikatakanahalfwidth' => "\x{FF72}",
+	'ikorean' => "\x{3163}",
+	'ilde' => "\x{02DC}",
+	'iluyhebrew' => "\x{05AC}",
+	'imacroncyrillic' => "\x{04E3}",
+	'imageorapproximatelyequal' => "\x{2253}",
+	'imatragurmukhi' => "\x{0A3F}",
+	'imonospace' => "\x{FF49}",
+	'increment' => "\x{2206}",
+	'iniarmenian' => "\x{056B}",
+	'integralbottom' => "\x{2321}",
+	'integralex' => "\x{F8F5}",
+	'integraltop' => "\x{2320}",
+	'intisquare' => "\x{3305}",
+	'iocyrillic' => "\x{0451}",
+	'iotalatin' => "\x{0269}",
+	'iparen' => "\x{24A4}",
+	'irigurmukhi' => "\x{0A72}",
+	'ismallhiragana' => "\x{3043}",
+	'ismallkatakana' => "\x{30A3}",
+	'ismallkatakanahalfwidth' => "\x{FF68}",
+	'issharbengali' => "\x{09FA}",
+	'istroke' => "\x{0268}",
+	'isuperior' => "\x{F6ED}",
+	'iterationhiragana' => "\x{309D}",
+	'iterationkatakana' => "\x{30FD}",
+	'itildebelow' => "\x{1E2D}",
+	'iubopomofo' => "\x{3129}",
+	'iucyrillic' => "\x{044E}",
+	'ivowelsignbengali' => "\x{09BF}",
+	'ivowelsigndeva' => "\x{093F}",
+	'ivowelsigngujarati' => "\x{0ABF}",
+	'izhitsacyrillic' => "\x{0475}",
+	'izhitsadblgravecyrillic' => "\x{0477}",
+	'jaarmenian' => "\x{0571}",
+	'jabengali' => "\x{099C}",
+	'jadeva' => "\x{091C}",
+	'jagujarati' => "\x{0A9C}",
+	'jagurmukhi' => "\x{0A1C}",
+	'jbopomofo' => "\x{3110}",
+	'jcaron' => "\x{01F0}",
+	'jcircle' => "\x{24D9}",
+	'jcrossedtail' => "\x{029D}",
+	'jdotlessstroke' => "\x{025F}",
+	'jecyrillic' => "\x{0458}",
+	'jeemarabic' => "\x{062C}",
+	'jeemfinalarabic' => "\x{FE9E}",
+	'jeeminitialarabic' => "\x{FE9F}",
+	'jeemmedialarabic' => "\x{FEA0}",
+	'jeharabic' => "\x{0698}",
+	'jehfinalarabic' => "\x{FB8B}",
+	'jhabengali' => "\x{099D}",
+	'jhadeva' => "\x{091D}",
+	'jhagujarati' => "\x{0A9D}",
+	'jhagurmukhi' => "\x{0A1D}",
+	'jheharmenian' => "\x{057B}",
+	'jis' => "\x{3004}",
+	'jmonospace' => "\x{FF4A}",
+	'jparen' => "\x{24A5}",
+	'jsuperior' => "\x{02B2}",
+	'kabashkircyrillic' => "\x{04A1}",
+	'kabengali' => "\x{0995}",
+	'kacute' => "\x{1E31}",
+	'kacyrillic' => "\x{043A}",
+	'kadescendercyrillic' => "\x{049B}",
+	'kadeva' => "\x{0915}",
+	'kaf' => "\x{05DB}",
+	'kafarabic' => "\x{0643}",
+	'kafdagesh' => "\x{FB3B}",
+	'kafdageshhebrew' => "\x{FB3B}",
+	'kaffinalarabic' => "\x{FEDA}",
+	'kafhebrew' => "\x{05DB}",
+	'kafinitialarabic' => "\x{FEDB}",
+	'kafmedialarabic' => "\x{FEDC}",
+	'kafrafehebrew' => "\x{FB4D}",
+	'kagujarati' => "\x{0A95}",
+	'kagurmukhi' => "\x{0A15}",
+	'kahiragana' => "\x{304B}",
+	'kahookcyrillic' => "\x{04C4}",
+	'kakatakana' => "\x{30AB}",
+	'kakatakanahalfwidth' => "\x{FF76}",
+	'kappasymbolgreek' => "\x{03F0}",
+	'kapyeounmieumkorean' => "\x{3171}",
+	'kapyeounphieuphkorean' => "\x{3184}",
+	'kapyeounpieupkorean' => "\x{3178}",
+	'kapyeounssangpieupkorean' => "\x{3179}",
+	'karoriisquare' => "\x{330D}",
+	'kashidaautoarabic' => "\x{0640}",
+	'kashidaautonosidebearingarabic' => "\x{0640}",
+	'kasmallkatakana' => "\x{30F5}",
+	'kasquare' => "\x{3384}",
+	'kasraarabic' => "\x{0650}",
+	'kasratanarabic' => "\x{064D}",
+	'kastrokecyrillic' => "\x{049F}",
+	'katahiraprolongmarkhalfwidth' => "\x{FF70}",
+	'kaverticalstrokecyrillic' => "\x{049D}",
+	'kbopomofo' => "\x{310E}",
+	'kcalsquare' => "\x{3389}",
+	'kcaron' => "\x{01E9}",
+	'kcedilla' => "\x{0137}",
+	'kcircle' => "\x{24DA}",
+	'kdotbelow' => "\x{1E33}",
+	'keharmenian' => "\x{0584}",
+	'kehiragana' => "\x{3051}",
+	'kekatakana' => "\x{30B1}",
+	'kekatakanahalfwidth' => "\x{FF79}",
+	'kenarmenian' => "\x{056F}",
+	'kesmallkatakana' => "\x{30F6}",
+	'khabengali' => "\x{0996}",
+	'khacyrillic' => "\x{0445}",
+	'khadeva' => "\x{0916}",
+	'khagujarati' => "\x{0A96}",
+	'khagurmukhi' => "\x{0A16}",
+	'khaharabic' => "\x{062E}",
+	'khahfinalarabic' => "\x{FEA6}",
+	'khahinitialarabic' => "\x{FEA7}",
+	'khahmedialarabic' => "\x{FEA8}",
+	'kheicoptic' => "\x{03E7}",
+	'khhadeva' => "\x{0959}",
+	'khhagurmukhi' => "\x{0A59}",
+	'khieukhacirclekorean' => "\x{3278}",
+	'khieukhaparenkorean' => "\x{3218}",
+	'khieukhcirclekorean' => "\x{326A}",
+	'khieukhkorean' => "\x{314B}",
+	'khieukhparenkorean' => "\x{320A}",
+	'khokhaithai' => "\x{0E02}",
+	'khokhonthai' => "\x{0E05}",
+	'khokhuatthai' => "\x{0E03}",
+	'khokhwaithai' => "\x{0E04}",
+	'khomutthai' => "\x{0E5B}",
+	'khook' => "\x{0199}",
+	'khorakhangthai' => "\x{0E06}",
+	'khzsquare' => "\x{3391}",
+	'kihiragana' => "\x{304D}",
+	'kikatakana' => "\x{30AD}",
+	'kikatakanahalfwidth' => "\x{FF77}",
+	'kiroguramusquare' => "\x{3315}",
+	'kiromeetorusquare' => "\x{3316}",
+	'kirosquare' => "\x{3314}",
+	'kiyeokacirclekorean' => "\x{326E}",
+	'kiyeokaparenkorean' => "\x{320E}",
+	'kiyeokcirclekorean' => "\x{3260}",
+	'kiyeokkorean' => "\x{3131}",
+	'kiyeokparenkorean' => "\x{3200}",
+	'kiyeoksioskorean' => "\x{3133}",
+	'kjecyrillic' => "\x{045C}",
+	'klinebelow' => "\x{1E35}",
+	'klsquare' => "\x{3398}",
+	'kmcubedsquare' => "\x{33A6}",
+	'kmonospace' => "\x{FF4B}",
+	'kmsquaredsquare' => "\x{33A2}",
+	'kohiragana' => "\x{3053}",
+	'kohmsquare' => "\x{33C0}",
+	'kokaithai' => "\x{0E01}",
+	'kokatakana' => "\x{30B3}",
+	'kokatakanahalfwidth' => "\x{FF7A}",
+	'kooposquare' => "\x{331E}",
+	'koppacyrillic' => "\x{0481}",
+	'koreanstandardsymbol' => "\x{327F}",
+	'koroniscmb' => "\x{0343}",
+	'kparen' => "\x{24A6}",
+	'kpasquare' => "\x{33AA}",
+	'ksicyrillic' => "\x{046F}",
+	'ktsquare' => "\x{33CF}",
+	'kturned' => "\x{029E}",
+	'kuhiragana' => "\x{304F}",
+	'kukatakana' => "\x{30AF}",
+	'kukatakanahalfwidth' => "\x{FF78}",
+	'kvsquare' => "\x{33B8}",
+	'kwsquare' => "\x{33BE}",
+	'labengali' => "\x{09B2}",
+	'ladeva' => "\x{0932}",
+	'lagujarati' => "\x{0AB2}",
+	'lagurmukhi' => "\x{0A32}",
+	'lakkhangyaothai' => "\x{0E45}",
+	'lamaleffinalarabic' => "\x{FEFC}",
+	'lamalefhamzaabovefinalarabic' => "\x{FEF8}",
+	'lamalefhamzaaboveisolatedarabic' => "\x{FEF7}",
+	'lamalefhamzabelowfinalarabic' => "\x{FEFA}",
+	'lamalefhamzabelowisolatedarabic' => "\x{FEF9}",
+	'lamalefisolatedarabic' => "\x{FEFB}",
+	'lamalefmaddaabovefinalarabic' => "\x{FEF6}",
+	'lamalefmaddaaboveisolatedarabic' => "\x{FEF5}",
+	'lamarabic' => "\x{0644}",
+	'lambdastroke' => "\x{019B}",
+	'lamed' => "\x{05DC}",
+	'lameddagesh' => "\x{FB3C}",
+	'lameddageshhebrew' => "\x{FB3C}",
+	'lamedhebrew' => "\x{05DC}",
+	'lamedholam' => "\x{05DC}\x{05B9}",
+	'lamedholamdagesh' => "\x{05DC}\x{05B9}\x{05BC}",
+	'lamedholamdageshhebrew' => "\x{05DC}\x{05B9}\x{05BC}",
+	'lamedholamhebrew' => "\x{05DC}\x{05B9}",
+	'lamfinalarabic' => "\x{FEDE}",
+	'lamhahinitialarabic' => "\x{FCCA}",
+	'laminitialarabic' => "\x{FEDF}",
+	'lamjeeminitialarabic' => "\x{FCC9}",
+	'lamkhahinitialarabic' => "\x{FCCB}",
+	'lamlamhehisolatedarabic' => "\x{FDF2}",
+	'lammedialarabic' => "\x{FEE0}",
+	'lammeemhahinitialarabic' => "\x{FD88}",
+	'lammeeminitialarabic' => "\x{FCCC}",
+	'lammeemjeeminitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA0}",
+	'lammeemkhahinitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA8}",
+	'largecircle' => "\x{25EF}",
+	'lbar' => "\x{019A}",
+	'lbelt' => "\x{026C}",
+	'lbopomofo' => "\x{310C}",
+	'lcedilla' => "\x{013C}",
+	'lcircle' => "\x{24DB}",
+	'lcircumflexbelow' => "\x{1E3D}",
+	'ldotaccent' => "\x{0140}",
+	'ldotbelow' => "\x{1E37}",
+	'ldotbelowmacron' => "\x{1E39}",
+	'leftangleabovecmb' => "\x{031A}",
+	'lefttackbelowcmb' => "\x{0318}",
+	'lessequalorgreater' => "\x{22DA}",
+	'lessmonospace' => "\x{FF1C}",
+	'lessorequivalent' => "\x{2272}",
+	'lessorgreater' => "\x{2276}",
+	'lessoverequal' => "\x{2266}",
+	'lesssmall' => "\x{FE64}",
+	'lezh' => "\x{026E}",
+	'lhookretroflex' => "\x{026D}",
+	'liwnarmenian' => "\x{056C}",
+	'lj' => "\x{01C9}",
+	'ljecyrillic' => "\x{0459}",
+	'll' => "\x{F6C0}",
+	'lladeva' => "\x{0933}",
+	'llagujarati' => "\x{0AB3}",
+	'llinebelow' => "\x{1E3B}",
+	'llladeva' => "\x{0934}",
+	'llvocalicbengali' => "\x{09E1}",
+	'llvocalicdeva' => "\x{0961}",
+	'llvocalicvowelsignbengali' => "\x{09E3}",
+	'llvocalicvowelsigndeva' => "\x{0963}",
+	'lmiddletilde' => "\x{026B}",
+	'lmonospace' => "\x{FF4C}",
+	'lmsquare' => "\x{33D0}",
+	'lochulathai' => "\x{0E2C}",
+	'logicalnotreversed' => "\x{2310}",
+	'lolingthai' => "\x{0E25}",
+	'lowlinecenterline' => "\x{FE4E}",
+	'lowlinecmb' => "\x{0332}",
+	'lowlinedashed' => "\x{FE4D}",
+	'lparen' => "\x{24A7}",
+	'lsquare' => "\x{2113}",
+	'lsuperior' => "\x{F6EE}",
+	'luthai' => "\x{0E26}",
+	'lvocalicbengali' => "\x{098C}",
+	'lvocalicdeva' => "\x{090C}",
+	'lvocalicvowelsignbengali' => "\x{09E2}",
+	'lvocalicvowelsigndeva' => "\x{0962}",
+	'lxsquare' => "\x{33D3}",
+	'mabengali' => "\x{09AE}",
+	'macronbelowcmb' => "\x{0331}",
+	'macroncmb' => "\x{0304}",
+	'macronlowmod' => "\x{02CD}",
+	'macronmonospace' => "\x{FFE3}",
+	'macute' => "\x{1E3F}",
+	'madeva' => "\x{092E}",
+	'magujarati' => "\x{0AAE}",
+	'magurmukhi' => "\x{0A2E}",
+	'mahapakhhebrew' => "\x{05A4}",
+	'mahapakhlefthebrew' => "\x{05A4}",
+	'mahiragana' => "\x{307E}",
+	'maichattawalowleftthai' => "\x{F895}",
+	'maichattawalowrightthai' => "\x{F894}",
+	'maichattawathai' => "\x{0E4B}",
+	'maichattawaupperleftthai' => "\x{F893}",
+	'maieklowleftthai' => "\x{F88C}",
+	'maieklowrightthai' => "\x{F88B}",
+	'maiekthai' => "\x{0E48}",
+	'maiekupperleftthai' => "\x{F88A}",
+	'maihanakatleftthai' => "\x{F884}",
+	'maihanakatthai' => "\x{0E31}",
+	'maitaikhuleftthai' => "\x{F889}",
+	'maitaikhuthai' => "\x{0E47}",
+	'maitholowleftthai' => "\x{F88F}",
+	'maitholowrightthai' => "\x{F88E}",
+	'maithothai' => "\x{0E49}",
+	'maithoupperleftthai' => "\x{F88D}",
+	'maitrilowleftthai' => "\x{F892}",
+	'maitrilowrightthai' => "\x{F891}",
+	'maitrithai' => "\x{0E4A}",
+	'maitriupperleftthai' => "\x{F890}",
+	'maiyamokthai' => "\x{0E46}",
+	'makatakana' => "\x{30DE}",
+	'makatakanahalfwidth' => "\x{FF8F}",
+	'mansyonsquare' => "\x{3347}",
+	'maqafhebrew' => "\x{05BE}",
+	'mars' => "\x{2642}",
+	'masoracirclehebrew' => "\x{05AF}",
+	'masquare' => "\x{3383}",
+	'mbopomofo' => "\x{3107}",
+	'mbsquare' => "\x{33D4}",
+	'mcircle' => "\x{24DC}",
+	'mcubedsquare' => "\x{33A5}",
+	'mdotaccent' => "\x{1E41}",
+	'mdotbelow' => "\x{1E43}",
+	'meemarabic' => "\x{0645}",
+	'meemfinalarabic' => "\x{FEE2}",
+	'meeminitialarabic' => "\x{FEE3}",
+	'meemmedialarabic' => "\x{FEE4}",
+	'meemmeeminitialarabic' => "\x{FCD1}",
+	'meemmeemisolatedarabic' => "\x{FC48}",
+	'meetorusquare' => "\x{334D}",
+	'mehiragana' => "\x{3081}",
+	'meizierasquare' => "\x{337E}",
+	'mekatakana' => "\x{30E1}",
+	'mekatakanahalfwidth' => "\x{FF92}",
+	'mem' => "\x{05DE}",
+	'memdagesh' => "\x{FB3E}",
+	'memdageshhebrew' => "\x{FB3E}",
+	'memhebrew' => "\x{05DE}",
+	'menarmenian' => "\x{0574}",
+	'merkhahebrew' => "\x{05A5}",
+	'merkhakefulahebrew' => "\x{05A6}",
+	'merkhakefulalefthebrew' => "\x{05A6}",
+	'merkhalefthebrew' => "\x{05A5}",
+	'mhook' => "\x{0271}",
+	'mhzsquare' => "\x{3392}",
+	'middledotkatakanahalfwidth' => "\x{FF65}",
+	'middot' => "\x{00B7}",
+	'mieumacirclekorean' => "\x{3272}",
+	'mieumaparenkorean' => "\x{3212}",
+	'mieumcirclekorean' => "\x{3264}",
+	'mieumkorean' => "\x{3141}",
+	'mieumpansioskorean' => "\x{3170}",
+	'mieumparenkorean' => "\x{3204}",
+	'mieumpieupkorean' => "\x{316E}",
+	'mieumsioskorean' => "\x{316F}",
+	'mihiragana' => "\x{307F}",
+	'mikatakana' => "\x{30DF}",
+	'mikatakanahalfwidth' => "\x{FF90}",
+	'minusbelowcmb' => "\x{0320}",
+	'minuscircle' => "\x{2296}",
+	'minusmod' => "\x{02D7}",
+	'minusplus' => "\x{2213}",
+	'miribaarusquare' => "\x{334A}",
+	'mirisquare' => "\x{3349}",
+	'mlonglegturned' => "\x{0270}",
+	'mlsquare' => "\x{3396}",
+	'mmcubedsquare' => "\x{33A3}",
+	'mmonospace' => "\x{FF4D}",
+	'mmsquaredsquare' => "\x{339F}",
+	'mohiragana' => "\x{3082}",
+	'mohmsquare' => "\x{33C1}",
+	'mokatakana' => "\x{30E2}",
+	'mokatakanahalfwidth' => "\x{FF93}",
+	'molsquare' => "\x{33D6}",
+	'momathai' => "\x{0E21}",
+	'moverssquare' => "\x{33A7}",
+	'moverssquaredsquare' => "\x{33A8}",
+	'mparen' => "\x{24A8}",
+	'mpasquare' => "\x{33AB}",
+	'mssquare' => "\x{33B3}",
+	'msuperior' => "\x{F6EF}",
+	'mturned' => "\x{026F}",
+	'mu1' => "\x{00B5}",
+	'muasquare' => "\x{3382}",
+	'muchgreater' => "\x{226B}",
+	'muchless' => "\x{226A}",
+	'mufsquare' => "\x{338C}",
+	'mugreek' => "\x{03BC}",
+	'mugsquare' => "\x{338D}",
+	'muhiragana' => "\x{3080}",
+	'mukatakana' => "\x{30E0}",
+	'mukatakanahalfwidth' => "\x{FF91}",
+	'mulsquare' => "\x{3395}",
+	'mumsquare' => "\x{339B}",
+	'munahhebrew' => "\x{05A3}",
+	'munahlefthebrew' => "\x{05A3}",
+	'musicflatsign' => "\x{266D}",
+	'musicsharpsign' => "\x{266F}",
+	'mussquare' => "\x{33B2}",
+	'muvsquare' => "\x{33B6}",
+	'muwsquare' => "\x{33BC}",
+	'mvmegasquare' => "\x{33B9}",
+	'mvsquare' => "\x{33B7}",
+	'mwmegasquare' => "\x{33BF}",
+	'mwsquare' => "\x{33BD}",
+	'nabengali' => "\x{09A8}",
+	'nabla' => "\x{2207}",
+	'nadeva' => "\x{0928}",
+	'nagujarati' => "\x{0AA8}",
+	'nagurmukhi' => "\x{0A28}",
+	'nahiragana' => "\x{306A}",
+	'nakatakana' => "\x{30CA}",
+	'nakatakanahalfwidth' => "\x{FF85}",
+	'nasquare' => "\x{3381}",
+	'nbopomofo' => "\x{310B}",
+	'nbspace' => "\x{00A0}",
+	'ncedilla' => "\x{0146}",
+	'ncircle' => "\x{24DD}",
+	'ncircumflexbelow' => "\x{1E4B}",
+	'ndotaccent' => "\x{1E45}",
+	'ndotbelow' => "\x{1E47}",
+	'nehiragana' => "\x{306D}",
+	'nekatakana' => "\x{30CD}",
+	'nekatakanahalfwidth' => "\x{FF88}",
+	'newsheqelsign' => "\x{20AA}",
+	'nfsquare' => "\x{338B}",
+	'ngabengali' => "\x{0999}",
+	'ngadeva' => "\x{0919}",
+	'ngagujarati' => "\x{0A99}",
+	'ngagurmukhi' => "\x{0A19}",
+	'ngonguthai' => "\x{0E07}",
+	'nhiragana' => "\x{3093}",
+	'nhookleft' => "\x{0272}",
+	'nhookretroflex' => "\x{0273}",
+	'nieunacirclekorean' => "\x{326F}",
+	'nieunaparenkorean' => "\x{320F}",
+	'nieuncieuckorean' => "\x{3135}",
+	'nieuncirclekorean' => "\x{3261}",
+	'nieunhieuhkorean' => "\x{3136}",
+	'nieunkorean' => "\x{3134}",
+	'nieunpansioskorean' => "\x{3168}",
+	'nieunparenkorean' => "\x{3201}",
+	'nieunsioskorean' => "\x{3167}",
+	'nieuntikeutkorean' => "\x{3166}",
+	'nihiragana' => "\x{306B}",
+	'nikatakana' => "\x{30CB}",
+	'nikatakanahalfwidth' => "\x{FF86}",
+	'nikhahitleftthai' => "\x{F899}",
+	'nikhahitthai' => "\x{0E4D}",
+	'ninearabic' => "\x{0669}",
+	'ninebengali' => "\x{09EF}",
+	'ninecircle' => "\x{2468}",
+	'ninecircleinversesansserif' => "\x{2792}",
+	'ninedeva' => "\x{096F}",
+	'ninegujarati' => "\x{0AEF}",
+	'ninegurmukhi' => "\x{0A6F}",
+	'ninehackarabic' => "\x{0669}",
+	'ninehangzhou' => "\x{3029}",
+	'nineideographicparen' => "\x{3228}",
+	'nineinferior' => "\x{2089}",
+	'ninemonospace' => "\x{FF19}",
+	'nineoldstyle' => "\x{F739}",
+	'nineparen' => "\x{247C}",
+	'nineperiod' => "\x{2490}",
+	'ninepersian' => "\x{06F9}",
+	'nineroman' => "\x{2178}",
+	'ninesuperior' => "\x{2079}",
+	'nineteencircle' => "\x{2472}",
+	'nineteenparen' => "\x{2486}",
+	'nineteenperiod' => "\x{249A}",
+	'ninethai' => "\x{0E59}",
+	'nj' => "\x{01CC}",
+	'njecyrillic' => "\x{045A}",
+	'nkatakana' => "\x{30F3}",
+	'nkatakanahalfwidth' => "\x{FF9D}",
+	'nlegrightlong' => "\x{019E}",
+	'nlinebelow' => "\x{1E49}",
+	'nmonospace' => "\x{FF4E}",
+	'nmsquare' => "\x{339A}",
+	'nnabengali' => "\x{09A3}",
+	'nnadeva' => "\x{0923}",
+	'nnagujarati' => "\x{0AA3}",
+	'nnagurmukhi' => "\x{0A23}",
+	'nnnadeva' => "\x{0929}",
+	'nohiragana' => "\x{306E}",
+	'nokatakana' => "\x{30CE}",
+	'nokatakanahalfwidth' => "\x{FF89}",
+	'nonbreakingspace' => "\x{00A0}",
+	'nonenthai' => "\x{0E13}",
+	'nonuthai' => "\x{0E19}",
+	'noonarabic' => "\x{0646}",
+	'noonfinalarabic' => "\x{FEE6}",
+	'noonghunnaarabic' => "\x{06BA}",
+	'noonghunnafinalarabic' => "\x{FB9F}",
+	'noonhehinitialarabic' => "\x{FEE7}\x{FEEC}",
+	'nooninitialarabic' => "\x{FEE7}",
+	'noonjeeminitialarabic' => "\x{FCD2}",
+	'noonjeemisolatedarabic' => "\x{FC4B}",
+	'noonmedialarabic' => "\x{FEE8}",
+	'noonmeeminitialarabic' => "\x{FCD5}",
+	'noonmeemisolatedarabic' => "\x{FC4E}",
+	'noonnoonfinalarabic' => "\x{FC8D}",
+	'notcontains' => "\x{220C}",
+	'notelementof' => "\x{2209}",
+	'notgreater' => "\x{226F}",
+	'notgreaternorequal' => "\x{2271}",
+	'notgreaternorless' => "\x{2279}",
+	'notidentical' => "\x{2262}",
+	'notless' => "\x{226E}",
+	'notlessnorequal' => "\x{2270}",
+	'notparallel' => "\x{2226}",
+	'notprecedes' => "\x{2280}",
+	'notsucceeds' => "\x{2281}",
+	'notsuperset' => "\x{2285}",
+	'nowarmenian' => "\x{0576}",
+	'nparen' => "\x{24A9}",
+	'nssquare' => "\x{33B1}",
+	'nsuperior' => "\x{207F}",
+	'nuhiragana' => "\x{306C}",
+	'nukatakana' => "\x{30CC}",
+	'nukatakanahalfwidth' => "\x{FF87}",
+	'nuktabengali' => "\x{09BC}",
+	'nuktadeva' => "\x{093C}",
+	'nuktagujarati' => "\x{0ABC}",
+	'nuktagurmukhi' => "\x{0A3C}",
+	'numbersignmonospace' => "\x{FF03}",
+	'numbersignsmall' => "\x{FE5F}",
+	'numeralsigngreek' => "\x{0374}",
+	'numeralsignlowergreek' => "\x{0375}",
+	'numero' => "\x{2116}",
+	'nun' => "\x{05E0}",
+	'nundagesh' => "\x{FB40}",
+	'nundageshhebrew' => "\x{FB40}",
+	'nunhebrew' => "\x{05E0}",
+	'nvsquare' => "\x{33B5}",
+	'nwsquare' => "\x{33BB}",
+	'nyabengali' => "\x{099E}",
+	'nyadeva' => "\x{091E}",
+	'nyagujarati' => "\x{0A9E}",
+	'nyagurmukhi' => "\x{0A1E}",
+	'oangthai' => "\x{0E2D}",
+	'obarred' => "\x{0275}",
+	'obarredcyrillic' => "\x{04E9}",
+	'obarreddieresiscyrillic' => "\x{04EB}",
+	'obengali' => "\x{0993}",
+	'obopomofo' => "\x{311B}",
+	'ocandradeva' => "\x{0911}",
+	'ocandragujarati' => "\x{0A91}",
+	'ocandravowelsigndeva' => "\x{0949}",
+	'ocandravowelsigngujarati' => "\x{0AC9}",
+	'ocaron' => "\x{01D2}",
+	'ocircle' => "\x{24DE}",
+	'ocircumflexacute' => "\x{1ED1}",
+	'ocircumflexdotbelow' => "\x{1ED9}",
+	'ocircumflexgrave' => "\x{1ED3}",
+	'ocircumflexhookabove' => "\x{1ED5}",
+	'ocircumflextilde' => "\x{1ED7}",
+	'ocyrillic' => "\x{043E}",
+	'odblacute' => "\x{0151}",
+	'odblgrave' => "\x{020D}",
+	'odeva' => "\x{0913}",
+	'odieresiscyrillic' => "\x{04E7}",
+	'odotbelow' => "\x{1ECD}",
+	'oekorean' => "\x{315A}",
+	'ogonekcmb' => "\x{0328}",
+	'ogujarati' => "\x{0A93}",
+	'oharmenian' => "\x{0585}",
+	'ohiragana' => "\x{304A}",
+	'ohookabove' => "\x{1ECF}",
+	'ohornacute' => "\x{1EDB}",
+	'ohorndotbelow' => "\x{1EE3}",
+	'ohorngrave' => "\x{1EDD}",
+	'ohornhookabove' => "\x{1EDF}",
+	'ohorntilde' => "\x{1EE1}",
+	'oi' => "\x{01A3}",
+	'oinvertedbreve' => "\x{020F}",
+	'okatakana' => "\x{30AA}",
+	'okatakanahalfwidth' => "\x{FF75}",
+	'okorean' => "\x{3157}",
+	'olehebrew' => "\x{05AB}",
+	'omacronacute' => "\x{1E53}",
+	'omacrongrave' => "\x{1E51}",
+	'omdeva' => "\x{0950}",
+	'omegacyrillic' => "\x{0461}",
+	'omegalatinclosed' => "\x{0277}",
+	'omegaroundcyrillic' => "\x{047B}",
+	'omegatitlocyrillic' => "\x{047D}",
+	'omgujarati' => "\x{0AD0}",
+	'omonospace' => "\x{FF4F}",
+	'onearabic' => "\x{0661}",
+	'onebengali' => "\x{09E7}",
+	'onecircle' => "\x{2460}",
+	'onecircleinversesansserif' => "\x{278A}",
+	'onedeva' => "\x{0967}",
+	'onefitted' => "\x{F6DC}",
+	'onegujarati' => "\x{0AE7}",
+	'onegurmukhi' => "\x{0A67}",
+	'onehackarabic' => "\x{0661}",
+	'onehangzhou' => "\x{3021}",
+	'oneideographicparen' => "\x{3220}",
+	'oneinferior' => "\x{2081}",
+	'onemonospace' => "\x{FF11}",
+	'onenumeratorbengali' => "\x{09F4}",
+	'oneoldstyle' => "\x{F731}",
+	'oneparen' => "\x{2474}",
+	'oneperiod' => "\x{2488}",
+	'onepersian' => "\x{06F1}",
+	'oneroman' => "\x{2170}",
+	'onethai' => "\x{0E51}",
+	'oogonek' => "\x{01EB}",
+	'oogonekmacron' => "\x{01ED}",
+	'oogurmukhi' => "\x{0A13}",
+	'oomatragurmukhi' => "\x{0A4B}",
+	'oopen' => "\x{0254}",
+	'oparen' => "\x{24AA}",
+	'option' => "\x{2325}",
+	'oshortdeva' => "\x{0912}",
+	'oshortvowelsigndeva' => "\x{094A}",
+	'osmallhiragana' => "\x{3049}",
+	'osmallkatakana' => "\x{30A9}",
+	'osmallkatakanahalfwidth' => "\x{FF6B}",
+	'ostrokeacute' => "\x{01FF}",
+	'osuperior' => "\x{F6F0}",
+	'otcyrillic' => "\x{047F}",
+	'otildeacute' => "\x{1E4D}",
+	'otildedieresis' => "\x{1E4F}",
+	'oubopomofo' => "\x{3121}",
+	'overline' => "\x{203E}",
+	'overlinecenterline' => "\x{FE4A}",
+	'overlinecmb' => "\x{0305}",
+	'overlinedashed' => "\x{FE49}",
+	'overlinedblwavy' => "\x{FE4C}",
+	'overlinewavy' => "\x{FE4B}",
+	'overscore' => "\x{00AF}",
+	'ovowelsignbengali' => "\x{09CB}",
+	'ovowelsigndeva' => "\x{094B}",
+	'ovowelsigngujarati' => "\x{0ACB}",
+	'paampssquare' => "\x{3380}",
+	'paasentosquare' => "\x{332B}",
+	'pabengali' => "\x{09AA}",
+	'pacute' => "\x{1E55}",
+	'padeva' => "\x{092A}",
+	'pagedown' => "\x{21DF}",
+	'pageup' => "\x{21DE}",
+	'pagujarati' => "\x{0AAA}",
+	'pagurmukhi' => "\x{0A2A}",
+	'pahiragana' => "\x{3071}",
+	'paiyannoithai' => "\x{0E2F}",
+	'pakatakana' => "\x{30D1}",
+	'palatalizationcyrilliccmb' => "\x{0484}",
+	'palochkacyrillic' => "\x{04C0}",
+	'pansioskorean' => "\x{317F}",
+	'parallel' => "\x{2225}",
+	'parenleftaltonearabic' => "\x{FD3E}",
+	'parenleftbt' => "\x{F8ED}",
+	'parenleftex' => "\x{F8EC}",
+	'parenleftinferior' => "\x{208D}",
+	'parenleftmonospace' => "\x{FF08}",
+	'parenleftsmall' => "\x{FE59}",
+	'parenleftsuperior' => "\x{207D}",
+	'parenlefttp' => "\x{F8EB}",
+	'parenleftvertical' => "\x{FE35}",
+	'parenrightaltonearabic' => "\x{FD3F}",
+	'parenrightbt' => "\x{F8F8}",
+	'parenrightex' => "\x{F8F7}",
+	'parenrightinferior' => "\x{208E}",
+	'parenrightmonospace' => "\x{FF09}",
+	'parenrightsmall' => "\x{FE5A}",
+	'parenrightsuperior' => "\x{207E}",
+	'parenrighttp' => "\x{F8F6}",
+	'parenrightvertical' => "\x{FE36}",
+	'paseqhebrew' => "\x{05C0}",
+	'pashtahebrew' => "\x{0599}",
+	'pasquare' => "\x{33A9}",
+	'patah' => "\x{05B7}",
+	'patah11' => "\x{05B7}",
+	'patah1d' => "\x{05B7}",
+	'patah2a' => "\x{05B7}",
+	'patahhebrew' => "\x{05B7}",
+	'patahnarrowhebrew' => "\x{05B7}",
+	'patahquarterhebrew' => "\x{05B7}",
+	'patahwidehebrew' => "\x{05B7}",
+	'pazerhebrew' => "\x{05A1}",
+	'pbopomofo' => "\x{3106}",
+	'pcircle' => "\x{24DF}",
+	'pdotaccent' => "\x{1E57}",
+	'pe' => "\x{05E4}",
+	'pecyrillic' => "\x{043F}",
+	'pedagesh' => "\x{FB44}",
+	'pedageshhebrew' => "\x{FB44}",
+	'peezisquare' => "\x{333B}",
+	'pefinaldageshhebrew' => "\x{FB43}",
+	'peharabic' => "\x{067E}",
+	'peharmenian' => "\x{057A}",
+	'pehebrew' => "\x{05E4}",
+	'pehfinalarabic' => "\x{FB57}",
+	'pehinitialarabic' => "\x{FB58}",
+	'pehiragana' => "\x{307A}",
+	'pehmedialarabic' => "\x{FB59}",
+	'pekatakana' => "\x{30DA}",
+	'pemiddlehookcyrillic' => "\x{04A7}",
+	'perafehebrew' => "\x{FB4E}",
+	'percentarabic' => "\x{066A}",
+	'percentmonospace' => "\x{FF05}",
+	'percentsmall' => "\x{FE6A}",
+	'periodarmenian' => "\x{0589}",
+	'periodhalfwidth' => "\x{FF61}",
+	'periodinferior' => "\x{F6E7}",
+	'periodmonospace' => "\x{FF0E}",
+	'periodsmall' => "\x{FE52}",
+	'periodsuperior' => "\x{F6E8}",
+	'perispomenigreekcmb' => "\x{0342}",
+	'pfsquare' => "\x{338A}",
+	'phabengali' => "\x{09AB}",
+	'phadeva' => "\x{092B}",
+	'phagujarati' => "\x{0AAB}",
+	'phagurmukhi' => "\x{0A2B}",
+	'phieuphacirclekorean' => "\x{327A}",
+	'phieuphaparenkorean' => "\x{321A}",
+	'phieuphcirclekorean' => "\x{326C}",
+	'phieuphkorean' => "\x{314D}",
+	'phieuphparenkorean' => "\x{320C}",
+	'philatin' => "\x{0278}",
+	'phinthuthai' => "\x{0E3A}",
+	'phisymbolgreek' => "\x{03D5}",
+	'phook' => "\x{01A5}",
+	'phophanthai' => "\x{0E1E}",
+	'phophungthai' => "\x{0E1C}",
+	'phosamphaothai' => "\x{0E20}",
+	'pieupacirclekorean' => "\x{3273}",
+	'pieupaparenkorean' => "\x{3213}",
+	'pieupcieuckorean' => "\x{3176}",
+	'pieupcirclekorean' => "\x{3265}",
+	'pieupkiyeokkorean' => "\x{3172}",
+	'pieupkorean' => "\x{3142}",
+	'pieupparenkorean' => "\x{3205}",
+	'pieupsioskiyeokkorean' => "\x{3174}",
+	'pieupsioskorean' => "\x{3144}",
+	'pieupsiostikeutkorean' => "\x{3175}",
+	'pieupthieuthkorean' => "\x{3177}",
+	'pieuptikeutkorean' => "\x{3173}",
+	'pihiragana' => "\x{3074}",
+	'pikatakana' => "\x{30D4}",
+	'pisymbolgreek' => "\x{03D6}",
+	'piwrarmenian' => "\x{0583}",
+	'plusbelowcmb' => "\x{031F}",
+	'pluscircle' => "\x{2295}",
+	'plusmod' => "\x{02D6}",
+	'plusmonospace' => "\x{FF0B}",
+	'plussmall' => "\x{FE62}",
+	'plussuperior' => "\x{207A}",
+	'pmonospace' => "\x{FF50}",
+	'pmsquare' => "\x{33D8}",
+	'pohiragana' => "\x{307D}",
+	'pointingindexdownwhite' => "\x{261F}",
+	'pointingindexleftwhite' => "\x{261C}",
+	'pointingindexrightwhite' => "\x{261E}",
+	'pointingindexupwhite' => "\x{261D}",
+	'pokatakana' => "\x{30DD}",
+	'poplathai' => "\x{0E1B}",
+	'postalmark' => "\x{3012}",
+	'postalmarkface' => "\x{3020}",
+	'pparen' => "\x{24AB}",
+	'precedes' => "\x{227A}",
+	'primemod' => "\x{02B9}",
+	'primereversed' => "\x{2035}",
+	'projective' => "\x{2305}",
+	'prolongedkana' => "\x{30FC}",
+	'propellor' => "\x{2318}",
+	'proportion' => "\x{2237}",
+	'psicyrillic' => "\x{0471}",
+	'psilipneumatacyrilliccmb' => "\x{0486}",
+	'pssquare' => "\x{33B0}",
+	'puhiragana' => "\x{3077}",
+	'pukatakana' => "\x{30D7}",
+	'pvsquare' => "\x{33B4}",
+	'pwsquare' => "\x{33BA}",
+	'qadeva' => "\x{0958}",
+	'qadmahebrew' => "\x{05A8}",
+	'qafarabic' => "\x{0642}",
+	'qaffinalarabic' => "\x{FED6}",
+	'qafinitialarabic' => "\x{FED7}",
+	'qafmedialarabic' => "\x{FED8}",
+	'qamats' => "\x{05B8}",
+	'qamats10' => "\x{05B8}",
+	'qamats1a' => "\x{05B8}",
+	'qamats1c' => "\x{05B8}",
+	'qamats27' => "\x{05B8}",
+	'qamats29' => "\x{05B8}",
+	'qamats33' => "\x{05B8}",
+	'qamatsde' => "\x{05B8}",
+	'qamatshebrew' => "\x{05B8}",
+	'qamatsnarrowhebrew' => "\x{05B8}",
+	'qamatsqatanhebrew' => "\x{05B8}",
+	'qamatsqatannarrowhebrew' => "\x{05B8}",
+	'qamatsqatanquarterhebrew' => "\x{05B8}",
+	'qamatsqatanwidehebrew' => "\x{05B8}",
+	'qamatsquarterhebrew' => "\x{05B8}",
+	'qamatswidehebrew' => "\x{05B8}",
+	'qarneyparahebrew' => "\x{059F}",
+	'qbopomofo' => "\x{3111}",
+	'qcircle' => "\x{24E0}",
+	'qhook' => "\x{02A0}",
+	'qmonospace' => "\x{FF51}",
+	'qof' => "\x{05E7}",
+	'qofdagesh' => "\x{FB47}",
+	'qofdageshhebrew' => "\x{FB47}",
+	'qofhatafpatah' => "\x{05E7}\x{05B2}",
+	'qofhatafpatahhebrew' => "\x{05E7}\x{05B2}",
+	'qofhatafsegol' => "\x{05E7}\x{05B1}",
+	'qofhatafsegolhebrew' => "\x{05E7}\x{05B1}",
+	'qofhebrew' => "\x{05E7}",
+	'qofhiriq' => "\x{05E7}\x{05B4}",
+	'qofhiriqhebrew' => "\x{05E7}\x{05B4}",
+	'qofholam' => "\x{05E7}\x{05B9}",
+	'qofholamhebrew' => "\x{05E7}\x{05B9}",
+	'qofpatah' => "\x{05E7}\x{05B7}",
+	'qofpatahhebrew' => "\x{05E7}\x{05B7}",
+	'qofqamats' => "\x{05E7}\x{05B8}",
+	'qofqamatshebrew' => "\x{05E7}\x{05B8}",
+	'qofqubuts' => "\x{05E7}\x{05BB}",
+	'qofqubutshebrew' => "\x{05E7}\x{05BB}",
+	'qofsegol' => "\x{05E7}\x{05B6}",
+	'qofsegolhebrew' => "\x{05E7}\x{05B6}",
+	'qofsheva' => "\x{05E7}\x{05B0}",
+	'qofshevahebrew' => "\x{05E7}\x{05B0}",
+	'qoftsere' => "\x{05E7}\x{05B5}",
+	'qoftserehebrew' => "\x{05E7}\x{05B5}",
+	'qparen' => "\x{24AC}",
+	'quarternote' => "\x{2669}",
+	'qubuts' => "\x{05BB}",
+	'qubuts18' => "\x{05BB}",
+	'qubuts25' => "\x{05BB}",
+	'qubuts31' => "\x{05BB}",
+	'qubutshebrew' => "\x{05BB}",
+	'qubutsnarrowhebrew' => "\x{05BB}",
+	'qubutsquarterhebrew' => "\x{05BB}",
+	'qubutswidehebrew' => "\x{05BB}",
+	'questionarabic' => "\x{061F}",
+	'questionarmenian' => "\x{055E}",
+	'questiondownsmall' => "\x{F7BF}",
+	'questiongreek' => "\x{037E}",
+	'questionmonospace' => "\x{FF1F}",
+	'questionsmall' => "\x{F73F}",
+	'quotedblmonospace' => "\x{FF02}",
+	'quotedblprime' => "\x{301E}",
+	'quotedblprimereversed' => "\x{301D}",
+	'quoteleftreversed' => "\x{201B}",
+	'quoterightn' => "\x{0149}",
+	'quotesinglemonospace' => "\x{FF07}",
+	'raarmenian' => "\x{057C}",
+	'rabengali' => "\x{09B0}",
+	'radeva' => "\x{0930}",
+	'radicalex' => "\x{F8E5}",
+	'radoverssquare' => "\x{33AE}",
+	'radoverssquaredsquare' => "\x{33AF}",
+	'radsquare' => "\x{33AD}",
+	'rafe' => "\x{05BF}",
+	'rafehebrew' => "\x{05BF}",
+	'ragujarati' => "\x{0AB0}",
+	'ragurmukhi' => "\x{0A30}",
+	'rahiragana' => "\x{3089}",
+	'rakatakana' => "\x{30E9}",
+	'rakatakanahalfwidth' => "\x{FF97}",
+	'ralowerdiagonalbengali' => "\x{09F1}",
+	'ramiddlediagonalbengali' => "\x{09F0}",
+	'ramshorn' => "\x{0264}",
+	'ratio' => "\x{2236}",
+	'rbopomofo' => "\x{3116}",
+	'rcedilla' => "\x{0157}",
+	'rcircle' => "\x{24E1}",
+	'rdblgrave' => "\x{0211}",
+	'rdotaccent' => "\x{1E59}",
+	'rdotbelow' => "\x{1E5B}",
+	'rdotbelowmacron' => "\x{1E5D}",
+	'referencemark' => "\x{203B}",
+	'registersans' => "\x{F8E8}",
+	'registerserif' => "\x{F6DA}",
+	'reharabic' => "\x{0631}",
+	'reharmenian' => "\x{0580}",
+	'rehfinalarabic' => "\x{FEAE}",
+	'rehiragana' => "\x{308C}",
+	'rehyehaleflamarabic' => "\x{0631}\x{FEF3}\x{FE8E}\x{0644}",
+	'rekatakana' => "\x{30EC}",
+	'rekatakanahalfwidth' => "\x{FF9A}",
+	'resh' => "\x{05E8}",
+	'reshdageshhebrew' => "\x{FB48}",
+	'reshhatafpatah' => "\x{05E8}\x{05B2}",
+	'reshhatafpatahhebrew' => "\x{05E8}\x{05B2}",
+	'reshhatafsegol' => "\x{05E8}\x{05B1}",
+	'reshhatafsegolhebrew' => "\x{05E8}\x{05B1}",
+	'reshhebrew' => "\x{05E8}",
+	'reshhiriq' => "\x{05E8}\x{05B4}",
+	'reshhiriqhebrew' => "\x{05E8}\x{05B4}",
+	'reshholam' => "\x{05E8}\x{05B9}",
+	'reshholamhebrew' => "\x{05E8}\x{05B9}",
+	'reshpatah' => "\x{05E8}\x{05B7}",
+	'reshpatahhebrew' => "\x{05E8}\x{05B7}",
+	'reshqamats' => "\x{05E8}\x{05B8}",
+	'reshqamatshebrew' => "\x{05E8}\x{05B8}",
+	'reshqubuts' => "\x{05E8}\x{05BB}",
+	'reshqubutshebrew' => "\x{05E8}\x{05BB}",
+	'reshsegol' => "\x{05E8}\x{05B6}",
+	'reshsegolhebrew' => "\x{05E8}\x{05B6}",
+	'reshsheva' => "\x{05E8}\x{05B0}",
+	'reshshevahebrew' => "\x{05E8}\x{05B0}",
+	'reshtsere' => "\x{05E8}\x{05B5}",
+	'reshtserehebrew' => "\x{05E8}\x{05B5}",
+	'reversedtilde' => "\x{223D}",
+	'reviahebrew' => "\x{0597}",
+	'reviamugrashhebrew' => "\x{0597}",
+	'rfishhook' => "\x{027E}",
+	'rfishhookreversed' => "\x{027F}",
+	'rhabengali' => "\x{09DD}",
+	'rhadeva' => "\x{095D}",
+	'rhook' => "\x{027D}",
+	'rhookturned' => "\x{027B}",
+	'rhookturnedsuperior' => "\x{02B5}",
+	'rhosymbolgreek' => "\x{03F1}",
+	'rhotichookmod' => "\x{02DE}",
+	'rieulacirclekorean' => "\x{3271}",
+	'rieulaparenkorean' => "\x{3211}",
+	'rieulcirclekorean' => "\x{3263}",
+	'rieulhieuhkorean' => "\x{3140}",
+	'rieulkiyeokkorean' => "\x{313A}",
+	'rieulkiyeoksioskorean' => "\x{3169}",
+	'rieulkorean' => "\x{3139}",
+	'rieulmieumkorean' => "\x{313B}",
+	'rieulpansioskorean' => "\x{316C}",
+	'rieulparenkorean' => "\x{3203}",
+	'rieulphieuphkorean' => "\x{313F}",
+	'rieulpieupkorean' => "\x{313C}",
+	'rieulpieupsioskorean' => "\x{316B}",
+	'rieulsioskorean' => "\x{313D}",
+	'rieulthieuthkorean' => "\x{313E}",
+	'rieultikeutkorean' => "\x{316A}",
+	'rieulyeorinhieuhkorean' => "\x{316D}",
+	'rightangle' => "\x{221F}",
+	'righttackbelowcmb' => "\x{0319}",
+	'righttriangle' => "\x{22BF}",
+	'rihiragana' => "\x{308A}",
+	'rikatakana' => "\x{30EA}",
+	'rikatakanahalfwidth' => "\x{FF98}",
+	'ringbelowcmb' => "\x{0325}",
+	'ringcmb' => "\x{030A}",
+	'ringhalfleft' => "\x{02BF}",
+	'ringhalfleftarmenian' => "\x{0559}",
+	'ringhalfleftbelowcmb' => "\x{031C}",
+	'ringhalfleftcentered' => "\x{02D3}",
+	'ringhalfright' => "\x{02BE}",
+	'ringhalfrightbelowcmb' => "\x{0339}",
+	'ringhalfrightcentered' => "\x{02D2}",
+	'rinvertedbreve' => "\x{0213}",
+	'rittorusquare' => "\x{3351}",
+	'rlinebelow' => "\x{1E5F}",
+	'rlongleg' => "\x{027C}",
+	'rlonglegturned' => "\x{027A}",
+	'rmonospace' => "\x{FF52}",
+	'rohiragana' => "\x{308D}",
+	'rokatakana' => "\x{30ED}",
+	'rokatakanahalfwidth' => "\x{FF9B}",
+	'roruathai' => "\x{0E23}",
+	'rparen' => "\x{24AD}",
+	'rrabengali' => "\x{09DC}",
+	'rradeva' => "\x{0931}",
+	'rragurmukhi' => "\x{0A5C}",
+	'rreharabic' => "\x{0691}",
+	'rrehfinalarabic' => "\x{FB8D}",
+	'rrvocalicbengali' => "\x{09E0}",
+	'rrvocalicdeva' => "\x{0960}",
+	'rrvocalicgujarati' => "\x{0AE0}",
+	'rrvocalicvowelsignbengali' => "\x{09C4}",
+	'rrvocalicvowelsigndeva' => "\x{0944}",
+	'rrvocalicvowelsigngujarati' => "\x{0AC4}",
+	'rsuperior' => "\x{F6F1}",
+	'rturned' => "\x{0279}",
+	'rturnedsuperior' => "\x{02B4}",
+	'ruhiragana' => "\x{308B}",
+	'rukatakana' => "\x{30EB}",
+	'rukatakanahalfwidth' => "\x{FF99}",
+	'rupeemarkbengali' => "\x{09F2}",
+	'rupeesignbengali' => "\x{09F3}",
+	'rupiah' => "\x{F6DD}",
+	'ruthai' => "\x{0E24}",
+	'rvocalicbengali' => "\x{098B}",
+	'rvocalicdeva' => "\x{090B}",
+	'rvocalicgujarati' => "\x{0A8B}",
+	'rvocalicvowelsignbengali' => "\x{09C3}",
+	'rvocalicvowelsigndeva' => "\x{0943}",
+	'rvocalicvowelsigngujarati' => "\x{0AC3}",
+	'sabengali' => "\x{09B8}",
+	'sacutedotaccent' => "\x{1E65}",
+	'sadarabic' => "\x{0635}",
+	'sadeva' => "\x{0938}",
+	'sadfinalarabic' => "\x{FEBA}",
+	'sadinitialarabic' => "\x{FEBB}",
+	'sadmedialarabic' => "\x{FEBC}",
+	'sagujarati' => "\x{0AB8}",
+	'sagurmukhi' => "\x{0A38}",
+	'sahiragana' => "\x{3055}",
+	'sakatakana' => "\x{30B5}",
+	'sakatakanahalfwidth' => "\x{FF7B}",
+	'sallallahoualayhewasallamarabic' => "\x{FDFA}",
+	'samekh' => "\x{05E1}",
+	'samekhdagesh' => "\x{FB41}",
+	'samekhdageshhebrew' => "\x{FB41}",
+	'samekhhebrew' => "\x{05E1}",
+	'saraaathai' => "\x{0E32}",
+	'saraaethai' => "\x{0E41}",
+	'saraaimaimalaithai' => "\x{0E44}",
+	'saraaimaimuanthai' => "\x{0E43}",
+	'saraamthai' => "\x{0E33}",
+	'saraathai' => "\x{0E30}",
+	'saraethai' => "\x{0E40}",
+	'saraiileftthai' => "\x{F886}",
+	'saraiithai' => "\x{0E35}",
+	'saraileftthai' => "\x{F885}",
+	'saraithai' => "\x{0E34}",
+	'saraothai' => "\x{0E42}",
+	'saraueeleftthai' => "\x{F888}",
+	'saraueethai' => "\x{0E37}",
+	'saraueleftthai' => "\x{F887}",
+	'sarauethai' => "\x{0E36}",
+	'sarauthai' => "\x{0E38}",
+	'sarauuthai' => "\x{0E39}",
+	'sbopomofo' => "\x{3119}",
+	'scarondotaccent' => "\x{1E67}",
+	'schwa' => "\x{0259}",
+	'schwacyrillic' => "\x{04D9}",
+	'schwadieresiscyrillic' => "\x{04DB}",
+	'schwahook' => "\x{025A}",
+	'scircle' => "\x{24E2}",
+	'sdotaccent' => "\x{1E61}",
+	'sdotbelow' => "\x{1E63}",
+	'sdotbelowdotaccent' => "\x{1E69}",
+	'seagullbelowcmb' => "\x{033C}",
+	'secondtonechinese' => "\x{02CA}",
+	'seenarabic' => "\x{0633}",
+	'seenfinalarabic' => "\x{FEB2}",
+	'seeninitialarabic' => "\x{FEB3}",
+	'seenmedialarabic' => "\x{FEB4}",
+	'segol' => "\x{05B6}",
+	'segol13' => "\x{05B6}",
+	'segol1f' => "\x{05B6}",
+	'segol2c' => "\x{05B6}",
+	'segolhebrew' => "\x{05B6}",
+	'segolnarrowhebrew' => "\x{05B6}",
+	'segolquarterhebrew' => "\x{05B6}",
+	'segoltahebrew' => "\x{0592}",
+	'segolwidehebrew' => "\x{05B6}",
+	'seharmenian' => "\x{057D}",
+	'sehiragana' => "\x{305B}",
+	'sekatakana' => "\x{30BB}",
+	'sekatakanahalfwidth' => "\x{FF7E}",
+	'semicolonarabic' => "\x{061B}",
+	'semicolonmonospace' => "\x{FF1B}",
+	'semicolonsmall' => "\x{FE54}",
+	'semivoicedmarkkana' => "\x{309C}",
+	'semivoicedmarkkanahalfwidth' => "\x{FF9F}",
+	'sentisquare' => "\x{3322}",
+	'sentosquare' => "\x{3323}",
+	'sevenarabic' => "\x{0667}",
+	'sevenbengali' => "\x{09ED}",
+	'sevencircle' => "\x{2466}",
+	'sevencircleinversesansserif' => "\x{2790}",
+	'sevendeva' => "\x{096D}",
+	'sevengujarati' => "\x{0AED}",
+	'sevengurmukhi' => "\x{0A6D}",
+	'sevenhackarabic' => "\x{0667}",
+	'sevenhangzhou' => "\x{3027}",
+	'sevenideographicparen' => "\x{3226}",
+	'seveninferior' => "\x{2087}",
+	'sevenmonospace' => "\x{FF17}",
+	'sevenoldstyle' => "\x{F737}",
+	'sevenparen' => "\x{247A}",
+	'sevenperiod' => "\x{248E}",
+	'sevenpersian' => "\x{06F7}",
+	'sevenroman' => "\x{2176}",
+	'sevensuperior' => "\x{2077}",
+	'seventeencircle' => "\x{2470}",
+	'seventeenparen' => "\x{2484}",
+	'seventeenperiod' => "\x{2498}",
+	'seventhai' => "\x{0E57}",
+	'sfthyphen' => "\x{00AD}",
+	'shaarmenian' => "\x{0577}",
+	'shabengali' => "\x{09B6}",
+	'shacyrillic' => "\x{0448}",
+	'shaddaarabic' => "\x{0651}",
+	'shaddadammaarabic' => "\x{FC61}",
+	'shaddadammatanarabic' => "\x{FC5E}",
+	'shaddafathaarabic' => "\x{FC60}",
+	'shaddafathatanarabic' => "\x{0651}\x{064B}",
+	'shaddakasraarabic' => "\x{FC62}",
+	'shaddakasratanarabic' => "\x{FC5F}",
+	'shadedark' => "\x{2593}",
+	'shadelight' => "\x{2591}",
+	'shademedium' => "\x{2592}",
+	'shadeva' => "\x{0936}",
+	'shagujarati' => "\x{0AB6}",
+	'shagurmukhi' => "\x{0A36}",
+	'shalshelethebrew' => "\x{0593}",
+	'shbopomofo' => "\x{3115}",
+	'shchacyrillic' => "\x{0449}",
+	'sheenarabic' => "\x{0634}",
+	'sheenfinalarabic' => "\x{FEB6}",
+	'sheeninitialarabic' => "\x{FEB7}",
+	'sheenmedialarabic' => "\x{FEB8}",
+	'sheicoptic' => "\x{03E3}",
+	'sheqel' => "\x{20AA}",
+	'sheqelhebrew' => "\x{20AA}",
+	'sheva' => "\x{05B0}",
+	'sheva115' => "\x{05B0}",
+	'sheva15' => "\x{05B0}",
+	'sheva22' => "\x{05B0}",
+	'sheva2e' => "\x{05B0}",
+	'shevahebrew' => "\x{05B0}",
+	'shevanarrowhebrew' => "\x{05B0}",
+	'shevaquarterhebrew' => "\x{05B0}",
+	'shevawidehebrew' => "\x{05B0}",
+	'shhacyrillic' => "\x{04BB}",
+	'shimacoptic' => "\x{03ED}",
+	'shin' => "\x{05E9}",
+	'shindagesh' => "\x{FB49}",
+	'shindageshhebrew' => "\x{FB49}",
+	'shindageshshindot' => "\x{FB2C}",
+	'shindageshshindothebrew' => "\x{FB2C}",
+	'shindageshsindot' => "\x{FB2D}",
+	'shindageshsindothebrew' => "\x{FB2D}",
+	'shindothebrew' => "\x{05C1}",
+	'shinhebrew' => "\x{05E9}",
+	'shinshindot' => "\x{FB2A}",
+	'shinshindothebrew' => "\x{FB2A}",
+	'shinsindot' => "\x{FB2B}",
+	'shinsindothebrew' => "\x{FB2B}",
+	'shook' => "\x{0282}",
+	'sigmafinal' => "\x{03C2}",
+	'sigmalunatesymbolgreek' => "\x{03F2}",
+	'sihiragana' => "\x{3057}",
+	'sikatakana' => "\x{30B7}",
+	'sikatakanahalfwidth' => "\x{FF7C}",
+	'siluqhebrew' => "\x{05BD}",
+	'siluqlefthebrew' => "\x{05BD}",
+	'sindothebrew' => "\x{05C2}",
+	'siosacirclekorean' => "\x{3274}",
+	'siosaparenkorean' => "\x{3214}",
+	'sioscieuckorean' => "\x{317E}",
+	'sioscirclekorean' => "\x{3266}",
+	'sioskiyeokkorean' => "\x{317A}",
+	'sioskorean' => "\x{3145}",
+	'siosnieunkorean' => "\x{317B}",
+	'siosparenkorean' => "\x{3206}",
+	'siospieupkorean' => "\x{317D}",
+	'siostikeutkorean' => "\x{317C}",
+	'sixarabic' => "\x{0666}",
+	'sixbengali' => "\x{09EC}",
+	'sixcircle' => "\x{2465}",
+	'sixcircleinversesansserif' => "\x{278F}",
+	'sixdeva' => "\x{096C}",
+	'sixgujarati' => "\x{0AEC}",
+	'sixgurmukhi' => "\x{0A6C}",
+	'sixhackarabic' => "\x{0666}",
+	'sixhangzhou' => "\x{3026}",
+	'sixideographicparen' => "\x{3225}",
+	'sixinferior' => "\x{2086}",
+	'sixmonospace' => "\x{FF16}",
+	'sixoldstyle' => "\x{F736}",
+	'sixparen' => "\x{2479}",
+	'sixperiod' => "\x{248D}",
+	'sixpersian' => "\x{06F6}",
+	'sixroman' => "\x{2175}",
+	'sixsuperior' => "\x{2076}",
+	'sixteencircle' => "\x{246F}",
+	'sixteencurrencydenominatorbengali' => "\x{09F9}",
+	'sixteenparen' => "\x{2483}",
+	'sixteenperiod' => "\x{2497}",
+	'sixthai' => "\x{0E56}",
+	'slashmonospace' => "\x{FF0F}",
+	'slong' => "\x{017F}",
+	'slongdotaccent' => "\x{1E9B}",
+	'smonospace' => "\x{FF53}",
+	'sofpasuqhebrew' => "\x{05C3}",
+	'softhyphen' => "\x{00AD}",
+	'softsigncyrillic' => "\x{044C}",
+	'sohiragana' => "\x{305D}",
+	'sokatakana' => "\x{30BD}",
+	'sokatakanahalfwidth' => "\x{FF7F}",
+	'soliduslongoverlaycmb' => "\x{0338}",
+	'solidusshortoverlaycmb' => "\x{0337}",
+	'sorusithai' => "\x{0E29}",
+	'sosalathai' => "\x{0E28}",
+	'sosothai' => "\x{0E0B}",
+	'sosuathai' => "\x{0E2A}",
+	'spacehackarabic' => "\x{0020}",
+	'spadesuitblack' => "\x{2660}",
+	'spadesuitwhite' => "\x{2664}",
+	'sparen' => "\x{24AE}",
+	'squarebelowcmb' => "\x{033B}",
+	'squarecc' => "\x{33C4}",
+	'squarecm' => "\x{339D}",
+	'squarediagonalcrosshatchfill' => "\x{25A9}",
+	'squarehorizontalfill' => "\x{25A4}",
+	'squarekg' => "\x{338F}",
+	'squarekm' => "\x{339E}",
+	'squarekmcapital' => "\x{33CE}",
+	'squareln' => "\x{33D1}",
+	'squarelog' => "\x{33D2}",
+	'squaremg' => "\x{338E}",
+	'squaremil' => "\x{33D5}",
+	'squaremm' => "\x{339C}",
+	'squaremsquared' => "\x{33A1}",
+	'squareorthogonalcrosshatchfill' => "\x{25A6}",
+	'squareupperlefttolowerrightfill' => "\x{25A7}",
+	'squareupperrighttolowerleftfill' => "\x{25A8}",
+	'squareverticalfill' => "\x{25A5}",
+	'squarewhitewithsmallblack' => "\x{25A3}",
+	'srsquare' => "\x{33DB}",
+	'ssabengali' => "\x{09B7}",
+	'ssadeva' => "\x{0937}",
+	'ssagujarati' => "\x{0AB7}",
+	'ssangcieuckorean' => "\x{3149}",
+	'ssanghieuhkorean' => "\x{3185}",
+	'ssangieungkorean' => "\x{3180}",
+	'ssangkiyeokkorean' => "\x{3132}",
+	'ssangnieunkorean' => "\x{3165}",
+	'ssangpieupkorean' => "\x{3143}",
+	'ssangsioskorean' => "\x{3146}",
+	'ssangtikeutkorean' => "\x{3138}",
+	'ssuperior' => "\x{F6F2}",
+	'sterlingmonospace' => "\x{FFE1}",
+	'strokelongoverlaycmb' => "\x{0336}",
+	'strokeshortoverlaycmb' => "\x{0335}",
+	'subset' => "\x{2282}",
+	'subsetnotequal' => "\x{228A}",
+	'subsetorequal' => "\x{2286}",
+	'succeeds' => "\x{227B}",
+	'suhiragana' => "\x{3059}",
+	'sukatakana' => "\x{30B9}",
+	'sukatakanahalfwidth' => "\x{FF7D}",
+	'sukunarabic' => "\x{0652}",
+	'superset' => "\x{2283}",
+	'supersetnotequal' => "\x{228B}",
+	'supersetorequal' => "\x{2287}",
+	'svsquare' => "\x{33DC}",
+	'syouwaerasquare' => "\x{337C}",
+	'tabengali' => "\x{09A4}",
+	'tackdown' => "\x{22A4}",
+	'tackleft' => "\x{22A3}",
+	'tadeva' => "\x{0924}",
+	'tagujarati' => "\x{0AA4}",
+	'tagurmukhi' => "\x{0A24}",
+	'taharabic' => "\x{0637}",
+	'tahfinalarabic' => "\x{FEC2}",
+	'tahinitialarabic' => "\x{FEC3}",
+	'tahiragana' => "\x{305F}",
+	'tahmedialarabic' => "\x{FEC4}",
+	'taisyouerasquare' => "\x{337D}",
+	'takatakana' => "\x{30BF}",
+	'takatakanahalfwidth' => "\x{FF80}",
+	'tatweelarabic' => "\x{0640}",
+	'tav' => "\x{05EA}",
+	'tavdages' => "\x{FB4A}",
+	'tavdagesh' => "\x{FB4A}",
+	'tavdageshhebrew' => "\x{FB4A}",
+	'tavhebrew' => "\x{05EA}",
+	'tbopomofo' => "\x{310A}",
+	'tccurl' => "\x{02A8}",
+	'tcedilla' => "\x{0163}",
+	'tcheharabic' => "\x{0686}",
+	'tchehfinalarabic' => "\x{FB7B}",
+	'tchehinitialarabic' => "\x{FB7C}",
+	'tchehmedialarabic' => "\x{FB7D}",
+	'tchehmeeminitialarabic' => "\x{FB7C}\x{FEE4}",
+	'tcircle' => "\x{24E3}",
+	'tcircumflexbelow' => "\x{1E71}",
+	'tdieresis' => "\x{1E97}",
+	'tdotaccent' => "\x{1E6B}",
+	'tdotbelow' => "\x{1E6D}",
+	'tecyrillic' => "\x{0442}",
+	'tedescendercyrillic' => "\x{04AD}",
+	'teharabic' => "\x{062A}",
+	'tehfinalarabic' => "\x{FE96}",
+	'tehhahinitialarabic' => "\x{FCA2}",
+	'tehhahisolatedarabic' => "\x{FC0C}",
+	'tehinitialarabic' => "\x{FE97}",
+	'tehiragana' => "\x{3066}",
+	'tehjeeminitialarabic' => "\x{FCA1}",
+	'tehjeemisolatedarabic' => "\x{FC0B}",
+	'tehmarbutaarabic' => "\x{0629}",
+	'tehmarbutafinalarabic' => "\x{FE94}",
+	'tehmedialarabic' => "\x{FE98}",
+	'tehmeeminitialarabic' => "\x{FCA4}",
+	'tehmeemisolatedarabic' => "\x{FC0E}",
+	'tehnoonfinalarabic' => "\x{FC73}",
+	'tekatakana' => "\x{30C6}",
+	'tekatakanahalfwidth' => "\x{FF83}",
+	'telephone' => "\x{2121}",
+	'telephoneblack' => "\x{260E}",
+	'telishagedolahebrew' => "\x{05A0}",
+	'telishaqetanahebrew' => "\x{05A9}",
+	'tencircle' => "\x{2469}",
+	'tenideographicparen' => "\x{3229}",
+	'tenparen' => "\x{247D}",
+	'tenperiod' => "\x{2491}",
+	'tenroman' => "\x{2179}",
+	'tesh' => "\x{02A7}",
+	'tet' => "\x{05D8}",
+	'tetdagesh' => "\x{FB38}",
+	'tetdageshhebrew' => "\x{FB38}",
+	'tethebrew' => "\x{05D8}",
+	'tetsecyrillic' => "\x{04B5}",
+	'tevirhebrew' => "\x{059B}",
+	'tevirlefthebrew' => "\x{059B}",
+	'thabengali' => "\x{09A5}",
+	'thadeva' => "\x{0925}",
+	'thagujarati' => "\x{0AA5}",
+	'thagurmukhi' => "\x{0A25}",
+	'thalarabic' => "\x{0630}",
+	'thalfinalarabic' => "\x{FEAC}",
+	'thanthakhatlowleftthai' => "\x{F898}",
+	'thanthakhatlowrightthai' => "\x{F897}",
+	'thanthakhatthai' => "\x{0E4C}",
+	'thanthakhatupperleftthai' => "\x{F896}",
+	'theharabic' => "\x{062B}",
+	'thehfinalarabic' => "\x{FE9A}",
+	'thehinitialarabic' => "\x{FE9B}",
+	'thehmedialarabic' => "\x{FE9C}",
+	'thereexists' => "\x{2203}",
+	'thetasymbolgreek' => "\x{03D1}",
+	'thieuthacirclekorean' => "\x{3279}",
+	'thieuthaparenkorean' => "\x{3219}",
+	'thieuthcirclekorean' => "\x{326B}",
+	'thieuthkorean' => "\x{314C}",
+	'thieuthparenkorean' => "\x{320B}",
+	'thirteencircle' => "\x{246C}",
+	'thirteenparen' => "\x{2480}",
+	'thirteenperiod' => "\x{2494}",
+	'thonangmonthothai' => "\x{0E11}",
+	'thook' => "\x{01AD}",
+	'thophuthaothai' => "\x{0E12}",
+	'thothahanthai' => "\x{0E17}",
+	'thothanthai' => "\x{0E10}",
+	'thothongthai' => "\x{0E18}",
+	'thothungthai' => "\x{0E16}",
+	'thousandcyrillic' => "\x{0482}",
+	'thousandsseparatorarabic' => "\x{066C}",
+	'thousandsseparatorpersian' => "\x{066C}",
+	'threearabic' => "\x{0663}",
+	'threebengali' => "\x{09E9}",
+	'threecircle' => "\x{2462}",
+	'threecircleinversesansserif' => "\x{278C}",
+	'threedeva' => "\x{0969}",
+	'threegujarati' => "\x{0AE9}",
+	'threegurmukhi' => "\x{0A69}",
+	'threehackarabic' => "\x{0663}",
+	'threehangzhou' => "\x{3023}",
+	'threeideographicparen' => "\x{3222}",
+	'threeinferior' => "\x{2083}",
+	'threemonospace' => "\x{FF13}",
+	'threenumeratorbengali' => "\x{09F6}",
+	'threeoldstyle' => "\x{F733}",
+	'threeparen' => "\x{2476}",
+	'threeperiod' => "\x{248A}",
+	'threepersian' => "\x{06F3}",
+	'threequartersemdash' => "\x{F6DE}",
+	'threeroman' => "\x{2172}",
+	'threethai' => "\x{0E53}",
+	'thzsquare' => "\x{3394}",
+	'tihiragana' => "\x{3061}",
+	'tikatakana' => "\x{30C1}",
+	'tikatakanahalfwidth' => "\x{FF81}",
+	'tikeutacirclekorean' => "\x{3270}",
+	'tikeutaparenkorean' => "\x{3210}",
+	'tikeutcirclekorean' => "\x{3262}",
+	'tikeutkorean' => "\x{3137}",
+	'tikeutparenkorean' => "\x{3202}",
+	'tildebelowcmb' => "\x{0330}",
+	'tildecmb' => "\x{0303}",
+	'tildedoublecmb' => "\x{0360}",
+	'tildeoperator' => "\x{223C}",
+	'tildeoverlaycmb' => "\x{0334}",
+	'tildeverticalcmb' => "\x{033E}",
+	'timescircle' => "\x{2297}",
+	'tipehahebrew' => "\x{0596}",
+	'tipehalefthebrew' => "\x{0596}",
+	'tippigurmukhi' => "\x{0A70}",
+	'titlocyrilliccmb' => "\x{0483}",
+	'tiwnarmenian' => "\x{057F}",
+	'tlinebelow' => "\x{1E6F}",
+	'tmonospace' => "\x{FF54}",
+	'toarmenian' => "\x{0569}",
+	'tohiragana' => "\x{3068}",
+	'tokatakana' => "\x{30C8}",
+	'tokatakanahalfwidth' => "\x{FF84}",
+	'tonebarextrahighmod' => "\x{02E5}",
+	'tonebarextralowmod' => "\x{02E9}",
+	'tonebarhighmod' => "\x{02E6}",
+	'tonebarlowmod' => "\x{02E8}",
+	'tonebarmidmod' => "\x{02E7}",
+	'tonefive' => "\x{01BD}",
+	'tonesix' => "\x{0185}",
+	'tonetwo' => "\x{01A8}",
+	'tonsquare' => "\x{3327}",
+	'topatakthai' => "\x{0E0F}",
+	'tortoiseshellbracketleft' => "\x{3014}",
+	'tortoiseshellbracketleftsmall' => "\x{FE5D}",
+	'tortoiseshellbracketleftvertical' => "\x{FE39}",
+	'tortoiseshellbracketright' => "\x{3015}",
+	'tortoiseshellbracketrightsmall' => "\x{FE5E}",
+	'tortoiseshellbracketrightvertical' => "\x{FE3A}",
+	'totaothai' => "\x{0E15}",
+	'tpalatalhook' => "\x{01AB}",
+	'tparen' => "\x{24AF}",
+	'trademarksans' => "\x{F8EA}",
+	'trademarkserif' => "\x{F6DB}",
+	'tretroflexhook' => "\x{0288}",
+	'ts' => "\x{02A6}",
+	'tsadi' => "\x{05E6}",
+	'tsadidagesh' => "\x{FB46}",
+	'tsadidageshhebrew' => "\x{FB46}",
+	'tsadihebrew' => "\x{05E6}",
+	'tsecyrillic' => "\x{0446}",
+	'tsere' => "\x{05B5}",
+	'tsere12' => "\x{05B5}",
+	'tsere1e' => "\x{05B5}",
+	'tsere2b' => "\x{05B5}",
+	'tserehebrew' => "\x{05B5}",
+	'tserenarrowhebrew' => "\x{05B5}",
+	'tserequarterhebrew' => "\x{05B5}",
+	'tserewidehebrew' => "\x{05B5}",
+	'tshecyrillic' => "\x{045B}",
+	'tsuperior' => "\x{F6F3}",
+	'ttabengali' => "\x{099F}",
+	'ttadeva' => "\x{091F}",
+	'ttagujarati' => "\x{0A9F}",
+	'ttagurmukhi' => "\x{0A1F}",
+	'tteharabic' => "\x{0679}",
+	'ttehfinalarabic' => "\x{FB67}",
+	'ttehinitialarabic' => "\x{FB68}",
+	'ttehmedialarabic' => "\x{FB69}",
+	'tthabengali' => "\x{09A0}",
+	'tthadeva' => "\x{0920}",
+	'tthagujarati' => "\x{0AA0}",
+	'tthagurmukhi' => "\x{0A20}",
+	'tturned' => "\x{0287}",
+	'tuhiragana' => "\x{3064}",
+	'tukatakana' => "\x{30C4}",
+	'tukatakanahalfwidth' => "\x{FF82}",
+	'tusmallhiragana' => "\x{3063}",
+	'tusmallkatakana' => "\x{30C3}",
+	'tusmallkatakanahalfwidth' => "\x{FF6F}",
+	'twelvecircle' => "\x{246B}",
+	'twelveparen' => "\x{247F}",
+	'twelveperiod' => "\x{2493}",
+	'twelveroman' => "\x{217B}",
+	'twentycircle' => "\x{2473}",
+	'twentyhangzhou' => "\x{5344}",
+	'twentyparen' => "\x{2487}",
+	'twentyperiod' => "\x{249B}",
+	'twoarabic' => "\x{0662}",
+	'twobengali' => "\x{09E8}",
+	'twocircle' => "\x{2461}",
+	'twocircleinversesansserif' => "\x{278B}",
+	'twodeva' => "\x{0968}",
+	'twodotleader' => "\x{2025}",
+	'twodotleadervertical' => "\x{FE30}",
+	'twogujarati' => "\x{0AE8}",
+	'twogurmukhi' => "\x{0A68}",
+	'twohackarabic' => "\x{0662}",
+	'twohangzhou' => "\x{3022}",
+	'twoideographicparen' => "\x{3221}",
+	'twoinferior' => "\x{2082}",
+	'twomonospace' => "\x{FF12}",
+	'twonumeratorbengali' => "\x{09F5}",
+	'twooldstyle' => "\x{F732}",
+	'twoparen' => "\x{2475}",
+	'twoperiod' => "\x{2489}",
+	'twopersian' => "\x{06F2}",
+	'tworoman' => "\x{2171}",
+	'twostroke' => "\x{01BB}",
+	'twothai' => "\x{0E52}",
+	'ubar' => "\x{0289}",
+	'ubengali' => "\x{0989}",
+	'ubopomofo' => "\x{3128}",
+	'ucaron' => "\x{01D4}",
+	'ucircle' => "\x{24E4}",
+	'ucircumflexbelow' => "\x{1E77}",
+	'ucyrillic' => "\x{0443}",
+	'udattadeva' => "\x{0951}",
+	'udblacute' => "\x{0171}",
+	'udblgrave' => "\x{0215}",
+	'udeva' => "\x{0909}",
+	'udieresisacute' => "\x{01D8}",
+	'udieresisbelow' => "\x{1E73}",
+	'udieresiscaron' => "\x{01DA}",
+	'udieresiscyrillic' => "\x{04F1}",
+	'udieresisgrave' => "\x{01DC}",
+	'udieresismacron' => "\x{01D6}",
+	'udotbelow' => "\x{1EE5}",
+	'ugujarati' => "\x{0A89}",
+	'ugurmukhi' => "\x{0A09}",
+	'uhiragana' => "\x{3046}",
+	'uhookabove' => "\x{1EE7}",
+	'uhornacute' => "\x{1EE9}",
+	'uhorndotbelow' => "\x{1EF1}",
+	'uhorngrave' => "\x{1EEB}",
+	'uhornhookabove' => "\x{1EED}",
+	'uhorntilde' => "\x{1EEF}",
+	'uhungarumlautcyrillic' => "\x{04F3}",
+	'uinvertedbreve' => "\x{0217}",
+	'ukatakana' => "\x{30A6}",
+	'ukatakanahalfwidth' => "\x{FF73}",
+	'ukcyrillic' => "\x{0479}",
+	'ukorean' => "\x{315C}",
+	'umacroncyrillic' => "\x{04EF}",
+	'umacrondieresis' => "\x{1E7B}",
+	'umatragurmukhi' => "\x{0A41}",
+	'umonospace' => "\x{FF55}",
+	'underscoremonospace' => "\x{FF3F}",
+	'underscorevertical' => "\x{FE33}",
+	'underscorewavy' => "\x{FE4F}",
+	'uparen' => "\x{24B0}",
+	'upperdothebrew' => "\x{05C4}",
+	'upsilonlatin' => "\x{028A}",
+	'uptackbelowcmb' => "\x{031D}",
+	'uptackmod' => "\x{02D4}",
+	'uragurmukhi' => "\x{0A73}",
+	'ushortcyrillic' => "\x{045E}",
+	'usmallhiragana' => "\x{3045}",
+	'usmallkatakana' => "\x{30A5}",
+	'usmallkatakanahalfwidth' => "\x{FF69}",
+	'ustraightcyrillic' => "\x{04AF}",
+	'ustraightstrokecyrillic' => "\x{04B1}",
+	'utildeacute' => "\x{1E79}",
+	'utildebelow' => "\x{1E75}",
+	'uubengali' => "\x{098A}",
+	'uudeva' => "\x{090A}",
+	'uugujarati' => "\x{0A8A}",
+	'uugurmukhi' => "\x{0A0A}",
+	'uumatragurmukhi' => "\x{0A42}",
+	'uuvowelsignbengali' => "\x{09C2}",
+	'uuvowelsigndeva' => "\x{0942}",
+	'uuvowelsigngujarati' => "\x{0AC2}",
+	'uvowelsignbengali' => "\x{09C1}",
+	'uvowelsigndeva' => "\x{0941}",
+	'uvowelsigngujarati' => "\x{0AC1}",
+	'vadeva' => "\x{0935}",
+	'vagujarati' => "\x{0AB5}",
+	'vagurmukhi' => "\x{0A35}",
+	'vakatakana' => "\x{30F7}",
+	'vav' => "\x{05D5}",
+	'vavdagesh' => "\x{FB35}",
+	'vavdagesh65' => "\x{FB35}",
+	'vavdageshhebrew' => "\x{FB35}",
+	'vavhebrew' => "\x{05D5}",
+	'vavholam' => "\x{FB4B}",
+	'vavholamhebrew' => "\x{FB4B}",
+	'vavvavhebrew' => "\x{05F0}",
+	'vavyodhebrew' => "\x{05F1}",
+	'vcircle' => "\x{24E5}",
+	'vdotbelow' => "\x{1E7F}",
+	'vecyrillic' => "\x{0432}",
+	'veharabic' => "\x{06A4}",
+	'vehfinalarabic' => "\x{FB6B}",
+	'vehinitialarabic' => "\x{FB6C}",
+	'vehmedialarabic' => "\x{FB6D}",
+	'vekatakana' => "\x{30F9}",
+	'venus' => "\x{2640}",
+	'verticalbar' => "\x{007C}",
+	'verticallineabovecmb' => "\x{030D}",
+	'verticallinebelowcmb' => "\x{0329}",
+	'verticallinelowmod' => "\x{02CC}",
+	'verticallinemod' => "\x{02C8}",
+	'vewarmenian' => "\x{057E}",
+	'vhook' => "\x{028B}",
+	'vikatakana' => "\x{30F8}",
+	'viramabengali' => "\x{09CD}",
+	'viramadeva' => "\x{094D}",
+	'viramagujarati' => "\x{0ACD}",
+	'visargabengali' => "\x{0983}",
+	'visargadeva' => "\x{0903}",
+	'visargagujarati' => "\x{0A83}",
+	'vmonospace' => "\x{FF56}",
+	'voarmenian' => "\x{0578}",
+	'voicediterationhiragana' => "\x{309E}",
+	'voicediterationkatakana' => "\x{30FE}",
+	'voicedmarkkana' => "\x{309B}",
+	'voicedmarkkanahalfwidth' => "\x{FF9E}",
+	'vokatakana' => "\x{30FA}",
+	'vparen' => "\x{24B1}",
+	'vtilde' => "\x{1E7D}",
+	'vturned' => "\x{028C}",
+	'vuhiragana' => "\x{3094}",
+	'vukatakana' => "\x{30F4}",
+	'waekorean' => "\x{3159}",
+	'wahiragana' => "\x{308F}",
+	'wakatakana' => "\x{30EF}",
+	'wakatakanahalfwidth' => "\x{FF9C}",
+	'wakorean' => "\x{3158}",
+	'wasmallhiragana' => "\x{308E}",
+	'wasmallkatakana' => "\x{30EE}",
+	'wattosquare' => "\x{3357}",
+	'wavedash' => "\x{301C}",
+	'wavyunderscorevertical' => "\x{FE34}",
+	'wawarabic' => "\x{0648}",
+	'wawfinalarabic' => "\x{FEEE}",
+	'wawhamzaabovearabic' => "\x{0624}",
+	'wawhamzaabovefinalarabic' => "\x{FE86}",
+	'wbsquare' => "\x{33DD}",
+	'wcircle' => "\x{24E6}",
+	'wdotaccent' => "\x{1E87}",
+	'wdotbelow' => "\x{1E89}",
+	'wehiragana' => "\x{3091}",
+	'wekatakana' => "\x{30F1}",
+	'wekorean' => "\x{315E}",
+	'weokorean' => "\x{315D}",
+	'whitebullet' => "\x{25E6}",
+	'whitecircle' => "\x{25CB}",
+	'whitecircleinverse' => "\x{25D9}",
+	'whitecornerbracketleft' => "\x{300E}",
+	'whitecornerbracketleftvertical' => "\x{FE43}",
+	'whitecornerbracketright' => "\x{300F}",
+	'whitecornerbracketrightvertical' => "\x{FE44}",
+	'whitediamond' => "\x{25C7}",
+	'whitediamondcontainingblacksmalldiamond' => "\x{25C8}",
+	'whitedownpointingsmalltriangle' => "\x{25BF}",
+	'whitedownpointingtriangle' => "\x{25BD}",
+	'whiteleftpointingsmalltriangle' => "\x{25C3}",
+	'whiteleftpointingtriangle' => "\x{25C1}",
+	'whitelenticularbracketleft' => "\x{3016}",
+	'whitelenticularbracketright' => "\x{3017}",
+	'whiterightpointingsmalltriangle' => "\x{25B9}",
+	'whiterightpointingtriangle' => "\x{25B7}",
+	'whitesmallsquare' => "\x{25AB}",
+	'whitesmilingface' => "\x{263A}",
+	'whitesquare' => "\x{25A1}",
+	'whitestar' => "\x{2606}",
+	'whitetelephone' => "\x{260F}",
+	'whitetortoiseshellbracketleft' => "\x{3018}",
+	'whitetortoiseshellbracketright' => "\x{3019}",
+	'whiteuppointingsmalltriangle' => "\x{25B5}",
+	'whiteuppointingtriangle' => "\x{25B3}",
+	'wihiragana' => "\x{3090}",
+	'wikatakana' => "\x{30F0}",
+	'wikorean' => "\x{315F}",
+	'wmonospace' => "\x{FF57}",
+	'wohiragana' => "\x{3092}",
+	'wokatakana' => "\x{30F2}",
+	'wokatakanahalfwidth' => "\x{FF66}",
+	'won' => "\x{20A9}",
+	'wonmonospace' => "\x{FFE6}",
+	'wowaenthai' => "\x{0E27}",
+	'wparen' => "\x{24B2}",
+	'wring' => "\x{1E98}",
+	'wsuperior' => "\x{02B7}",
+	'wturned' => "\x{028D}",
+	'wynn' => "\x{01BF}",
+	'xabovecmb' => "\x{033D}",
+	'xbopomofo' => "\x{3112}",
+	'xcircle' => "\x{24E7}",
+	'xdieresis' => "\x{1E8D}",
+	'xdotaccent' => "\x{1E8B}",
+	'xeharmenian' => "\x{056D}",
+	'xmonospace' => "\x{FF58}",
+	'xparen' => "\x{24B3}",
+	'xsuperior' => "\x{02E3}",
+	'yaadosquare' => "\x{334E}",
+	'yabengali' => "\x{09AF}",
+	'yadeva' => "\x{092F}",
+	'yaekorean' => "\x{3152}",
+	'yagujarati' => "\x{0AAF}",
+	'yagurmukhi' => "\x{0A2F}",
+	'yahiragana' => "\x{3084}",
+	'yakatakana' => "\x{30E4}",
+	'yakatakanahalfwidth' => "\x{FF94}",
+	'yakorean' => "\x{3151}",
+	'yamakkanthai' => "\x{0E4E}",
+	'yasmallhiragana' => "\x{3083}",
+	'yasmallkatakana' => "\x{30E3}",
+	'yasmallkatakanahalfwidth' => "\x{FF6C}",
+	'yatcyrillic' => "\x{0463}",
+	'ycircle' => "\x{24E8}",
+	'ydotaccent' => "\x{1E8F}",
+	'ydotbelow' => "\x{1EF5}",
+	'yeharabic' => "\x{064A}",
+	'yehbarreearabic' => "\x{06D2}",
+	'yehbarreefinalarabic' => "\x{FBAF}",
+	'yehfinalarabic' => "\x{FEF2}",
+	'yehhamzaabovearabic' => "\x{0626}",
+	'yehhamzaabovefinalarabic' => "\x{FE8A}",
+	'yehhamzaaboveinitialarabic' => "\x{FE8B}",
+	'yehhamzaabovemedialarabic' => "\x{FE8C}",
+	'yehinitialarabic' => "\x{FEF3}",
+	'yehmedialarabic' => "\x{FEF4}",
+	'yehmeeminitialarabic' => "\x{FCDD}",
+	'yehmeemisolatedarabic' => "\x{FC58}",
+	'yehnoonfinalarabic' => "\x{FC94}",
+	'yehthreedotsbelowarabic' => "\x{06D1}",
+	'yekorean' => "\x{3156}",
+	'yenmonospace' => "\x{FFE5}",
+	'yeokorean' => "\x{3155}",
+	'yeorinhieuhkorean' => "\x{3186}",
+	'yerahbenyomohebrew' => "\x{05AA}",
+	'yerahbenyomolefthebrew' => "\x{05AA}",
+	'yericyrillic' => "\x{044B}",
+	'yerudieresiscyrillic' => "\x{04F9}",
+	'yesieungkorean' => "\x{3181}",
+	'yesieungpansioskorean' => "\x{3183}",
+	'yesieungsioskorean' => "\x{3182}",
+	'yetivhebrew' => "\x{059A}",
+	'yhook' => "\x{01B4}",
+	'yhookabove' => "\x{1EF7}",
+	'yiarmenian' => "\x{0575}",
+	'yicyrillic' => "\x{0457}",
+	'yikorean' => "\x{3162}",
+	'yinyang' => "\x{262F}",
+	'yiwnarmenian' => "\x{0582}",
+	'ymonospace' => "\x{FF59}",
+	'yod' => "\x{05D9}",
+	'yoddagesh' => "\x{FB39}",
+	'yoddageshhebrew' => "\x{FB39}",
+	'yodhebrew' => "\x{05D9}",
+	'yodyodhebrew' => "\x{05F2}",
+	'yodyodpatahhebrew' => "\x{FB1F}",
+	'yohiragana' => "\x{3088}",
+	'yoikorean' => "\x{3189}",
+	'yokatakana' => "\x{30E8}",
+	'yokatakanahalfwidth' => "\x{FF96}",
+	'yokorean' => "\x{315B}",
+	'yosmallhiragana' => "\x{3087}",
+	'yosmallkatakana' => "\x{30E7}",
+	'yosmallkatakanahalfwidth' => "\x{FF6E}",
+	'yotgreek' => "\x{03F3}",
+	'yoyaekorean' => "\x{3188}",
+	'yoyakorean' => "\x{3187}",
+	'yoyakthai' => "\x{0E22}",
+	'yoyingthai' => "\x{0E0D}",
+	'yparen' => "\x{24B4}",
+	'ypogegrammeni' => "\x{037A}",
+	'ypogegrammenigreekcmb' => "\x{0345}",
+	'yr' => "\x{01A6}",
+	'yring' => "\x{1E99}",
+	'ysuperior' => "\x{02B8}",
+	'ytilde' => "\x{1EF9}",
+	'yturned' => "\x{028E}",
+	'yuhiragana' => "\x{3086}",
+	'yuikorean' => "\x{318C}",
+	'yukatakana' => "\x{30E6}",
+	'yukatakanahalfwidth' => "\x{FF95}",
+	'yukorean' => "\x{3160}",
+	'yusbigcyrillic' => "\x{046B}",
+	'yusbigiotifiedcyrillic' => "\x{046D}",
+	'yuslittlecyrillic' => "\x{0467}",
+	'yuslittleiotifiedcyrillic' => "\x{0469}",
+	'yusmallhiragana' => "\x{3085}",
+	'yusmallkatakana' => "\x{30E5}",
+	'yusmallkatakanahalfwidth' => "\x{FF6D}",
+	'yuyekorean' => "\x{318B}",
+	'yuyeokorean' => "\x{318A}",
+	'yyabengali' => "\x{09DF}",
+	'yyadeva' => "\x{095F}",
+	'zaarmenian' => "\x{0566}",
+	'zadeva' => "\x{095B}",
+	'zagurmukhi' => "\x{0A5B}",
+	'zaharabic' => "\x{0638}",
+	'zahfinalarabic' => "\x{FEC6}",
+	'zahinitialarabic' => "\x{FEC7}",
+	'zahiragana' => "\x{3056}",
+	'zahmedialarabic' => "\x{FEC8}",
+	'zainarabic' => "\x{0632}",
+	'zainfinalarabic' => "\x{FEB0}",
+	'zakatakana' => "\x{30B6}",
+	'zaqefgadolhebrew' => "\x{0595}",
+	'zaqefqatanhebrew' => "\x{0594}",
+	'zarqahebrew' => "\x{0598}",
+	'zayin' => "\x{05D6}",
+	'zayindagesh' => "\x{FB36}",
+	'zayindageshhebrew' => "\x{FB36}",
+	'zayinhebrew' => "\x{05D6}",
+	'zbopomofo' => "\x{3117}",
+	'zcircle' => "\x{24E9}",
+	'zcircumflex' => "\x{1E91}",
+	'zcurl' => "\x{0291}",
+	'zdot' => "\x{017C}",
+	'zdotbelow' => "\x{1E93}",
+	'zecyrillic' => "\x{0437}",
+	'zedescendercyrillic' => "\x{0499}",
+	'zedieresiscyrillic' => "\x{04DF}",
+	'zehiragana' => "\x{305C}",
+	'zekatakana' => "\x{30BC}",
+	'zeroarabic' => "\x{0660}",
+	'zerobengali' => "\x{09E6}",
+	'zerodeva' => "\x{0966}",
+	'zerogujarati' => "\x{0AE6}",
+	'zerogurmukhi' => "\x{0A66}",
+	'zerohackarabic' => "\x{0660}",
+	'zeroinferior' => "\x{2080}",
+	'zeromonospace' => "\x{FF10}",
+	'zerooldstyle' => "\x{F730}",
+	'zeropersian' => "\x{06F0}",
+	'zerosuperior' => "\x{2070}",
+	'zerothai' => "\x{0E50}",
+	'zerowidthjoiner' => "\x{FEFF}",
+	'zerowidthnonjoiner' => "\x{200C}",
+	'zerowidthspace' => "\x{200B}",
+	'zhbopomofo' => "\x{3113}",
+	'zhearmenian' => "\x{056A}",
+	'zhebrevecyrillic' => "\x{04C2}",
+	'zhecyrillic' => "\x{0436}",
+	'zhedescendercyrillic' => "\x{0497}",
+	'zhedieresiscyrillic' => "\x{04DD}",
+	'zihiragana' => "\x{3058}",
+	'zikatakana' => "\x{30B8}",
+	'zinorhebrew' => "\x{05AE}",
+	'zlinebelow' => "\x{1E95}",
+	'zmonospace' => "\x{FF5A}",
+	'zohiragana' => "\x{305E}",
+	'zokatakana' => "\x{30BE}",
+	'zparen' => "\x{24B5}",
+	'zretroflexhook' => "\x{0290}",
+	'zstroke' => "\x{01B6}",
+	'zuhiragana' => "\x{305A}",
+	'zukatakana' => "\x{30BA}",
+	);
+
+# Add to this list the glyphs for new fonts (from aglfn13):
+
+map { $agl{$names{$_}} = pack('U',hex ($_))} (keys %names);
+
+
+# %doubles = (map{$_ => "uni$_"} qw(0394 03A9 0162 2215 00AD 02C9 03BC 2219 00A0 0163));
+
+=head2 lookup ( $usv [, $noAlt [, $noUni] ])
+
+return the Adobe-recommended glyph name for a specific Unicode codepoint (integer). By default
+returns C<uniXXXX> names rather than C<afiiNNNNN> or C<SFnnnnnn> names
+
+If C<$noAlt> is true, C<afii> and C<SF> names are returned rather than C<uniXXXX>.
+
+if C<$noUni> is true, returns undef if it would have to resort to C<uniXXXX> or C<uXXXXXX> 
+style names. Essentially this represents a straight lookup in the Adobe-recommended list.
+
+=cut
+
+sub lookup
+{
+    my ($num, $noalt, $noUni) = @_;
+    my ($val) = sprintf("%04X", $num);
+
+    if (defined $names{$val})
+    {
+        return $names{$val} if ($noalt || $names{$val} !~ m/^(?:afii|SF)/o);
+    }
+    return undef if $noUni;
+    if ($num > 0xFFFF)
+    { return "u$val"; }
+    elsif ($num)
+    { return "uni$val"; }
+    else
+    { return ".notdef"; }
+}
+
+=head2 parse ( $glyphname )
+
+Parse an Adobe-conformant glyph name, generating a Unicode codepoint sequence equivalent to the glyph (or
+glyph components, should the name represent a ligature). In scalar context, returns a reference to an
+array of Unicodes (decimal). Array is empty if the glyph name is non-conformant.
+In list context, the first item returned is the same array reference as above. The second item
+is a reference to an array containing the extensions (if any) present on the glyph name. 
+The '.' that precedes each extension is not included.
+
+=cut
+
+sub parse
+{
+	my ($gname, @USVs, @extensions);
+	($gname, @extensions) = split('\.', $_[0]);
+	# if name originally started with . (e.g., .null) then $gname will now be '' ... need to fix that up:
+	$gname = '.' . shift(@extensions) if $gname eq '';
+	if (defined $gname)
+	{
+		foreach $gname (split('_', $gname))
+		{
+			if ($gname =~ /^u[0-9a-fA-F]{4,6}$/)
+			{
+				push @USVs, hex(substr($gname, 1));
+			}
+			elsif ($gname =~ /^uni([0-9a-fA-F]{4,4})+$/)
+			{
+				push @USVs, map {hex($_)} ($gname =~ /([0-9a-fA-F]{4,4})/g)
+			}
+			elsif (exists $agl{$gname})
+			{
+				push @USVs, unpack ('U*', $agl{$gname});
+			}
+		}
+	}
+	return \@USVs unless wantarray;
+	my @res = (\@USVs, \@extensions);
+	return @res;	
+}
+
+#Code used to parse Adobe's agl file and generate text for %agl initialization:
+#while (<ARGV>) {
+#	chomp;
+#	next if m/^#/;
+#	my ($gname, @nums) = split(/[; ]/);
+#	if ($#nums > 0 or !defined ($Font::TTF::PSNames::names{$nums[0]}) or $Font::TTF::PSNames::names{$nums[0]} ne $gname)
+#	{
+#		print "\t'$gname' => \"";
+#		map {print "\\x{$_}" } @nums;
+#		print  "\",\n";
+#	}
+# }
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;

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

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prep.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prep.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prep.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,89 +1,89 @@
-package Font::TTF::Prep;
-
-=head1 NAME
-
-Font::TTF::Prep - Preparation hinting program. Called when ppem changes
-
-=head1 DESCRIPTION
-
-This is a minimal class adding nothing beyond a table, but is a repository
-for prep type information for those processes brave enough to address hinting.
-
-=cut
-
-use strict;
-use vars qw(@ISA $VERSION);
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
-
-$VERSION = 0.0001;
-
-
-=head2 $t->read
-
-Reads the data using C<read_dat>.
-
-=cut
-
-sub read
-{
-    $_[0]->read_dat;
-    $_[0]->{' read'} = 1;
-}
-
-
-=head2 $t->out_xml($context, $depth)
-
-Outputs Prep program as XML
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($dat);
-
-    $self->read;
-    $dat = Font::TTF::Utils::XML_binhint($self->{' dat'});
-    $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg;
-    $fh->print("$depth<code>\n");
-    $fh->print("$depth$context->{'indent'}$dat");
-    $fh->print("$depth</code>\n");
-    $self;
-}
-    
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Parse all that hinting code
-
-=cut
-
-sub XML_end
-{
-    my ($self) = shift;
-    my ($context, $tag, %attrs) = @_;
-
-    if ($tag eq 'code')
-    {
-        $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'});
-        return $context;
-    } else
-    { return $self->SUPER::XML_end(@_); }
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Prep;
+
+=head1 NAME
+
+Font::TTF::Prep - Preparation hinting program. Called when ppem changes
+
+=head1 DESCRIPTION
+
+This is a minimal class adding nothing beyond a table, but is a repository
+for prep type information for those processes brave enough to address hinting.
+
+=cut
+
+use strict;
+use vars qw(@ISA $VERSION);
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+
+$VERSION = 0.0001;
+
+
+=head2 $t->read
+
+Reads the data using C<read_dat>.
+
+=cut
+
+sub read
+{
+    $_[0]->read_dat;
+    $_[0]->{' read'} = 1;
+}
+
+
+=head2 $t->out_xml($context, $depth)
+
+Outputs Prep program as XML
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($dat);
+
+    $self->read;
+    $dat = Font::TTF::Utils::XML_binhint($self->{' dat'});
+    $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg;
+    $fh->print("$depth<code>\n");
+    $fh->print("$depth$context->{'indent'}$dat");
+    $fh->print("$depth</code>\n");
+    $self;
+}
+    
+
+=head2 $t->XML_end($context, $tag, %attrs)
+
+Parse all that hinting code
+
+=cut
+
+sub XML_end
+{
+    my ($self) = shift;
+    my ($context, $tag, %attrs) = @_;
+
+    if ($tag eq 'code')
+    {
+        $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'});
+        return $context;
+    } else
+    { return $self->SUPER::XML_end(@_); }
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prop.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prop.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Prop.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,154 +1,154 @@
-package Font::TTF::Prop;
-
-=head1 NAME
-
-Font::TTF::Prop - Glyph Properties table in a font
-
-=head1 DESCRIPTION
-
-=head1 INSTANCE VARIABLES
-
-=item version
-
-=item default
-
-=item lookup
-
-Hash of property values keyed by glyph number
-
-=item lookupFormat
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-use Font::TTF::Utils;
-use Font::TTF::AATutils;
-use Font::TTF::Segarr;
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $fh);
-    my ($version, $lookupPresent, $default);
-    
-    $self->SUPER::read or return $self;
-
-    $fh = $self->{' INFILE'};
-    $fh->read($dat, 8);
-    ($version, $lookupPresent, $default) = TTF_Unpack("fSS", $dat);
-
-    if ($lookupPresent) {
-        my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{' LENGTH'} - 8, $default);
-        $self->{'lookup'} = $lookup;
-        $self->{'format'} = $format;
-    }
-
-    $self->{'version'} = $version;
-    $self->{'default'} = $default;
-
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($default, $lookup);
-    
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $default = $self->{'default'};
-    $lookup = $self->{'lookup'};
-    $fh->print(TTF_Pack("fSS", $self->{'version'}, (defined $lookup ? 1 : 0), $default));
-
-    AAT_write_lookup($fh, $self->{'format'}, $lookup, 2, $default) if (defined $lookup);
-}
-
-=head2 $t->print($fh)
-
-Prints a human-readable representation of the table
-
-=cut
-
-sub print
-{
-    my ($self, $fh) = @_;
-    my ($lookup);
-    
-    $self->read;
-    
-    $fh = 'STDOUT' unless defined $fh;
-
-    $fh->printf("version %f\ndefault %04x # %s\n", $self->{'version'}, $self->{'default'}, meaning_($self->{'default'}));
-    $lookup = $self->{'lookup'};
-    if (defined $lookup) {
-        $fh->printf("format %d\n", $self->{'format'});
-        foreach (sort { $a <=> $b } keys %$lookup) {
-            $fh->printf("\t%d -> %04x # %s\n", $_, $lookup->{$_}, meaning_($lookup->{$_}));
-        }
-    }
-}
-
-sub meaning_
-{
-    my ($val) = @_;
-    my ($res);
-    
-    my @types = (
-        "Strong left-to-right",
-        "Strong right-to-left",
-        "Arabic letter",
-        "European number",
-        "European number separator",
-        "European number terminator",
-        "Arabic number",
-        "Common number separator",
-        "Block separator",
-        "Segment separator",
-        "Whitespace",
-        "Other neutral");
-    $res = $types[$val & 0x001f] or ("Undefined [" . ($val & 0x001f) . "]");
-    
-    $res .= ", floater" if $val & 0x8000;
-    $res .= ", hang left" if $val & 0x4000;
-    $res .= ", hang right" if $val & 0x2000;
-    $res .= ", attaches on right" if $val & 0x0080;
-    $res .= ", pair" if $val & 0x1000;
-    my $pairOffset = ($val & 0x0f00) >> 8;
-    $pairOffset = $pairOffset - 16 if $pairOffset > 7;
-    $res .= $pairOffset > 0 ? " +" . $pairOffset : $pairOffset < 0 ? " " . $pairOffset : "";
-    
-    $res;
-}
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Prop;
+
+=head1 NAME
+
+Font::TTF::Prop - Glyph Properties table in a font
+
+=head1 DESCRIPTION
+
+=head1 INSTANCE VARIABLES
+
+=item version
+
+=item default
+
+=item lookup
+
+Hash of property values keyed by glyph number
+
+=item lookupFormat
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+use Font::TTF::Utils;
+use Font::TTF::AATutils;
+use Font::TTF::Segarr;
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $fh);
+    my ($version, $lookupPresent, $default);
+    
+    $self->SUPER::read or return $self;
+
+    $fh = $self->{' INFILE'};
+    $fh->read($dat, 8);
+    ($version, $lookupPresent, $default) = TTF_Unpack("fSS", $dat);
+
+    if ($lookupPresent) {
+        my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{' LENGTH'} - 8, $default);
+        $self->{'lookup'} = $lookup;
+        $self->{'format'} = $format;
+    }
+
+    $self->{'version'} = $version;
+    $self->{'default'} = $default;
+
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($default, $lookup);
+    
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $default = $self->{'default'};
+    $lookup = $self->{'lookup'};
+    $fh->print(TTF_Pack("fSS", $self->{'version'}, (defined $lookup ? 1 : 0), $default));
+
+    AAT_write_lookup($fh, $self->{'format'}, $lookup, 2, $default) if (defined $lookup);
+}
+
+=head2 $t->print($fh)
+
+Prints a human-readable representation of the table
+
+=cut
+
+sub print
+{
+    my ($self, $fh) = @_;
+    my ($lookup);
+    
+    $self->read;
+    
+    $fh = 'STDOUT' unless defined $fh;
+
+    $fh->printf("version %f\ndefault %04x # %s\n", $self->{'version'}, $self->{'default'}, meaning_($self->{'default'}));
+    $lookup = $self->{'lookup'};
+    if (defined $lookup) {
+        $fh->printf("format %d\n", $self->{'format'});
+        foreach (sort { $a <=> $b } keys %$lookup) {
+            $fh->printf("\t%d -> %04x # %s\n", $_, $lookup->{$_}, meaning_($lookup->{$_}));
+        }
+    }
+}
+
+sub meaning_
+{
+    my ($val) = @_;
+    my ($res);
+    
+    my @types = (
+        "Strong left-to-right",
+        "Strong right-to-left",
+        "Arabic letter",
+        "European number",
+        "European number separator",
+        "European number terminator",
+        "Arabic number",
+        "Common number separator",
+        "Block separator",
+        "Segment separator",
+        "Whitespace",
+        "Other neutral");
+    $res = $types[$val & 0x001f] or ("Undefined [" . ($val & 0x001f) . "]");
+    
+    $res .= ", floater" if $val & 0x8000;
+    $res .= ", hang left" if $val & 0x4000;
+    $res .= ", hang right" if $val & 0x2000;
+    $res .= ", attaches on right" if $val & 0x0080;
+    $res .= ", pair" if $val & 0x1000;
+    my $pairOffset = ($val & 0x0f00) >> 8;
+    $pairOffset = $pairOffset - 16 if $pairOffset > 7;
+    $res .= $pairOffset > 0 ? " +" . $pairOffset : $pairOffset < 0 ? " " . $pairOffset : "";
+    
+    $res;
+}
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Jonathan Kew L<Jonathan_Kew at sil.org>. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Segarr.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Segarr.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Segarr.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,376 +1,376 @@
-package Font::TTF::Segarr;
-
-=head1 NAME
-
-Font::TTF::Segarr - Segmented array
-
-=head1 DESCRIPTION
-
-Holds data either directly or indirectly as a series of arrays. This class
-looks after the set of arrays and masks the individual sub-arrays, thus saving
-a class, we hope.
-
-=head1 INSTANCE VARIABLES
-
-All instance variables do not start with a space.
-
-The segmented array is simply an array of segments
-
-Each segment is a more complex affair:
-
-=over 4
-
-=item START
-
-In terms of the array, the address for the 0th element in this segment.
-
-=item LEN
-
-Number of elements in this segment
-
-=item VAL
-
-The array which contains the elements
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@types $VERSION);
-$VERSION = 0.0001;
-
- at types = ('', 'C', 'n', '', 'N');
-
-=head2 Font::TTF::Segarr->new($size)
-
-Creates a new segmented array with a given data size
-
-=cut
-
-sub new
-{
-    my ($class) = @_;
-    my ($self) = [];
-
-    bless $self, (ref($class) || $class);
-}
-
-
-=head2 $s->fastadd_segment($start, $is_sparse, @dat)
-
-Creates a new segment and adds it to the array assuming no overlap between
-the new segment and any others in the array. $is_sparse indicates whether the
-passed in array contains C<undef>s or not. If false no checking is done (which
-is faster, but riskier). If equal to 2 then 0 is considered undef as well.
-
-Returns the number of segments inserted.
-
-=cut
-
-sub fastadd_segment
-{
-    my ($self) = shift;
-    my ($start) = shift;
-    my ($sparse) = shift;
-    my ($p, $i, $seg, @seg);
-
-
-    if ($sparse)
-    {
-        for ($i = 0; $i <= $#_; $i++)
-        {
-            if (!defined $seg && (($sparse != 2 && defined $_[$i]) || $_[$i] != 0))
-            { $seg->{'START'} = $start + $i; $seg->{'VAL'} = []; }
-            
-            if (defined $seg && (($sparse == 2 && $_[$i] == 0) || !defined $_[$i]))
-            {
-                $seg->{'LEN'} = $start + $i - $seg->{'START'};
-                push(@seg, $seg);
-                $seg = undef;
-            } elsif (defined $seg)
-            { push (@{$seg->{'VAL'}}, $_[$i]); }
-        }
-        if (defined $seg)
-        {
-            push(@seg, $seg);
-            $seg->{'LEN'} = $start + $i - $seg->{'START'};
-        }
-    } else
-    {
-        $seg->{'START'} = $start;
-        $seg->{'LEN'} = $#_ + 1;
-        $seg->{'VAL'} = [@_];
-        @seg = ($seg);
-    }
-
-    for ($i = 0; $i <= $#$self; $i++)
-    {
-        if ($self->[$i]{'START'} > $start)
-        {
-            splice(@$self, $i, 0, @seg);
-            return wantarray ? @seg : scalar(@seg);
-        }
-    }
-    push(@$self, @seg);
-    return wantarray ? @seg : scalar(@seg);
-}
-
-
-=head2 $s->add_segment($start, $overwrite, @dat)
-
-Creates a new segment and adds it to the array allowing for possible overlaps
-between the new segment and the existing ones. In the case of overlaps, elements
-from the new segment are deleted unless $overwrite is set in which case the
-elements already there are over-written.
-
-This method also checks the data coming in to see if it is sparse (i.e. contains
-undef values). Gaps cause new segments to be created or not to over-write existing
-values.
-
-=cut
-
-sub add_segment
-{
-    my ($self) = shift;
-    my ($start) = shift;
-    my ($over) = shift;
-    my ($seg, $i, $s, $offset, $j, $newi);
-
-    return $self->fastadd_segment($start, $over, @_) if ($#$self < 0);
-    $offset = 0;
-    for ($i = 0; $i <= $#$self && $offset <= $#_; $i++)
-    {
-        $s = $self->[$i];
-        if ($s->{'START'} <= $start + $offset)              # only < for $offset == 0
-        {
-            if ($s->{'START'} + $s->{'LEN'} > $start + $#_)
-            {
-                for ($j = $offset; $j <= $#_; $j++)
-                {
-                    if ($over)
-                    { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; }
-                    else
-                    { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; }
-                }
-                $offset = $#_ + 1;
-                last;
-            } elsif ($s->{'START'} + $s->{'LEN'} > $start + $offset)        # is $offset needed here?
-            {
-                for ($j = $offset; $j < $s->{'START'} + $s->{'LEN'} - $start; $j++)
-                {
-                    if ($over)
-                    { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; }
-                    else
-                    { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; }
-                }
-                $offset = $s->{'START'} + $s->{'LEN'} - $start;
-            }
-        } else                                              # new seg please
-        {
-            if ($s->{'START'} > $start + $#_ + 1)
-            {
-                $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $#_]) - 1;
-                $offset = $#_ + 1;
-            }
-            else
-            {
-                $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $s->{'START'} - $start]) - 1;
-                $offset = $s->{'START'} - $start + 1;
-            }
-        }
-    }
-    if ($offset <= $#_)
-    {
-        $seg->{'START'} = $start + $offset;
-        $seg->{'LEN'} = $#_ - $offset + 1;
-        $seg->{'VAL'} = [@_[$offset .. $#_]];
-        push (@$self, $seg);
-    }
-    $self->tidy;
-}
-
-
-=head2 $s->tidy
-
-Merges any immediately adjacent segments
-
-=cut
-
-sub tidy
-{
-    my ($self) = @_;
-    my ($i, $sl, $s);
-
-    for ($i = 1; $i <= $#$self; $i++)
-    {
-        $sl = $self->[$i - 1];
-        $s = $self->[$i];
-        if ($s->{'START'} == $sl->{'START'} + $sl->{'LEN'})
-        {
-            $sl->{'LEN'} += $s->{'LEN'};
-            push (@{$sl->{'VAL'}}, @{$s->{'VAL'}});
-            splice(@$self, $i, 1);
-            $i--;
-        }
-    }
-    $self;
-}
-
-
-=head2 $s->at($addr, [$len])
-
-Looks up the data held at the given address by locating the appropriate segment
-etc. If $len > 1 then returns an array of values, spaces being filled with undef.
-
-=cut
-
-sub at
-{
-    my ($self, $addr, $len) = @_;
-    my ($i, $dat, $s, @res, $offset);
-
-    $len = 1 unless defined $len;
-    $offset = 0;
-    for ($i = 0; $i <= $#$self; $i++)
-    {
-        $s = $self->[$i];
-        next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset);        # only fires on $offset == 0
-        if ($s->{'START'} > $addr + $offset)
-        {
-            push (@res, (undef) x ($s->{'START'} > $addr + $len ?
-                    $len - $offset : $s->{'START'} - $addr - $offset));
-            $offset = $s->{'START'} - $addr;
-        }
-        last if ($s->{'START'} >= $addr + $len);
-        
-        if ($s->{'START'} + $s->{'LEN'} >= $addr + $len)
-        {
-            push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} ..
-                    $addr + $len - $s->{'START'} - 1]);
-            $offset = $len;
-            last;
-        } else
-        {
-            push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. $s->{'LEN'} - 1]);
-            $offset = $s->{'START'} + $s->{'LEN'} - $addr;
-        }
-    }
-    push (@res, (undef) x ($len - $offset)) if ($offset < $len);
-    return wantarray ? @res : $res[0];
-}
-
-
-=head2 $s->remove($addr, [$len])
-
-Removes the item or items from addr returning them as an array or the first
-value in a scalar context. This is very like C<at>, including padding with
-undef, but it deletes stuff as it goes.
-
-=cut
-
-sub remove
-{
-    my ($self, $addr, $len) = @_;
-    my ($i, $dat, $s, @res, $offset);
-
-    $len = 1 unless defined $len;
-    $offset = 0;
-    for ($i = 0; $i <= $#$self; $i++)
-    {
-        $s = $self->[$i];
-        next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset);
-        if ($s->{'START'} > $addr + $offset)
-        {
-            push (@res, (undef) x ($s->{'START'} > $addr + $len ?
-                    $len - $offset : $s->{'START'} - $addr - $offset));
-            $offset = $s->{'START'} - $addr;
-        }
-        last if ($s->{'START'} >= $addr + $len);
-        
-        unless ($s->{'START'} == $addr + $offset)
-        {
-            my ($seg) = {};
-
-            $seg->{'START'} = $s->{'START'};
-            $seg->{'LEN'} = $addr + $offset - $s->{'START'};
-            $seg->{'VAL'} = [splice(@{$s->{'VAL'}}, 0, $addr + $offset - $s->{'START'})];
-            $s->{'LEN'} -= $addr + $offset - $s->{'START'};
-            $s->{'START'} = $addr + $offset;
-
-            splice(@$self, $i, 0, $seg);
-            $i++;
-        }
-
-        if ($s->{'START'} + $s->{'LEN'} >= $addr + $len)
-        {
-            push (@res, splice(@{$s->{'VAL'}}, 0, $len - $offset));
-            $s->{'LEN'} -= $len - $offset;
-            $s->{'START'} += $len - $offset;
-            $offset = $len;
-            last;
-        } else
-        {
-            push (@res, @{$s->{'VAL'}});
-            $offset = $s->{'START'} + $s->{'LEN'} - $addr;
-            splice(@$self, $i, 0);
-            $i--;
-        }
-    }
-    push (@res, (undef) x ($len - $offset)) if ($offset < $len);
-    return wantarray ? @res : $res[0];
-}
-    
-
-=head2 $s->copy
-
-Deep copies this array
-
-=cut
-
-sub copy
-{
-    my ($self) = @_;
-    my ($res, $p);
-
-    $res = [];
-    foreach $p (@$self)
-    { push (@$res, $self->copy_seg($p)); }
-    $res;
-}
-    
-
-=head2 $s->copy_seg($seg)
-
-Creates a deep copy of a segment
-
-=cut
-
-sub copy_seg
-{
-    my ($self, $seg) = @_;
-    my ($p, $res);
-
-    $res = {};
-    $res->{'VAL'} = [@{$seg->{'VAL'}}];
-    foreach $p (keys %$seg)
-    { $res->{$p} = $seg->{$p} unless defined $res->{$p}; }
-    $res;
-}
-
-
-1;
-
-=head1 BUGS
-
-No known bugs.
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Segarr;
+
+=head1 NAME
+
+Font::TTF::Segarr - Segmented array
+
+=head1 DESCRIPTION
+
+Holds data either directly or indirectly as a series of arrays. This class
+looks after the set of arrays and masks the individual sub-arrays, thus saving
+a class, we hope.
+
+=head1 INSTANCE VARIABLES
+
+All instance variables do not start with a space.
+
+The segmented array is simply an array of segments
+
+Each segment is a more complex affair:
+
+=over 4
+
+=item START
+
+In terms of the array, the address for the 0th element in this segment.
+
+=item LEN
+
+Number of elements in this segment
+
+=item VAL
+
+The array which contains the elements
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@types $VERSION);
+$VERSION = 0.0001;
+
+ at types = ('', 'C', 'n', '', 'N');
+
+=head2 Font::TTF::Segarr->new($size)
+
+Creates a new segmented array with a given data size
+
+=cut
+
+sub new
+{
+    my ($class) = @_;
+    my ($self) = [];
+
+    bless $self, (ref($class) || $class);
+}
+
+
+=head2 $s->fastadd_segment($start, $is_sparse, @dat)
+
+Creates a new segment and adds it to the array assuming no overlap between
+the new segment and any others in the array. $is_sparse indicates whether the
+passed in array contains C<undef>s or not. If false no checking is done (which
+is faster, but riskier). If equal to 2 then 0 is considered undef as well.
+
+Returns the number of segments inserted.
+
+=cut
+
+sub fastadd_segment
+{
+    my ($self) = shift;
+    my ($start) = shift;
+    my ($sparse) = shift;
+    my ($p, $i, $seg, @seg);
+
+
+    if ($sparse)
+    {
+        for ($i = 0; $i <= $#_; $i++)
+        {
+            if (!defined $seg && (($sparse != 2 && defined $_[$i]) || $_[$i] != 0))
+            { $seg->{'START'} = $start + $i; $seg->{'VAL'} = []; }
+            
+            if (defined $seg && (($sparse == 2 && $_[$i] == 0) || !defined $_[$i]))
+            {
+                $seg->{'LEN'} = $start + $i - $seg->{'START'};
+                push(@seg, $seg);
+                $seg = undef;
+            } elsif (defined $seg)
+            { push (@{$seg->{'VAL'}}, $_[$i]); }
+        }
+        if (defined $seg)
+        {
+            push(@seg, $seg);
+            $seg->{'LEN'} = $start + $i - $seg->{'START'};
+        }
+    } else
+    {
+        $seg->{'START'} = $start;
+        $seg->{'LEN'} = $#_ + 1;
+        $seg->{'VAL'} = [@_];
+        @seg = ($seg);
+    }
+
+    for ($i = 0; $i <= $#$self; $i++)
+    {
+        if ($self->[$i]{'START'} > $start)
+        {
+            splice(@$self, $i, 0, @seg);
+            return wantarray ? @seg : scalar(@seg);
+        }
+    }
+    push(@$self, @seg);
+    return wantarray ? @seg : scalar(@seg);
+}
+
+
+=head2 $s->add_segment($start, $overwrite, @dat)
+
+Creates a new segment and adds it to the array allowing for possible overlaps
+between the new segment and the existing ones. In the case of overlaps, elements
+from the new segment are deleted unless $overwrite is set in which case the
+elements already there are over-written.
+
+This method also checks the data coming in to see if it is sparse (i.e. contains
+undef values). Gaps cause new segments to be created or not to over-write existing
+values.
+
+=cut
+
+sub add_segment
+{
+    my ($self) = shift;
+    my ($start) = shift;
+    my ($over) = shift;
+    my ($seg, $i, $s, $offset, $j, $newi);
+
+    return $self->fastadd_segment($start, $over, @_) if ($#$self < 0);
+    $offset = 0;
+    for ($i = 0; $i <= $#$self && $offset <= $#_; $i++)
+    {
+        $s = $self->[$i];
+        if ($s->{'START'} <= $start + $offset)              # only < for $offset == 0
+        {
+            if ($s->{'START'} + $s->{'LEN'} > $start + $#_)
+            {
+                for ($j = $offset; $j <= $#_; $j++)
+                {
+                    if ($over)
+                    { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; }
+                    else
+                    { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; }
+                }
+                $offset = $#_ + 1;
+                last;
+            } elsif ($s->{'START'} + $s->{'LEN'} > $start + $offset)        # is $offset needed here?
+            {
+                for ($j = $offset; $j < $s->{'START'} + $s->{'LEN'} - $start; $j++)
+                {
+                    if ($over)
+                    { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; }
+                    else
+                    { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; }
+                }
+                $offset = $s->{'START'} + $s->{'LEN'} - $start;
+            }
+        } else                                              # new seg please
+        {
+            if ($s->{'START'} > $start + $#_ + 1)
+            {
+                $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $#_]) - 1;
+                $offset = $#_ + 1;
+            }
+            else
+            {
+                $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $s->{'START'} - $start]) - 1;
+                $offset = $s->{'START'} - $start + 1;
+            }
+        }
+    }
+    if ($offset <= $#_)
+    {
+        $seg->{'START'} = $start + $offset;
+        $seg->{'LEN'} = $#_ - $offset + 1;
+        $seg->{'VAL'} = [@_[$offset .. $#_]];
+        push (@$self, $seg);
+    }
+    $self->tidy;
+}
+
+
+=head2 $s->tidy
+
+Merges any immediately adjacent segments
+
+=cut
+
+sub tidy
+{
+    my ($self) = @_;
+    my ($i, $sl, $s);
+
+    for ($i = 1; $i <= $#$self; $i++)
+    {
+        $sl = $self->[$i - 1];
+        $s = $self->[$i];
+        if ($s->{'START'} == $sl->{'START'} + $sl->{'LEN'})
+        {
+            $sl->{'LEN'} += $s->{'LEN'};
+            push (@{$sl->{'VAL'}}, @{$s->{'VAL'}});
+            splice(@$self, $i, 1);
+            $i--;
+        }
+    }
+    $self;
+}
+
+
+=head2 $s->at($addr, [$len])
+
+Looks up the data held at the given address by locating the appropriate segment
+etc. If $len > 1 then returns an array of values, spaces being filled with undef.
+
+=cut
+
+sub at
+{
+    my ($self, $addr, $len) = @_;
+    my ($i, $dat, $s, @res, $offset);
+
+    $len = 1 unless defined $len;
+    $offset = 0;
+    for ($i = 0; $i <= $#$self; $i++)
+    {
+        $s = $self->[$i];
+        next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset);        # only fires on $offset == 0
+        if ($s->{'START'} > $addr + $offset)
+        {
+            push (@res, (undef) x ($s->{'START'} > $addr + $len ?
+                    $len - $offset : $s->{'START'} - $addr - $offset));
+            $offset = $s->{'START'} - $addr;
+        }
+        last if ($s->{'START'} >= $addr + $len);
+        
+        if ($s->{'START'} + $s->{'LEN'} >= $addr + $len)
+        {
+            push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} ..
+                    $addr + $len - $s->{'START'} - 1]);
+            $offset = $len;
+            last;
+        } else
+        {
+            push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. $s->{'LEN'} - 1]);
+            $offset = $s->{'START'} + $s->{'LEN'} - $addr;
+        }
+    }
+    push (@res, (undef) x ($len - $offset)) if ($offset < $len);
+    return wantarray ? @res : $res[0];
+}
+
+
+=head2 $s->remove($addr, [$len])
+
+Removes the item or items from addr returning them as an array or the first
+value in a scalar context. This is very like C<at>, including padding with
+undef, but it deletes stuff as it goes.
+
+=cut
+
+sub remove
+{
+    my ($self, $addr, $len) = @_;
+    my ($i, $dat, $s, @res, $offset);
+
+    $len = 1 unless defined $len;
+    $offset = 0;
+    for ($i = 0; $i <= $#$self; $i++)
+    {
+        $s = $self->[$i];
+        next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset);
+        if ($s->{'START'} > $addr + $offset)
+        {
+            push (@res, (undef) x ($s->{'START'} > $addr + $len ?
+                    $len - $offset : $s->{'START'} - $addr - $offset));
+            $offset = $s->{'START'} - $addr;
+        }
+        last if ($s->{'START'} >= $addr + $len);
+        
+        unless ($s->{'START'} == $addr + $offset)
+        {
+            my ($seg) = {};
+
+            $seg->{'START'} = $s->{'START'};
+            $seg->{'LEN'} = $addr + $offset - $s->{'START'};
+            $seg->{'VAL'} = [splice(@{$s->{'VAL'}}, 0, $addr + $offset - $s->{'START'})];
+            $s->{'LEN'} -= $addr + $offset - $s->{'START'};
+            $s->{'START'} = $addr + $offset;
+
+            splice(@$self, $i, 0, $seg);
+            $i++;
+        }
+
+        if ($s->{'START'} + $s->{'LEN'} >= $addr + $len)
+        {
+            push (@res, splice(@{$s->{'VAL'}}, 0, $len - $offset));
+            $s->{'LEN'} -= $len - $offset;
+            $s->{'START'} += $len - $offset;
+            $offset = $len;
+            last;
+        } else
+        {
+            push (@res, @{$s->{'VAL'}});
+            $offset = $s->{'START'} + $s->{'LEN'} - $addr;
+            splice(@$self, $i, 0);
+            $i--;
+        }
+    }
+    push (@res, (undef) x ($len - $offset)) if ($offset < $len);
+    return wantarray ? @res : $res[0];
+}
+    
+
+=head2 $s->copy
+
+Deep copies this array
+
+=cut
+
+sub copy
+{
+    my ($self) = @_;
+    my ($res, $p);
+
+    $res = [];
+    foreach $p (@$self)
+    { push (@$res, $self->copy_seg($p)); }
+    $res;
+}
+    
+
+=head2 $s->copy_seg($seg)
+
+Creates a deep copy of a segment
+
+=cut
+
+sub copy_seg
+{
+    my ($self, $seg) = @_;
+    my ($p, $res);
+
+    $res = {};
+    $res->{'VAL'} = [@{$seg->{'VAL'}}];
+    foreach $p (keys %$seg)
+    { $res->{$p} = $seg->{$p} unless defined $res->{$p}; }
+    $res;
+}
+
+
+1;
+
+=head1 BUGS
+
+No known bugs.
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Table.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Table.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Table.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,382 +1,382 @@
-package Font::TTF::Table;
-
-=head1 NAME
-
-Font::TTF::Table - Superclass for tables and used for tables we don't have a class for
-
-=head1 DESCRIPTION
-
-Looks after the purely table aspects of a TTF table, such as whether the table
-has been read before, locating the file pointer, etc. Also copies tables from
-input to output.
-
-=head1 INSTANCE VARIABLES
-
-Instance variables start with a space
-
-=over 4
-
-=item read
-
-Flag which indicates that the table has already been read from file.
-
-=item dat
-
-Allows the creation of unspecific tables. Data is simply output to any font
-file being created.
-
-=item INFILE
-
-The read file handle
-
-=item OFFSET
-
-Location of the file in the input file
-
-=item LENGTH
-
-Length in the input directory
-
-=item CSUM
-
-Checksum read from the input file's directory
-
-=item PARENT
-
-The L<Font::TTF::Font> that table is part of
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw($VERSION);
-use Font::TTF::Utils;
-
-$VERSION = 0.0001;
-
-=head2 Font::TTF::Table->new(%parms)
-
-Creates a new table or subclass. Table instance variables are passed in
-at this point as an associative array.
-
-=cut
-
-sub new
-{
-    my ($class, %parms) = @_;
-    my ($self) = {};
-    my ($p);
-
-    $class = ref($class) || $class;
-    foreach $p (keys %parms)
-    { $self->{" $p"} = $parms{$p}; }
-    bless $self, $class;
-}
-
-
-=head2 $t->read
-
-Reads the table from the input file. Acts as a superclass to all true tables.
-This method marks the table as read and then just sets the input file pointer
-but does not read any data. If the table has already been read, then returns
-C<undef> else returns C<$self>
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-
-    return $self->read_dat if (ref($self) eq qq/__PACKAGE__/);
-    return undef if $self->{' read'};
-    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
-    $self->{' read'} = 1;
-    $self;
-}
-
-
-=head2 $t->read_dat
-
-Reads the table into the C<dat> instance variable for those tables which don't
-know any better
-
-=cut
-
-sub read_dat
-{
-    my ($self) = @_;
-
-# can't just $self->read here otherwise those tables which start their read sub with
-# $self->read_dat are going to permanently loop
-    return undef if ($self->{' read'});
-#    $self->{' read'} = 1;      # Let read do this, now out will call us for subclasses
-    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
-    $self->{' INFILE'}->read($self->{' dat'}, $self->{' LENGTH'});
-    $self;
-}
-
-=head2 $t->out($fh)
-
-Writes out the table to the font file. If there is anything in the
-C<data> instance variable then this is output, otherwise the data is copied
-from the input file to the output
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($dat, $i, $len, $count);
-
-    if (defined $self->{' dat'})
-    {
-        $fh->print($self->{' dat'});
-        return $self;
-    }
-
-    return undef unless defined $self->{' INFILE'};
-    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
-    $len = $self->{' LENGTH'};
-    while ($len > 0)
-    {
-        $count = ($len > 4096) ? 4096 : $len;
-        $self->{' INFILE'}->read($dat, $count);
-        $fh->print($dat);
-        $len -= $count;
-    }
-    $self;
-}
-
-
-=head2 $t->out_xml($context)
-
-Outputs this table in XML format. The table is first read (if not already read) and then if
-there is no subclass, then the data is dumped as hex data
-
-=cut
-
-sub out_xml
-{
-    my ($self, $context, $depth) = @_;
-    my ($k);
-
-    if (ref($self) eq __PACKAGE__)
-    {
-        $self->read_dat;
-        Font::TTF::Utils::XML_hexdump($context, $depth, $self->{' dat'});
-    }
-    else
-    {
-        $self->read;
-        foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self})
-        {
-            $self->XML_element($context, $depth, $k, $self->{$k});
-        }
-    }
-    $self;
-}
-
-
-=head2 $t->XML_element
-
-Output a particular element based on its contents.
-
-=cut
-
-sub XML_element
-{
-    my ($self, $context, $depth, $k, $dat) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($ndepth, $d);
-
-    return unless defined $dat;
-    
-    if (!ref($dat))
-    {
-        $fh->printf("%s<%s>%s</%s>\n", $depth, $k, $dat, $k);
-        return $self;
-    }
-
-    $fh->printf("%s<%s>\n", $depth, $k);
-    $ndepth = $depth . $context->{'indent'};
-
-    if (ref($dat) eq 'SCALAR')
-    { $self->XML_element($context, $ndepth, 'scalar', $$dat); }
-    elsif (ref($dat) eq 'ARRAY')
-    {
-        foreach $d (@{$dat})
-        { $self->XML_element($context, $ndepth, 'elem', $d); }
-    }
-    elsif (ref($dat) eq 'HASH')
-    {
-        foreach $d (sort grep {$_ !~ m/^\s/o} keys %{$dat})
-        { $self->XML_element($context, $ndepth, $d, $dat->{$d}); }
-    }
-    else
-    {
-        $context->{'name'} = ref($dat);
-        $context->{'name'} =~ s/^.*://o;
-        $dat->out_xml($context, $ndepth);
-    }
-
-    $fh->printf("%s</%s>\n", $depth, $k);
-    $self;
-}
-
-
-=head2 $t->XML_end($context, $tag, %attrs)
-
-Handles the default type of <data> for those tables which aren't subclassed
-
-=cut
-
-sub XML_end
-{
-    my ($self, $context, $tag, %attrs) = @_;
-    my ($dat, $addr);
-
-    return undef unless ($tag eq 'data');
-    $dat = $context->{'text'};
-    $dat =~ s/([0-9a-f]{2})\s*/hex($1)/oig;
-    if (defined $attrs{'addr'})
-    { $addr = hex($attrs{'addr'}); }
-    else
-    { $addr = length($self->{' dat'}); }
-    substr($self->{' dat'}, $addr, length($dat)) = $dat;
-    return $context;
-}
-    
-
-=head2 $t->dirty($val)
-
-This sets the dirty flag to the given value or 1 if no given value. It returns the
-value of the flag
-
-=cut
-
-sub dirty
-{
-    my ($self, $val) = @_;
-    my ($res) = $self->{' isDirty'};
-
-    $self->{' isDirty'} = defined $val ? $val : 1;
-    $res;
-}
-
-=head2 $t->update
-
-Each table knows how to update itself. This consists of doing whatever work
-is required to ensure that the memory version of the table is consistent
-and that other parameters in other tables have been updated accordingly.
-I.e. by the end of sending C<update> to all the tables, the memory version
-of the font should be entirely consistent.
-
-Some tables which do no work indicate to themselves the need to update
-themselves by setting isDirty above 1. This method resets that accordingly.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-
-    if ($self->{' isDirty'})
-    {
-        $self->read;
-        $self->{' isDirty'} = 0;
-        return $self;
-    }
-    else
-    { return undef; }
-}
-
-
-=head2 $t->empty
-
-Clears a table of all data to the level of not having been read
-
-=cut
-
-sub empty
-{
-    my ($self) = @_;
-    my (%keep);
-
-    foreach (qw(INFILE LENGTH OFFSET CSUM PARENT))
-    { $keep{" $_"} = 1; }
-
-    map {delete $self->{$_} unless $keep{$_}} keys %$self;
-    $self;
-}
-
-
-=head2 $t->release
-
-Releases ALL of the memory used by this table, and all of its component/child
-objects.  This method is called automatically by
-'C<Font::TTF::Font-E<GT>release>' (so you don't have to call it yourself).
-
-B<NOTE>, that it is important that this method get called at some point prior
-to the actual destruction of the object.  Internally, we track things in a
-structure that can result in circular references, and without calling
-'C<release()>' these will not properly get cleaned up by Perl.  Once this
-method has been called, though, don't expect to be able to do anything with the
-C<Font::TTF::Table> object; it'll have B<no> internal state whatsoever.
-
-B<Developer note:>  As part of the brute-force cleanup done here, this method
-will throw a warning message whenever unexpected key values are found within
-the C<Font::TTF::Table> object.  This is done to help ensure that any
-unexpected and unfreed values are brought to your attention so that you can bug
-us to keep the module updated properly; otherwise the potential for memory
-leaks due to dangling circular references will exist.
-
-=cut
-
-sub release
-{
-    my ($self) = @_;
-
-# delete stuff that we know we can, here
-
-    my @tofree = map { delete $self->{$_} } keys %{$self};
-
-    while (my $item = shift @tofree)
-    {
-        my $ref = ref($item);
-        if (UNIVERSAL::can($item, 'release'))
-        { $item->release(); }
-        elsif ($ref eq 'ARRAY')
-        { push( @tofree, @{$item} ); }
-        elsif (UNIVERSAL::isa($ref, 'HASH'))
-        { release($item); }
-    }
-
-# check that everything has gone - it better had!
-    foreach my $key (keys %{$self})
-    { warn ref($self) . " still has '$key' key left after release.\n"; }
-}
-
-
-sub __dumpvar__
-{
-    my ($self, $key) = @_;
-
-    return ($key eq ' PARENT' ? '...parent...' : $self->{$key});
-}
-
-1;
-
-=head1 BUGS
-
-No known bugs
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Table;
+
+=head1 NAME
+
+Font::TTF::Table - Superclass for tables and used for tables we don't have a class for
+
+=head1 DESCRIPTION
+
+Looks after the purely table aspects of a TTF table, such as whether the table
+has been read before, locating the file pointer, etc. Also copies tables from
+input to output.
+
+=head1 INSTANCE VARIABLES
+
+Instance variables start with a space
+
+=over 4
+
+=item read
+
+Flag which indicates that the table has already been read from file.
+
+=item dat
+
+Allows the creation of unspecific tables. Data is simply output to any font
+file being created.
+
+=item INFILE
+
+The read file handle
+
+=item OFFSET
+
+Location of the file in the input file
+
+=item LENGTH
+
+Length in the input directory
+
+=item CSUM
+
+Checksum read from the input file's directory
+
+=item PARENT
+
+The L<Font::TTF::Font> that table is part of
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw($VERSION);
+use Font::TTF::Utils;
+
+$VERSION = 0.0001;
+
+=head2 Font::TTF::Table->new(%parms)
+
+Creates a new table or subclass. Table instance variables are passed in
+at this point as an associative array.
+
+=cut
+
+sub new
+{
+    my ($class, %parms) = @_;
+    my ($self) = {};
+    my ($p);
+
+    $class = ref($class) || $class;
+    foreach $p (keys %parms)
+    { $self->{" $p"} = $parms{$p}; }
+    bless $self, $class;
+}
+
+
+=head2 $t->read
+
+Reads the table from the input file. Acts as a superclass to all true tables.
+This method marks the table as read and then just sets the input file pointer
+but does not read any data. If the table has already been read, then returns
+C<undef> else returns C<$self>
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+
+    return $self->read_dat if (ref($self) eq "Font::TTF::Table");
+    return undef if $self->{' read'};
+    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
+    $self->{' read'} = 1;
+    $self;
+}
+
+
+=head2 $t->read_dat
+
+Reads the table into the C<dat> instance variable for those tables which don't
+know any better
+
+=cut
+
+sub read_dat
+{
+    my ($self) = @_;
+
+# can't just $self->read here otherwise those tables which start their read sub with
+# $self->read_dat are going to permanently loop
+    return undef if ($self->{' read'});
+#    $self->{' read'} = 1;      # Let read do this, now out will call us for subclasses
+    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
+    $self->{' INFILE'}->read($self->{' dat'}, $self->{' LENGTH'});
+    $self;
+}
+
+=head2 $t->out($fh)
+
+Writes out the table to the font file. If there is anything in the
+C<data> instance variable then this is output, otherwise the data is copied
+from the input file to the output
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($dat, $i, $len, $count);
+
+    if (defined $self->{' dat'})
+    {
+        $fh->print($self->{' dat'});
+        return $self;
+    }
+
+    return undef unless defined $self->{' INFILE'};
+    $self->{' INFILE'}->seek($self->{' OFFSET'}, 0);
+    $len = $self->{' LENGTH'};
+    while ($len > 0)
+    {
+        $count = ($len > 4096) ? 4096 : $len;
+        $self->{' INFILE'}->read($dat, $count);
+        $fh->print($dat);
+        $len -= $count;
+    }
+    $self;
+}
+
+
+=head2 $t->out_xml($context)
+
+Outputs this table in XML format. The table is first read (if not already read) and then if
+there is no subclass, then the data is dumped as hex data
+
+=cut
+
+sub out_xml
+{
+    my ($self, $context, $depth) = @_;
+    my ($k);
+
+    if (ref($self) eq __PACKAGE__)
+    {
+        $self->read_dat;
+        Font::TTF::Utils::XML_hexdump($context, $depth, $self->{' dat'});
+    }
+    else
+    {
+        $self->read;
+        foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self})
+        {
+            $self->XML_element($context, $depth, $k, $self->{$k});
+        }
+    }
+    $self;
+}
+
+
+=head2 $t->XML_element
+
+Output a particular element based on its contents.
+
+=cut
+
+sub XML_element
+{
+    my ($self, $context, $depth, $k, $dat) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($ndepth, $d);
+
+    return unless defined $dat;
+    
+    if (!ref($dat))
+    {
+        $fh->printf("%s<%s>%s</%s>\n", $depth, $k, $dat, $k);
+        return $self;
+    }
+
+    $fh->printf("%s<%s>\n", $depth, $k);
+    $ndepth = $depth . $context->{'indent'};
+
+    if (ref($dat) eq 'SCALAR')
+    { $self->XML_element($context, $ndepth, 'scalar', $$dat); }
+    elsif (ref($dat) eq 'ARRAY')
+    {
+        foreach $d (@{$dat})
+        { $self->XML_element($context, $ndepth, 'elem', $d); }
+    }
+    elsif (ref($dat) eq 'HASH')
+    {
+        foreach $d (sort grep {$_ !~ m/^\s/o} keys %{$dat})
+        { $self->XML_element($context, $ndepth, $d, $dat->{$d}); }
+    }
+    else
+    {
+        $context->{'name'} = ref($dat);
+        $context->{'name'} =~ s/^.*://o;
+        $dat->out_xml($context, $ndepth);
+    }
+
+    $fh->printf("%s</%s>\n", $depth, $k);
+    $self;
+}
+
+
+=head2 $t->XML_end($context, $tag, %attrs)
+
+Handles the default type of <data> for those tables which aren't subclassed
+
+=cut
+
+sub XML_end
+{
+    my ($self, $context, $tag, %attrs) = @_;
+    my ($dat, $addr);
+
+    return undef unless ($tag eq 'data');
+    $dat = $context->{'text'};
+    $dat =~ s/([0-9a-f]{2})\s*/hex($1)/oig;
+    if (defined $attrs{'addr'})
+    { $addr = hex($attrs{'addr'}); }
+    else
+    { $addr = length($self->{' dat'}); }
+    substr($self->{' dat'}, $addr, length($dat)) = $dat;
+    return $context;
+}
+    
+
+=head2 $t->dirty($val)
+
+This sets the dirty flag to the given value or 1 if no given value. It returns the
+value of the flag
+
+=cut
+
+sub dirty
+{
+    my ($self, $val) = @_;
+    my ($res) = $self->{' isDirty'};
+
+    $self->{' isDirty'} = defined $val ? $val : 1;
+    $res;
+}
+
+=head2 $t->update
+
+Each table knows how to update itself. This consists of doing whatever work
+is required to ensure that the memory version of the table is consistent
+and that other parameters in other tables have been updated accordingly.
+I.e. by the end of sending C<update> to all the tables, the memory version
+of the font should be entirely consistent.
+
+Some tables which do no work indicate to themselves the need to update
+themselves by setting isDirty above 1. This method resets that accordingly.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+
+    if ($self->{' isDirty'})
+    {
+        $self->read;
+        $self->{' isDirty'} = 0;
+        return $self;
+    }
+    else
+    { return undef; }
+}
+
+
+=head2 $t->empty
+
+Clears a table of all data to the level of not having been read
+
+=cut
+
+sub empty
+{
+    my ($self) = @_;
+    my (%keep);
+
+    foreach (qw(INFILE LENGTH OFFSET CSUM PARENT))
+    { $keep{" $_"} = 1; }
+
+    map {delete $self->{$_} unless $keep{$_}} keys %$self;
+    $self;
+}
+
+
+=head2 $t->release
+
+Releases ALL of the memory used by this table, and all of its component/child
+objects.  This method is called automatically by
+'C<Font::TTF::Font-E<GT>release>' (so you don't have to call it yourself).
+
+B<NOTE>, that it is important that this method get called at some point prior
+to the actual destruction of the object.  Internally, we track things in a
+structure that can result in circular references, and without calling
+'C<release()>' these will not properly get cleaned up by Perl.  Once this
+method has been called, though, don't expect to be able to do anything with the
+C<Font::TTF::Table> object; it'll have B<no> internal state whatsoever.
+
+B<Developer note:>  As part of the brute-force cleanup done here, this method
+will throw a warning message whenever unexpected key values are found within
+the C<Font::TTF::Table> object.  This is done to help ensure that any
+unexpected and unfreed values are brought to your attention so that you can bug
+us to keep the module updated properly; otherwise the potential for memory
+leaks due to dangling circular references will exist.
+
+=cut
+
+sub release
+{
+    my ($self) = @_;
+
+# delete stuff that we know we can, here
+
+    my @tofree = map { delete $self->{$_} } keys %{$self};
+
+    while (my $item = shift @tofree)
+    {
+        my $ref = ref($item);
+        if (UNIVERSAL::can($item, 'release'))
+        { $item->release(); }
+        elsif ($ref eq 'ARRAY')
+        { push( @tofree, @{$item} ); }
+        elsif (UNIVERSAL::isa($ref, 'HASH'))
+        { release($item); }
+    }
+
+# check that everything has gone - it better had!
+    foreach my $key (keys %{$self})
+    { warn ref($self) . " still has '$key' key left after release.\n"; }
+}
+
+
+sub __dumpvar__
+{
+    my ($self, $key) = @_;
+
+    return ($key eq ' PARENT' ? '...parent...' : $self->{$key});
+}
+
+1;
+
+=head1 BUGS
+
+No known bugs
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttc.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttc.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttc.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,164 +1,164 @@
-package Font::TTF::Ttc;
-
-=head1 NAME
-
-Font::TTF::Ttc - Truetype Collection class
-
-=head1 DESCRIPTION
-
-A TrueType collection is a collection of TrueType fonts in one file in which
-tables may be shared between different directories. In order to support this,
-the TTC introduces the concept of a table being shared by different TrueType
-fonts. This begs the question of what should happen to the ' PARENT' property
-of a particular table. It is made to point to the first directory object which
-refers to it. It is therefore up to the application to sort out any confusion.
-Confusion only occurs if shared tables require access to non-shared tables.
-This should not happen since the shared tables are dealing with glyph
-information only and the private tables are dealing with encoding and glyph
-identification. Thus the general direction is from identification to glyph and
-not the other way around (at least not without knowledge of the particular
-context).
-
-=head1 INSTANCE VARIABLES
-
-The following instance variables are preceded by a space
-
-=over 4
-
-=item fname (P)
-
-Filename for this TrueType Collection
-
-=item INFILE (P)
-
-The filehandle of this collection
-
-=back
-
-The following instance variable does not start with a space
-
-=over 4
-
-=item directs
-
-An array of directories (Font::TTF::Font objects) for each sub-font in the directory
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw($VERSION);
-
-use IO::File;
-
-$VERSION = 0.0001;
-
-=head2 Font::TTF::Ttc->open($fname)
-
-Opens and reads the given filename as a TrueType Collection. Reading a collection
-involves reading each of the directories which go to make up the collection.
-
-=cut
-
-sub open
-{
-    my ($class, $fname) = @_;
-    my ($self) = {};
-    my ($fh);
-
-    unless (ref($fname))
-    {
-        $fh = IO::File->new($fname) or return undef;
-        binmode $fh;
-    } else
-    { $fh = $fname; }
-    
-    bless $self, $class;
-    $self->{' INFILE'} = $fh;
-    $self->{' fname'} = $fname;
-    $fh->seek(0, 0);
-    $self->read;
-}
-
-
-=head2 $c->read
-
-Reads a Collection by reading all the directories in the collection
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($fh) = $self->{' INFILE'};
-    my ($dat, $ttc, $ver, $num, $i, $loc);
-
-    $fh->read($dat, 12);
-    ($ttc, $ver, $num) = unpack("A4N2", $dat);
-
-    return undef unless $ttc eq "ttcf";
-    $fh->read($dat, $num << 2);
-    for ($i = 0; $i < $num; $i++)
-    {
-        $loc = unpack("N", substr($dat, $i << 2, 4));       
-        $self->{'directs'}[$i] = Font::TTF::Font->new('INFILE' => $fh,
-                                                'PARENT' => $self,
-                                                'OFFSET' => $loc) || return undef;
-    }
-    for ($i = 0; $i < $num; $i++)
-    { $self->{'directs'}[$i]->read; }
-    $self;
-}
-
-
-=head2 $c->find($direct, $name, $check, $off, $len)
-
-Hunts around to see if a table with the given characteristics of name, checksum,
-offset and length has been associated with a directory earlier in the list.
-Actually on checks the offset since no two tables can share the same offset in
-a TrueType font, collection or otherwise.
-
-=cut
-
-sub find
-{
-    my ($self, $direct, $name, $check, $off, $len) = @_;
-    my ($d);
-
-    foreach $d (@{$self->{'directs'}})
-    {
-        return undef if $d eq $direct;
-        next unless defined $d->{$name};
-        return $d->{$name} if ($d->{$name}{' OFFSET'} == $off);
-    }
-    undef;              # wierd that the font passed is not in the list!
-}
-
-
-=head2 $c->DESTROY
-
-Closees any opened files by us
-
-=cut
-
-sub DESTROY
-{
-    my ($self) = @_;
-    close ($self->{' INFILE'});
-    undef;
-}
-
-=head1 BUGS
-
-No known bugs, but then not ever executed!
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Ttc;
+
+=head1 NAME
+
+Font::TTF::Ttc - Truetype Collection class
+
+=head1 DESCRIPTION
+
+A TrueType collection is a collection of TrueType fonts in one file in which
+tables may be shared between different directories. In order to support this,
+the TTC introduces the concept of a table being shared by different TrueType
+fonts. This begs the question of what should happen to the ' PARENT' property
+of a particular table. It is made to point to the first directory object which
+refers to it. It is therefore up to the application to sort out any confusion.
+Confusion only occurs if shared tables require access to non-shared tables.
+This should not happen since the shared tables are dealing with glyph
+information only and the private tables are dealing with encoding and glyph
+identification. Thus the general direction is from identification to glyph and
+not the other way around (at least not without knowledge of the particular
+context).
+
+=head1 INSTANCE VARIABLES
+
+The following instance variables are preceded by a space
+
+=over 4
+
+=item fname (P)
+
+Filename for this TrueType Collection
+
+=item INFILE (P)
+
+The filehandle of this collection
+
+=back
+
+The following instance variable does not start with a space
+
+=over 4
+
+=item directs
+
+An array of directories (Font::TTF::Font objects) for each sub-font in the directory
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw($VERSION);
+
+use IO::File;
+
+$VERSION = 0.0001;
+
+=head2 Font::TTF::Ttc->open($fname)
+
+Opens and reads the given filename as a TrueType Collection. Reading a collection
+involves reading each of the directories which go to make up the collection.
+
+=cut
+
+sub open
+{
+    my ($class, $fname) = @_;
+    my ($self) = {};
+    my ($fh);
+
+    unless (ref($fname))
+    {
+        $fh = IO::File->new($fname) or return undef;
+        binmode $fh;
+    } else
+    { $fh = $fname; }
+    
+    bless $self, $class;
+    $self->{' INFILE'} = $fh;
+    $self->{' fname'} = $fname;
+    $fh->seek(0, 0);
+    $self->read;
+}
+
+
+=head2 $c->read
+
+Reads a Collection by reading all the directories in the collection
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($fh) = $self->{' INFILE'};
+    my ($dat, $ttc, $ver, $num, $i, $loc);
+
+    $fh->read($dat, 12);
+    ($ttc, $ver, $num) = unpack("A4N2", $dat);
+
+    return undef unless $ttc eq "ttcf";
+    $fh->read($dat, $num << 2);
+    for ($i = 0; $i < $num; $i++)
+    {
+        $loc = unpack("N", substr($dat, $i << 2, 4));       
+        $self->{'directs'}[$i] = Font::TTF::Font->new('INFILE' => $fh,
+                                                'PARENT' => $self,
+                                                'OFFSET' => $loc) || return undef;
+    }
+    for ($i = 0; $i < $num; $i++)
+    { $self->{'directs'}[$i]->read; }
+    $self;
+}
+
+
+=head2 $c->find($direct, $name, $check, $off, $len)
+
+Hunts around to see if a table with the given characteristics of name, checksum,
+offset and length has been associated with a directory earlier in the list.
+Actually on checks the offset since no two tables can share the same offset in
+a TrueType font, collection or otherwise.
+
+=cut
+
+sub find
+{
+    my ($self, $direct, $name, $check, $off, $len) = @_;
+    my ($d);
+
+    foreach $d (@{$self->{'directs'}})
+    {
+        return undef if $d eq $direct;
+        next unless defined $d->{$name};
+        return $d->{$name} if ($d->{$name}{' OFFSET'} == $off);
+    }
+    undef;              # wierd that the font passed is not in the list!
+}
+
+
+=head2 $c->DESTROY
+
+Closees any opened files by us
+
+=cut
+
+sub DESTROY
+{
+    my ($self) = @_;
+    close ($self->{' INFILE'});
+    undef;
+}
+
+=head1 BUGS
+
+No known bugs, but then not ever executed!
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttopen.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttopen.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Ttopen.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,1068 +1,1078 @@
-package Font::TTF::Ttopen;
-
-=head1 NAME
-
-Font::TTF::ttopen - Opentype superclass for standard Opentype lookup based tables
-(GSUB and GPOS)
-
-=head1 DESCRIPTION
-
-Handles all the script, lang, feature, lookup stuff for a
-L<Font::TTF::Gsub>/L<Font::TTF::Gpos> table leaving the class specifics to the
-subclass
-
-=head1 INSTANCE VARIABLES
-
-The instance variables of an opentype table form a complex sub-module hierarchy.
-
-=over 4
-
-=item Version
-
-This contains the version of the table as a floating point number
-
-=item SCRIPTS
-
-The scripts list is a hash of script tags. Each script tag (of the form
-$t->{'SCRIPTS'}{$tag}) has information below it.
-
-=over 8
-
-=item OFFSET
-
-This variable is preceeded by a space and gives the offset from the start of the
-table (not the table section) to the script table for this script
-
-=item REFTAG
-
-This variable is preceded by a space and gives a corresponding script tag to this
-one such that the offsets in the file are the same. When writing, it is up to the
-caller to ensure that the REFTAGs are set correctly, since these will be used to
-assume that the scripts are identical. Note that REFTAG must refer to a script which
-has no REFTAG of its own.
-
-=item DEFAULT
-
-This corresponds to the default language for this script, if there is one, and
-contains the same information as an itemised language
-
-=item LANG_TAGS
-
-This contains an array of language tag strings (each 4 bytes) corresponding to
-the languages listed by this script
-
-=item $lang
-
-Each language is a hash containing its information:
-
-=over 12
-
-=item OFFSET
-
-This variable is preceeded by a a space and gives the offset from the start of
-the whole table to the language table for this language
-
-=item REFTAG
-
-This variable is preceded by a space and has the same function as for the script
-REFTAG, only for the languages within a script.
-
-=item RE-ORDER
-
-This indicates re-ordering information, and has not been set. The value should
-always be 0.
-
-=item DEFAULT
-
-This holds the index of the default feature, if there is one, or -1 otherwise.
-
-=item FEATURES
-
-This is an array of feature indices which index into the FEATURES instance
-variable of the table
-
-=back
-
-=back
-
-=item FEATURES
-
-The features section of instance variables corresponds to the feature table in
-the opentype table.
-
-=over 8
-
-=item FEAT_TAGS
-
-This array gives the ordered list of feature tags for this table. It is used during
-reading and writing for converting between feature index and feature tag.
-
-=back
-
-The rest of the FEATURES variable is itself a hash based on the feature tag for
-each feature. Each feature has the following structure:
-
-=over 8
-
-=item OFFSET
-
-This attribute is preceeded by a space and gives the offset relative to the start of the whole
-table of this particular feature.
-
-=item PARMS
-
-This is an unused offset to the parameters for each feature
-
-=item LOOKUPS
-
-This is an array containing indices to lookups in the LOOKUP instance variable of the table
-
-=item INDEX
-
-This gives the feature index for this feature and is used during reading and writing for
-converting between feature tag and feature index.
-
-=back
-
-=item LOOKUP
-
-This variable is an array of lookups in order and is indexed via the features of a language of a
-script. Each lookup contains subtables and other information:
-
-=over 8
-
-=item OFFSET
-
-This name is preceeded by a space and contains the offset from the start of the table to this
-particular lookup
-
-=item TYPE
-
-This is a subclass specific type for a lookup. It stipulates the type of lookup and hence subtables
-within the lookup
-
-=item FLAG
-
-Holds the lookup flag bits
-
-=item SUB
-
-This holds an array of subtables which are subclass specific. Each subtable must have
-an OFFSET. The other variables described here are an abstraction used in both the
-GSUB and GPOS tables which are the target subclasses of this class.
-
-=over 12
-
-=item OFFSET
-
-This is preceeded by a space and gives the offset relative to the start of the table for this
-subtable
-
-=item FORMAT
-
-Gives the sub-table sub format for this GSUB subtable. It is assumed that this
-value is correct when it comes time to write the subtable.
-
-=item COVERAGE
-
-Most lookups consist of a coverage table corresponding to the first
-glyph to match. The offset of this coverage table is stored here and the coverage
-table looked up against the GSUB table proper. There are two lookups
-without this initial coverage table which is used to index into the RULES array.
-These lookups have one element in the RULES array which is used for the whole
-match.
-
-=item RULES
-
-The rules are a complex array. Each element of the array corresponds to an
-element in the coverage table (governed by the coverage index). If there is
-no coverage table, then there is considered to be only one element in the rules
-array. Each element of the array is itself an array corresponding to the
-possibly multiple string matches which may follow the initial glyph. Each
-element of this array is a hash with fixed keys corresponding to information
-needed to match a glyph string or act upon it. Thus the RULES element is an
-array of arrays of hashes which contain the following keys:
-
-=over 16
-
-=item MATCH
-
-This contains a sequence of elements held as an array. The elements may be
-glyph ids (gid), class ids (cids), or offsets to coverage tables. Each element
-corresponds to one glyph in the glyph string. See MATCH_TYPE for details of
-how the different element types are marked.
-
-=item PRE
-
-This array holds the sequence of elements preceeding the first match element
-and has the same form as the MATCH array.
-
-=item POST
-
-This array holds the sequence of elements to be tested for following the match
-string and is of the same form as the MATCH array.
-
-=item ACTION
-
-This array holds information regarding what should be done if a match is found.
-The array may either hold glyph ids (which are used to replace or insert or
-whatever glyphs in the glyph string) or 2 element arrays consisting of:
-
-=over 20
-
-=item OFFSET
-
-Offset from the start of the matched string that the lookup should start at
-when processing the substring.
-
-=item LOOKUP_INDEX
-
-The index to a lookup to be acted upon on the match string.
-
-=back
-
-=back
-
-=back
-
-=back
-
-=item CLASS
-
-For those lookups which use class categories rather than glyph ids for matching
-this is the offset to the class definition used to categories glyphs in the
-match string.
-
-=item PRE_CLASS
-
-This is the offset to the class definition for the before match glyphs
-
-=item POST_CLASS
-
-This is the offset to the class definition for the after match glyphs.
-
-=item ACTION_TYPE
-
-This string holds the type of information held in the ACTION variable of a RULE.
-It is subclass specific.
-
-=item MATCH_TYPE
-
-This holds the type of information in the MATCH array of a RULE. This is subclass
-specific.
-
-=item ADJUST
-
-This corresponds to a single action for all items in a coverage table. The meaning
-is subclass specific.
-
-=item CACHE
-
-This key starts with a space
-
-A hash of other tables (such as coverage tables, classes, anchors, device tables)
-based on the offset given in the subtable to that other information.
-Note that the documentation is particularly
-unhelpful here in that such tables are given as offsets relative to the
-beginning of the subtable not the whole GSUB table. This includes those items which
-are stored relative to another base within the subtable.
-
-=back
-
-
-=head1 METHODS
-
-=cut
-
-use Font::TTF::Table;
-use Font::TTF::Utils;
-use Font::TTF::Coverage;
-use strict;
-use vars qw(@ISA);
-
- at ISA = qw(Font::TTF::Table);
-
-=head2 $t->read
-
-Reads the table passing control to the subclass to handle the subtable specifics
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat, $i, $l, $oScript, $oFeat, $oLook, $tag, $nScript, $off, $dLang, $nLang, $lTag);
-    my ($nFeat, $nLook, $nSub, $j, $temp);
-    my ($fh) = $self->{' INFILE'};
-    my ($moff) = $self->{' OFFSET'};
-
-    $self->SUPER::read or return $self;
-    $fh->read($dat, 10);
-    ($self->{'Version'}, $oScript, $oFeat, $oLook) = TTF_Unpack("fSSS", $dat);
-
-# read features first so that in the script/lang hierarchy we can use feature tags
-
-    $fh->seek($moff + $oFeat, 0);
-    $fh->read($dat, 2);
-    $nFeat = unpack("n", $dat);
-    $self->{'FEATURES'} = {};
-    $l = $self->{'FEATURES'};
-    $fh->read($dat, 6 * $nFeat);
-    for ($i = 0; $i < $nFeat; $i++)
-    {
-    	($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
-    	while (defined $l->{$tag})
-    	{
-    	    if ($tag =~ m/(.*?)\s_(\d+)$/o)
-    	    { $tag = $1 . " _" . ($2 + 1); }
-    	    else
-    	    { $tag .= " _0"; }
-    	}
-	    $l->{$tag}{' OFFSET'} = $off + $oFeat;
-	    $l->{$tag}{'INDEX'} = $i;
-	    push (@{$l->{'FEAT_TAGS'}}, $tag);
-    }
-
-    foreach $tag (grep {length($_) == 4} keys %$l)
-    {
-	    $fh->seek($moff + $l->{$tag}{' OFFSET'}, 0);
-    	$fh->read($dat, 4);
-	    ($l->{$tag}{'PARMS'}, $nLook) = unpack("n2", $dat);
-    	$fh->read($dat, $nLook * 2);
-	    $l->{$tag}{'LOOKUPS'} = [unpack("n*", $dat)];
-    }
-
-# Now the script/lang hierarchy
-
-    $fh->seek($moff + $oScript, 0);
-    $fh->read($dat, 2);
-    $nScript = unpack("n", $dat);
-    $self->{'SCRIPTS'} = {};
-    $l = $self->{'SCRIPTS'};
-    $fh->read($dat, 6 * $nScript);
-    for ($i = 0; $i < $nScript; $i++)
-    {
-    	($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
-    	$off += $oScript;
-        foreach (keys %$l)
-        { $l->{$tag}{' REFTAG'} = $_ if ($l->{$_}{' OFFSET'} == $off
-                                        && !defined $l->{$_}{' REFTAG'}); }
-	    $l->{$tag}{' OFFSET'} = $off;
-    }
-
-    foreach $tag (keys %$l)
-    {
-        next if ($l->{$tag}{' REFTAG'});
-    	$fh->seek($moff + $l->{$tag}{' OFFSET'}, 0);
-    	$fh->read($dat, 4);
-    	($dLang, $nLang) = unpack("n2", $dat);
-    	$l->{$tag}{'DEFAULT'}{' OFFSET'} =
-    	        $dLang + $l->{$tag}{' OFFSET'} if $dLang;
-    	$fh->read($dat, 6 * $nLang);
-    	for ($i = 0; $i < $nLang; $i++)
-    	{
-    	    ($lTag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
-    	    $off += $l->{$tag}{' OFFSET'};
-    	    $l->{$tag}{$lTag}{' OFFSET'} = $off;
-            foreach (@{$l->{$tag}{'LANG_TAGS'}})
-            { $l->{$tag}{$lTag}{' REFTAG'} = $_ if ($l->{$tag}{$_}{' OFFSET'} == $off
-                                                   && !$l->{$tag}{$_}{' REFTAG'}); }
-    	    push (@{$l->{$tag}{'LANG_TAGS'}}, $lTag);
-    	}
-    	foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT')
-    	{
-    	    next unless defined $l->{$tag}{$lTag};
-            next if ($l->{$tag}{$lTag}{' REFTAG'});
-    	    $fh->seek($moff + $l->{$tag}{$lTag}{' OFFSET'}, 0);
-    	    $fh->read($dat, 6);
-    	    ($l->{$tag}{$lTag}{'RE-ORDER'}, $l->{$tag}{$lTag}{'DEFAULT'}, $nFeat) 
-    	      = unpack("n3", $dat);
-    	    $fh->read($dat, $nFeat * 2);
-    	    $l->{$tag}{$lTag}{'FEATURES'} = [map {$self->{'FEATURES'}{'FEAT_TAGS'}[$_]} unpack("n*", $dat)];
-    	}
-    	foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT')
-    	{
-       	    next unless $l->{$tag}{$lTag}{' REFTAG'};
-    	    $temp = $l->{$tag}{$lTag}{' REFTAG'};
-    	    $l->{$tag}{$lTag} = &copy($l->{$tag}{$temp});
-    	    $l->{$tag}{$lTag}{' REFTAG'} = $temp;
-    	}
-    }
-    foreach $tag (keys %$l)
-    {
-        next unless $l->{$tag}{' REFTAG'};
-        $temp = $l->{$tag}{' REFTAG'};
-        $l->{$tag} = &copy($l->{$temp});
-        $l->{$tag}{' REFTAG'} = $temp;
-    }
-
-# And finally the lookups
-
-    $fh->seek($moff + $oLook, 0);
-    $fh->read($dat, 2);
-    $nLook = unpack("n", $dat);
-    $fh->read($dat, $nLook * 2);
-    $i = 0;
-    map { $self->{'LOOKUP'}[$i++]{' OFFSET'} = $_; } unpack("n*", $dat);
-
-    for ($i = 0; $i < $nLook; $i++)
-    {
-    	$l = $self->{'LOOKUP'}[$i];
-    	$fh->seek($l->{' OFFSET'} + $moff + $oLook, 0);
-    	$fh->read($dat, 6);
-    	($l->{'TYPE'}, $l->{'FLAG'}, $nSub) = unpack("n3", $dat);
-    	$fh->read($dat, $nSub * 2);
-    	$j = 0;
-    	map { $l->{'SUB'}[$j]{' OFFSET'} = $_; } unpack("n*", $dat);
-    	for ($j = 0; $j < $nSub; $j++)
-    	{
-    	    $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0);
-	        $self->read_sub($fh, $l, $j);
-	    }
-    }
-    return $self;
-}
-
-=head2 $t->read_sub($fh, $lookup, $index)
-
-This stub is to allow subclasses to read subtables of lookups in a table specific manner. A
-reference to the lookup is passed in along with the subtable index. The file is located at the
-start of the subtable to be read
-
-=cut
-
-sub read_sub
-{ }
-
-
-=head2 $t->extension()
-
-Returns the lookup number for the extension table that allows access to 32-bit offsets.
-
-=cut
-
-sub extension
-{ }
-
-
-=head2 $t->out($fh)
-
-Writes this Opentype table to the output calling $t->out_sub for each sub table
-at the appropriate point in the output. The assumption is that on entry the
-number of scripts, languages, features, lookups, etc. are all resolved and
-the relationships fixed. This includes a script's LANG_TAGS list and that all
-scripts and languages in their respective dictionaries either have a REFTAG or contain
-real data.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($i, $j, $base, $off, $tag, $t, $l, $lTag, $oScript, @script, @tags);
-    my ($end, $nTags, @offs, $oFeat, $oLook, $nSub, $nSubs, $big);
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-# First sort the features
-    $i = 0;
-    $self->{'FEATURES'}{'FEAT_TAGS'} = [sort grep {length($_) == 4 || m/\s_\d+$/o} %{$self->{'FEATURES'}}]
-            if (!defined $self->{'FEATURES'}{'FEAT_TAGS'});
-    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
-    { $self->{'FEATURES'}{$t}{'INDEX'} = $i++; }
-
-    $base = $fh->tell();
-    $fh->print(TTF_Pack("f", $self->{'Version'}));
-    $fh->print(pack("n3", 10, 0, 0));
-    $oScript = $fh->tell() - $base;
-    @script = sort grep {length($_) == 4} keys %{$self->{'SCRIPTS'}};
-    $fh->print(pack("n", $#script + 1));
-    foreach $t (@script)
-    { $fh->print(pack("a4n", $t, 0)); }
-
-    $end = $fh->tell();
-    foreach $t (@script)
-    {
-        $fh->seek($end, 0);
-        $tag = $self->{'SCRIPTS'}{$t};
-        next if ($tag->{' REFTAG'});
-    	$tag->{' OFFSET'} = tell($fh) - $base - $oScript;
-    	$fh->print(pack("n2", 0, $#{$tag->{'LANG_TAGS'}} + 1));
-    	foreach $lTag (sort @{$tag->{'LANG_TAGS'}})
-    	{ $fh->print(pack("a4n", $lTag, 0)); }
-    	foreach $lTag (@{$tag->{'LANG_TAGS'}}, 'DEFAULT')
-    	{
-    	    my ($def);
-    	    $l = $tag->{$lTag};
-    	    next if (!defined $l || $l->{' REFTAG'} ne '');
-    	    $l->{' OFFSET'} = tell($fh) - $base - $oScript - $tag->{' OFFSET'};
-    	    if (defined $l->{'DEFAULT'})
-#    	    { $def = $self->{'FEATURES'}{$l->{'FEATURES'}[$l->{'DEFAULT'}]}{'INDEX'}; }
-            { $def = $l->{'DEFAULT'}; }
-    	    else
-    	    { $def = -1; }
-    	    $fh->print(pack("n*", $l->{'RE_ORDER'}, $def, $#{$l->{'FEATURES'}} + 1,
-    	            map {$self->{'FEATURES'}{$_}{'INDEX'}} @{$l->{'FEATURES'}}));
-    	}
-    	$end = $fh->tell();
-    	if ($tag->{'DEFAULT'}{' REFTAG'} || defined $tag->{'DEFAULT'}{'FEATURES'})
-    	{
-        	$fh->seek($base + $oScript + $tag->{' OFFSET'}, 0);
-        	$off = $tag->{'DEFAULT'}{' REFTAG'} ?
-        	        $tag->{$tag->{'DEFAULT'}{' REFTAG'}}{' OFFSET'} :
-        	        $tag->{'DEFAULT'}{' OFFSET'};
-        	$fh->print(pack("n", $off));
-    	}
-    	$fh->seek($base + $oScript + $tag->{' OFFSET'} + 4, 0);
-    	foreach (sort @{$tag->{'LANG_TAGS'}})
-    	{
-    	    $off = $tag->{$_}{' REFTAG'} ? $tag->{$tag->{$_}{' REFTAG'}}{' OFFSET'} :
-    	            $tag->{$_}{' OFFSET'};
-    	    $fh->print(pack("a4n", $_, $off));
-    	}
-    }
-    $fh->seek($base + $oScript + 2, 0);
-    foreach $t (@script)
-    {
-        $tag = $self->{'SCRIPTS'}{$t};
-        $off = $tag->{' REFTAG'} ? $tag->{$tag->{' REFTAG'}}{' OFFSET'} : $tag->{' OFFSET'};
-        $fh->print(pack("a4n", $t, $off));
-    }
-
-    $fh->seek($end, 0);
-    $oFeat = $end - $base;
-    $nTags = $#{$self->{'FEATURES'}{'FEAT_TAGS'}} + 1;
-    $fh->print(pack("n", $nTags));
-    $fh->print(pack("a4n", "    ", 0) x $nTags);
-    
-    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
-    {
-        $tag = $self->{'FEATURES'}{$t};
-        $tag->{' OFFSET'} = tell($fh) - $base - $oFeat;
-        $fh->print(pack("n*", 0, $#{$tag->{'LOOKUPS'}} + 1, @{$tag->{'LOOKUPS'}}));
-    }
-    $end = $fh->tell();
-    $fh->seek($oFeat + $base + 2, 0);
-    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
-    { $fh->print(pack("a4n", $t, $self->{'FEATURES'}{$t}{' OFFSET'})); }
-
-    undef $big;
-    $fh->seek($end, 0);
-    $oLook = $end - $base;
-    $nTags = $#{$self->{'LOOKUP'}} + 1;
-    $fh->print(pack("n", $nTags));
-    $fh->print(pack("n", 0) x $nTags);
-    $end = $fh->tell();
-    foreach $tag (@{$self->{'LOOKUP'}})
-    { $nSubs += $self->num_sub($tag); }
-    for ($i = 0; $i < $nTags; $i++)
-    {
-        $fh->seek($end, 0);
-        $tag = $self->{'LOOKUP'}[$i];
-        $tag->{' OFFSET'} = $end - $base - $oLook;
-        if (!defined $big && $tag->{' OFFSET'} + ($nTags - $i) * 6 + $nSubs * 10 > 65535)
-        {
-            my ($k, $ext);
-            $ext = $self->extension();
-            $i--;
-            $tag = $self->{'LOOKUP'}[$i];
-            $end = $tag->{' OFFSET'} + $base + $oLook;
-            $fh->seek($end, 0);
-            $big = $i;
-            for ($j = $i; $j < $nTags; $j++)
-            {
-                $tag = $self->{'LOOKUP'}[$j];
-                $nSub = $self->num_sub($tag);
-                $fh->print(pack("nnn", $ext, $tag->{'FLAG'}, $nSub));
-                $fh->print(pack("n*", map {$_ * 8 + 6 + $nSub * 2} (1 .. $nSub)));
-                $tag->{' EXT_OFFSET'} = $fh->tell();
-                $tag->{' OFFSET'} = $tag->{' EXT_OFFSET'} - $nSub * 2 - 6 - $base - $oLook;
-                for ($k = 0; $k < $nSub; $k++)
-                { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, 0)); }
-            }
-            $tag = $self->{'LOOKUP'}[$i];
-        }
-        $nSub = $self->num_sub($tag);
-        if (!defined $big)
-        {
-            $fh->print(pack("nnn", $tag->{'TYPE'}, $tag->{'FLAG'}, $nSub));
-            $fh->print(pack("n", 0) x $nSub);
-        }
-        else
-        { $end = $tag->{' EXT_OFFSET'}; }
-        @offs = ();
-        for ($j = 0; $j < $nSub; $j++)
-        {
-            push(@offs, tell($fh) - $end);
-            $self->out_sub($fh, $tag, $j);
-        }
-        $end = $fh->tell();
-        if (!defined $big)
-        {
-            $fh->seek($tag->{' OFFSET'} + $base + $oLook + 6, 0);
-            $fh->print(pack("n*", @offs));
-        }
-        else
-        {
-            $fh->seek($tag->{' EXT_OFFSET'}, 0);
-            for ($j = 0; $j < $nSub; $j++)
-            { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, $offs[$j] - $j * 8)); }
-        }
-    }
-    $fh->seek($oLook + $base + 2, 0);
-    $fh->print(pack("n*", map {$self->{'LOOKUP'}[$_]{' OFFSET'}} (0 .. $nTags - 1)));
-    $fh->seek($base + 6, 0);
-    $fh->print(pack('n2', $oFeat, $oLook));
-    $fh->seek($end, 0);
-    $self;
-}
-
-
-=head2 $t->num_sub($lookup)
-
-Asks the subclass to count the number of subtables for a particular lookup and to
-return that value. Used in out().
-
-=cut
-
-sub num_sub
-{
-    my ($self, $lookup) = @_;
-
-    return $#{$lookup->{'SUB'}} + 1;
-}
-
-
-=head2 $t->out_sub($fh, $lookup, $index)
-
-This stub is to allow subclasses to output subtables of lookups in a table specific manner. A
-reference to the lookup is passed in along with the subtable index. The file is located at the
-start of the subtable to be output
-
-=cut
-
-sub out_sub
-{ }
-
-
-=head1 Internal Functions & Methods
-
-Most of these methods are used by subclasses for handling such things as coverage
-tables.
-
-=head2 copy($ref)
-
-Internal function to copy the top level of a dictionary to create a new dictionary.
-Only the top level is copied.
-
-=cut
-
-sub copy
-{
-    my ($ref) = @_;
-    my ($res) = {};
-
-    foreach (keys %$ref)
-    { $res->{$_} = $ref->{$_}; }
-    $res;
-}
-
-
-=head2 $t->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover)
-
-Reads a coverage table and stores the results in $lookup->{' CACHE'}, that is, if
-it hasn't been read already.
-
-=cut
-
-sub read_cover
-{
-    my ($self, $offset, $base, $lookup, $fh, $is_cover) = @_;
-    my ($loc) = $fh->tell();
-    my ($cover, $str);
-
-    return undef unless $offset;
-    $str = sprintf("%X", $base + $offset);
-    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
-    $fh->seek($base + $offset, 0);
-    $cover = Font::TTF::Coverage->new($is_cover)->read($fh);
-    $fh->seek($loc, 0);
-    $lookup->{' CACHE'}{$str} = $cover;
-    return $cover;
-}
-
-
-=head2 ref_cache($obj, $cache, $offset)
-
-Internal function to keep track of the local positioning of subobjects such as
-coverage and class definition tables, and their offsets.
-What happens is that the cache is a hash of
-sub objects indexed by the reference (using a string mashing of the
-reference name which is valid for the duration of the reference) and holds a
-list of locations in the output string which should be filled in with the
-offset to the sub object when the final string is output in out_final.
-
-Uses tricks for Tie::Refhash
-
-=cut
-
-sub ref_cache
-{
-    my ($obj, $cache, $offset) = @_;
-
-    return 0 unless defined $obj;
-    $cache->{"$obj"}[0] = $obj unless defined $cache->{"$obj"};
-    push (@{$cache->{"$obj"}[1]}, $offset);
-    return 0;
-}
-
-
-=head2 out_final($fh, $out, $cache_list, $state)
-
-Internal function to actually output everything to the file handle given that
-now we know the offset to the first sub object to be output and which sub objects
-are to be output and what locations need to be updated, we can now
-generate everything. $cache_list is an array of two element arrays. The first element
-is a cache object, the second is an offset to be subtracted from each reference
-to that object made in the cache.
-
-If $state is 1, then the output is not sent to the filehandle and the return value
-is the string to be output. If $state is absent or 0 then output is not limited
-by storing in a string first and the return value is "";
-
-=cut
-
-sub out_final
-{
-    my ($fh, $out, $cache_list, $state) = @_;
-    my ($len) = length($out);
-    my ($base_loc) = $state ? 0 : $fh->tell();
-    my ($loc, $t, $r, $s, $master_cache, $offs, $str);
-
-    $fh->print($out) unless $state;       # first output the current attempt
-    foreach $r (@$cache_list)
-    {
-        $offs = $r->[1];
-        foreach $t (sort keys %{$r->[0]})
-        {
-            $str = "$t";
-            if (!defined $master_cache->{$str})
-            {
-                $master_cache->{$str} = ($state ? length($out) : $fh->tell())
-                                                            - $base_loc;
-                if ($state)
-                { $out .= $r->[0]{$str}[0]->out($fh, 1); }
-                else
-                { $r->[0]{$str}[0]->out($fh, 0); }
-            }
-            foreach $s (@{$r->[0]{$str}[1]})
-            { substr($out, $s, 2) = pack('n', $master_cache->{$str} - $offs); }
-        }
-    }
-    if ($state)
-    { return $out; }
-    else
-    {
-        $loc = $fh->tell();
-        $fh->seek($base_loc, 0);
-        $fh->print($out);       # the corrected version
-        $fh->seek($loc, 0);
-    }
-}
-
-
-=head2 $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc)
-
-Internal method to read context (simple and chaining context) lookup subtables for
-the GSUB and GPOS table types. The assumed values for $type correspond to those
-for GSUB, so GPOS should adjust the values upon calling.
-
-=cut
-
-sub read_context
-{
-    my ($self, $lookup, $fh, $type, $fmt, $cover, $count, $loc) = @_;
-    my ($dat, $i, $s, $t, @subst, @srec, $mcount, $scount);
-    
-    if ($type == 5 && $fmt < 3)
-    {
-        if ($fmt == 2)
-        {
-            $fh->read($dat, 2);
-            $lookup->{'CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0);
-            $count = TTF_Unpack('S', $dat);
-        }
-        $fh->read($dat, $count << 1);
-        foreach $s (TTF_Unpack('S*', $dat))
-        {
-            if ($s == 0)
-            {
-                push (@{$lookup->{'RULES'}}, []);
-                next;
-            }
-            @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);
-                @srec = ();
-                $fh->read($dat, 4);
-                ($mcount, $scount) = TTF_Unpack('S2', $dat);
-                $mcount--;
-                $fh->read($dat, ($mcount << 1) + ($scount << 2));
-                for ($i = 0; $i < $scount; $i++)
-                { push (@srec, [TTF_Unpack('S2', substr($dat,
-                    ($mcount << 1) + ($i << 2), 4))]); }
-                push (@subst, {'ACTION' => [@srec],
-                               'MATCH' => [TTF_Unpack('S*',
-                                    substr($dat, 0, $mcount << 1))]});
-            }
-            push (@{$lookup->{'RULES'}}, [@subst]);
-        }
-        $lookup->{'ACTION_TYPE'} = 'l';
-        $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g');
-    } elsif ($type == 5 && $fmt == 3)
-    {
-        $fh->read($dat, ($cover << 1) + ($count << 2));
-        @subst = (); @srec = ();
-        for ($i = 0; $i < $cover; $i++)
-        { push (@subst, $self->read_cover(TTF_Unpack('S', substr($dat, $i << 1, 2)),
-                                $loc, $lookup, $fh, 1)); }
-        for ($i = 0; $i < $count; $i++)
-        { push (@srec, [TTF_Unpack('S2', substr($dat, ($count << 1) + ($i << 2), 4))]); }
-        $lookup->{'RULES'} = [[{'ACTION' => [@srec], 'MATCH' => [@subst]}]];
-        $lookup->{'ACTION_TYPE'} = 'l';
-        $lookup->{'MATCH_TYPE'} = 'o';
-    } elsif ($type == 6 && $fmt < 3)
-    {
-        if ($fmt == 2)
-        {
-            $fh->read($dat, 6);
-            $lookup->{'PRE_CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0) if $count;
-            ($i, $mcount, $count) = TTF_Unpack('S3', $dat);     # messy: 2 classes & count
-            $lookup->{'CLASS'} = $self->read_cover($i, $loc, $lookup, $fh, 0) if $i;
-            $lookup->{'POST_CLASS'} = $self->read_cover($mcount, $loc, $lookup, $fh, 0) if $mcount;
-        }
-        $fh->read($dat, $count << 1);
-        foreach $s (TTF_Unpack('S*', $dat))
-        {
-            if ($s == 0)
-            {
-                push (@{$lookup->{'RULES'}}, []);
-                next;
-            }
-            @subst = ();
-            $fh->seek($loc + $s, 0);
-            $fh->read($dat, 2);
-            $t = TTF_Unpack('S', $dat);
-            $fh->read($dat, $t << 1);
-            foreach $i (TTF_Unpack('S*', $dat))
-            {
-                $fh->seek($loc + $s + $i, 0);
-                @srec = ();
-                $t = {};
-                $fh->read($dat, 2);
-                $mcount = TTF_Unpack('S', $dat);
-                if ($mcount > 0)
-                {
-                    $fh->read($dat, $mcount << 1);
-                    $t->{'PRE'} = [TTF_Unpack('S*', $dat)];
-                }
-                $fh->read($dat, 2);
-                $mcount = TTF_Unpack('S', $dat);
-                if ($mcount > 1)
-                {
-                    $fh->read($dat, ($mcount - 1) << 1);
-                    $t->{'MATCH'} = [TTF_Unpack('S*', $dat)];
-                }
-                $fh->read($dat, 2);
-                $mcount = TTF_Unpack('S', $dat);
-                if ($mcount > 0)
-                {
-                    $fh->read($dat, $mcount << 1);
-                    $t->{'POST'} = [TTF_Unpack('S*', $dat)];
-                }
-                $fh->read($dat, 2);
-                $scount = TTF_Unpack('S', $dat);
-                $fh->read($dat, $scount << 2);
-                for ($i = 0; $i < $scount; $i++)
-                { push (@srec, [TTF_Unpack('S2', substr($dat, $i << 2))]); }
-                $t->{'ACTION'} = [@srec];
-                push (@subst, $t);
-            }
-            push (@{$lookup->{'RULES'}}, [@subst]);
-        }
-        $lookup->{'ACTION_TYPE'} = 'l';
-        $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g');
-    } elsif ($type == 6 && $fmt == 3)
-    {
-        $t = {};
-        unless ($cover == 0)
-        {
-            @subst = ();
-            $fh->read($dat, $cover << 1);
-            foreach $s (TTF_Unpack('S*', $dat))
-            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
-            $t->{'PRE'} = [@subst];
-        }
-        $fh->read($dat, 2);
-        $count = TTF_Unpack('S', $dat);
-        unless ($count == 0)
-        {
-            @subst = ();
-            $fh->read($dat, $count << 1);
-            foreach $s (TTF_Unpack('S*', $dat))
-            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
-            $t->{'MATCH'} = [@subst];
-        }
-        $fh->read($dat, 2);
-        $count = TTF_Unpack('S', $dat);
-        unless ($count == 0)
-        {
-            @subst = ();
-            $fh->read($dat, $count << 1);
-            foreach $s (TTF_Unpack('S*', $dat))
-            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
-            $t->{'POST'} = [@subst];
-        }
-        $fh->read($dat, 2);
-        $count = TTF_Unpack('S', $dat);
-        @subst = ();
-        $fh->read($dat, $count << 2);
-        for ($i = 0; $i < $count; $i++)
-        { push (@subst, [TTF_Unpack('S2', substr($dat, $i << 2, 4))]); }
-        $t->{'ACTION'} = [@subst];
-        $lookup->{'RULES'} = [[$t]];
-        $lookup->{'ACTION_TYPE'} = 'l';
-        $lookup->{'MATCH_TYPE'} = 'o';
-    }
-    $lookup;
-}
-
-
-=head2 $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num)
-
-Provides shared behaviour between GSUB and GPOS tables during output for context
-(chained and simple) rules. In addition, support is provided here for type 4 GSUB
-tables, which are not used in GPOS. The value for $type corresponds to the type
-in a GSUB table so calling from GPOS should adjust the value accordingly.
-
-=cut
-
-sub out_context
-{
-    my ($self, $lookup, $fh, $type, $fmt, $ctables, $out, $num) = @_;
-    my ($offc, $offd, $i, $j, $r, $t, $numd);
-
-    if (($type == 4 || $type == 5 || $type == 6) && ($fmt == 1 || $fmt == 2))
-    {
-        my ($base_off);
-        
-        if ($fmt == 1)
-        {
-            $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            $num);
-            $base_off = 6;
-        } elsif ($type == 5)
-        {
-            $out = pack("nnnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                            Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 4), $num);
-            $base_off = 8;
-        } elsif ($type == 6)
-        {
-            $out = pack("n6", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
-                                Font::TTF::Ttopen::ref_cache($lookup->{'PRE_CLASS'}, $ctables, 4),
-                                Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 6),
-                                Font::TTF::Ttopen::ref_cache($lookup->{'POST_CLASS'}, $ctables, 8),
-                                $num);
-            $base_off = 12;
-        }
-
-        $out .= pack('n*', (0) x $num);
-        $offc = length($out);
-        for ($i = 0; $i < $num; $i++)
-        {
-            $r = $lookup->{'RULES'}[$i];
-            next unless exists $r->[0]{'ACTION'};
-            $numd = $#{$r} + 1;
-            substr($out, ($i << 1) + $base_off, 2) = pack('n', $offc);
-            $out .= pack('n*', $numd, (0) x $numd);
-            $offd = length($out) - $offc;
-            for ($j = 0; $j < $numd; $j++)
-            {
-                substr($out, $offc + 2 + ($j << 1), 2) = pack('n', $offd);
-                if ($type == 4)
-                {
-                    $out .= pack('n*', $r->[$j]{'ACTION'}[0], $#{$r->[$j]{'MATCH'}} + 2,
-                                        @{$r->[$j]{'MATCH'}});
-                } elsif ($type == 5)
-                {
-                    $out .= pack('n*', $#{$r->[$j]{'MATCH'}} + 2,
-                                        $#{$r->[$j]{'ACTION'}} + 1,
-                                        @{$r->[$j]{'MATCH'}});
-                    foreach $t (@{$r->[$j]{'ACTION'}})
-                    { $out .= pack('n2', @$t); }
-                } elsif ($type == 6)
-                {
-                    $out .= pack('n*', $#{$r->[$j]{'PRE'}} + 1, @{$r->[$j]{'PRE'}},
-                                    $#{$r->[$j]{'MATCH'}} + 2, @{$r->[$j]{'MATCH'}},
-                                    $#{$r->[$j]{'POST'}} + 1, @{$r->[$j]{'POST'}},
-                                    $#{$r->[$j]{'ACTION'}} + 1);
-                    foreach $t (@{$r->[$j]{'ACTION'}})
-                    { $out .= pack('n2', @$t); }
-                }
-                $offd = length($out) - $offc;
-            }
-            $offc = length($out);
-        }
-    } elsif ($type == 5 && $fmt == 3)
-    {
-        $out .= pack('n3', $fmt, $#{$lookup->{'RULES'}[0][0]{'MATCH'}} + 1,
-                                $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1);
-        foreach $t (@{$lookup->{'RULES'}[0][0]{'MATCH'}})
-        { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out))); }
-        foreach $t (@{$lookup->{'RULES'}[0][0]{'ACTION'}})
-        { $out .= pack('n2', @$t); }
-    } elsif ($type == 6 && $fmt == 3)
-    {
-        $r = $lookup->{'RULES'}[0][0];
-        $out .= pack('n2', $fmt, $#{$r->{'PRE'}} + 1);
-        foreach $t (@{$r->{'PRE'}})
-        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
-        $out .= pack('n', $#{$r->{'MATCH'}} + 1);
-        foreach $t (@{$r->{'MATCH'}})
-        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
-        $out .= pack('n', $#{$r->{'POST'}} + 1);
-        foreach $t (@{$r->{'POST'}})
-        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
-        $out .= pack('n', $#{$r->{'ACTION'}} + 1);
-        foreach $t (@{$r->{'ACTION'}})
-        { $out .= pack('n2', @$t); }
-    }
-    $out;
-}
-
-=head1 BUGS
-
-=over 4
-
-=item *
-
-No way to share cachable items (coverage tables, classes, anchors, device tables)
-across different lookups. The items are always output after the lookup and
-repeated if necessary. Within lookup sharing is possible.
-
-=back
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
-1;
-
+package Font::TTF::Ttopen;
+
+=head1 NAME
+
+Font::TTF::ttopen - Opentype superclass for standard Opentype lookup based tables
+(GSUB and GPOS)
+
+=head1 DESCRIPTION
+
+Handles all the script, lang, feature, lookup stuff for a
+L<Font::TTF::Gsub>/L<Font::TTF::Gpos> table leaving the class specifics to the
+subclass
+
+=head1 INSTANCE VARIABLES
+
+The instance variables of an opentype table form a complex sub-module hierarchy.
+
+=over 4
+
+=item Version
+
+This contains the version of the table as a floating point number
+
+=item SCRIPTS
+
+The scripts list is a hash of script tags. Each script tag (of the form
+$t->{'SCRIPTS'}{$tag}) has information below it.
+
+=over 8
+
+=item OFFSET
+
+This variable is preceeded by a space and gives the offset from the start of the
+table (not the table section) to the script table for this script
+
+=item REFTAG
+
+This variable is preceded by a space and gives a corresponding script tag to this
+one such that the offsets in the file are the same. When writing, it is up to the
+caller to ensure that the REFTAGs are set correctly, since these will be used to
+assume that the scripts are identical. Note that REFTAG must refer to a script which
+has no REFTAG of its own.
+
+=item DEFAULT
+
+This corresponds to the default language for this script, if there is one, and
+contains the same information as an itemised language
+
+=item LANG_TAGS
+
+This contains an array of language tag strings (each 4 bytes) corresponding to
+the languages listed by this script
+
+=item $lang
+
+Each language is a hash containing its information:
+
+=over 12
+
+=item OFFSET
+
+This variable is preceeded by a a space and gives the offset from the start of
+the whole table to the language table for this language
+
+=item REFTAG
+
+This variable is preceded by a space and has the same function as for the script
+REFTAG, only for the languages within a script.
+
+=item RE-ORDER
+
+This indicates re-ordering information, and has not been set. The value should
+always be 0.
+
+=item DEFAULT
+
+This holds the index of the default feature, if there is one, or -1 otherwise.
+
+=item FEATURES
+
+This is an array of feature indices which index into the FEATURES instance
+variable of the table
+
+=back
+
+=back
+
+=item FEATURES
+
+The features section of instance variables corresponds to the feature table in
+the opentype table.
+
+=over 8
+
+=item FEAT_TAGS
+
+This array gives the ordered list of feature tags for this table. It is used during
+reading and writing for converting between feature index and feature tag.
+
+=back
+
+The rest of the FEATURES variable is itself a hash based on the feature tag for
+each feature. Each feature has the following structure:
+
+=over 8
+
+=item OFFSET
+
+This attribute is preceeded by a space and gives the offset relative to the start of the whole
+table of this particular feature.
+
+=item PARMS
+
+This is an unused offset to the parameters for each feature
+
+=item LOOKUPS
+
+This is an array containing indices to lookups in the LOOKUP instance variable of the table
+
+=item INDEX
+
+This gives the feature index for this feature and is used during reading and writing for
+converting between feature tag and feature index.
+
+=back
+
+=item LOOKUP
+
+This variable is an array of lookups in order and is indexed via the features of a language of a
+script. Each lookup contains subtables and other information:
+
+=over 8
+
+=item OFFSET
+
+This name is preceeded by a space and contains the offset from the start of the table to this
+particular lookup
+
+=item TYPE
+
+This is a subclass specific type for a lookup. It stipulates the type of lookup and hence subtables
+within the lookup
+
+=item FLAG
+
+Holds the lookup flag bits
+
+=item SUB
+
+This holds an array of subtables which are subclass specific. Each subtable must have
+an OFFSET. The other variables described here are an abstraction used in both the
+GSUB and GPOS tables which are the target subclasses of this class.
+
+=over 12
+
+=item OFFSET
+
+This is preceeded by a space and gives the offset relative to the start of the table for this
+subtable
+
+=item FORMAT
+
+Gives the sub-table sub format for this GSUB subtable. It is assumed that this
+value is correct when it comes time to write the subtable.
+
+=item COVERAGE
+
+Most lookups consist of a coverage table corresponding to the first
+glyph to match. The offset of this coverage table is stored here and the coverage
+table looked up against the GSUB table proper. There are two lookups
+without this initial coverage table which is used to index into the RULES array.
+These lookups have one element in the RULES array which is used for the whole
+match.
+
+=item RULES
+
+The rules are a complex array. Each element of the array corresponds to an
+element in the coverage table (governed by the coverage index). If there is
+no coverage table, then there is considered to be only one element in the rules
+array. Each element of the array is itself an array corresponding to the
+possibly multiple string matches which may follow the initial glyph. Each
+element of this array is a hash with fixed keys corresponding to information
+needed to match a glyph string or act upon it. Thus the RULES element is an
+array of arrays of hashes which contain the following keys:
+
+=over 16
+
+=item MATCH
+
+This contains a sequence of elements held as an array. The elements may be
+glyph ids (gid), class ids (cids), or offsets to coverage tables. Each element
+corresponds to one glyph in the glyph string. See MATCH_TYPE for details of
+how the different element types are marked.
+
+=item PRE
+
+This array holds the sequence of elements preceeding the first match element
+and has the same form as the MATCH array.
+
+=item POST
+
+This array holds the sequence of elements to be tested for following the match
+string and is of the same form as the MATCH array.
+
+=item ACTION
+
+This array holds information regarding what should be done if a match is found.
+The array may either hold glyph ids (which are used to replace or insert or
+whatever glyphs in the glyph string) or 2 element arrays consisting of:
+
+=over 20
+
+=item OFFSET
+
+Offset from the start of the matched string that the lookup should start at
+when processing the substring.
+
+=item LOOKUP_INDEX
+
+The index to a lookup to be acted upon on the match string.
+
+=back
+
+=back
+
+=back
+
+=back
+
+=item CLASS
+
+For those lookups which use class categories rather than glyph ids for matching
+this is the offset to the class definition used to categories glyphs in the
+match string.
+
+=item PRE_CLASS
+
+This is the offset to the class definition for the before match glyphs
+
+=item POST_CLASS
+
+This is the offset to the class definition for the after match glyphs.
+
+=item ACTION_TYPE
+
+This string holds the type of information held in the ACTION variable of a RULE.
+It is subclass specific.
+
+=item MATCH_TYPE
+
+This holds the type of information in the MATCH array of a RULE. This is subclass
+specific.
+
+=item ADJUST
+
+This corresponds to a single action for all items in a coverage table. The meaning
+is subclass specific.
+
+=item CACHE
+
+This key starts with a space
+
+A hash of other tables (such as coverage tables, classes, anchors, device tables)
+based on the offset given in the subtable to that other information.
+Note that the documentation is particularly
+unhelpful here in that such tables are given as offsets relative to the
+beginning of the subtable not the whole GSUB table. This includes those items which
+are stored relative to another base within the subtable.
+
+=back
+
+
+=head1 METHODS
+
+=cut
+
+use Font::TTF::Table;
+use Font::TTF::Utils;
+use Font::TTF::Coverage;
+use strict;
+use vars qw(@ISA);
+
+ at ISA = qw(Font::TTF::Table);
+
+=head2 $t->read
+
+Reads the table passing control to the subclass to handle the subtable specifics
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat, $i, $l, $oScript, $oFeat, $oLook, $tag, $nScript, $off, $dLang, $nLang, $lTag);
+    my ($nFeat, $nLook, $nSub, $j, $temp);
+    my ($fh) = $self->{' INFILE'};
+    my ($moff) = $self->{' OFFSET'};
+
+    $self->SUPER::read or return $self;
+    $fh->read($dat, 10);
+    ($self->{'Version'}, $oScript, $oFeat, $oLook) = TTF_Unpack("fSSS", $dat);
+
+# read features first so that in the script/lang hierarchy we can use feature tags
+
+    $fh->seek($moff + $oFeat, 0);
+    $fh->read($dat, 2);
+    $nFeat = unpack("n", $dat);
+    $self->{'FEATURES'} = {};
+    $l = $self->{'FEATURES'};
+    $fh->read($dat, 6 * $nFeat);
+    for ($i = 0; $i < $nFeat; $i++)
+    {
+    	($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
+    	while (defined $l->{$tag})
+    	{
+    	    if ($tag =~ m/(.*?)\s_(\d+)$/o)
+    	    { $tag = $1 . " _" . ($2 + 1); }
+    	    else
+    	    { $tag .= " _0"; }
+    	}
+	    $l->{$tag}{' OFFSET'} = $off + $oFeat;
+	    $l->{$tag}{'INDEX'} = $i;
+	    push (@{$l->{'FEAT_TAGS'}}, $tag);
+    }
+
+    foreach $tag (grep {length($_) == 4} keys %$l)
+    {
+	    $fh->seek($moff + $l->{$tag}{' OFFSET'}, 0);
+    	$fh->read($dat, 4);
+	    ($l->{$tag}{'PARMS'}, $nLook) = unpack("n2", $dat);
+    	$fh->read($dat, $nLook * 2);
+	    $l->{$tag}{'LOOKUPS'} = [unpack("n*", $dat)];
+    }
+
+# Now the script/lang hierarchy
+
+    $fh->seek($moff + $oScript, 0);
+    $fh->read($dat, 2);
+    $nScript = unpack("n", $dat);
+    $self->{'SCRIPTS'} = {};
+    $l = $self->{'SCRIPTS'};
+    $fh->read($dat, 6 * $nScript);
+    for ($i = 0; $i < $nScript; $i++)
+    {
+    	($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
+    	$off += $oScript;
+        foreach (keys %$l)
+        { $l->{$tag}{' REFTAG'} = $_ if ($l->{$_}{' OFFSET'} == $off
+                                        && !defined $l->{$_}{' REFTAG'}); }
+	    $l->{$tag}{' OFFSET'} = $off;
+    }
+
+    foreach $tag (keys %$l)
+    {
+        next if ($l->{$tag}{' REFTAG'});
+    	$fh->seek($moff + $l->{$tag}{' OFFSET'}, 0);
+    	$fh->read($dat, 4);
+    	($dLang, $nLang) = unpack("n2", $dat);
+    	$l->{$tag}{'DEFAULT'}{' OFFSET'} =
+    	        $dLang + $l->{$tag}{' OFFSET'} if $dLang;
+    	$fh->read($dat, 6 * $nLang);
+    	for ($i = 0; $i < $nLang; $i++)
+    	{
+    	    ($lTag, $off) = unpack("a4n", substr($dat, $i * 6, 6));
+    	    $off += $l->{$tag}{' OFFSET'};
+    	    $l->{$tag}{$lTag}{' OFFSET'} = $off;
+            foreach (@{$l->{$tag}{'LANG_TAGS'}})
+            { $l->{$tag}{$lTag}{' REFTAG'} = $_ if ($l->{$tag}{$_}{' OFFSET'} == $off
+                                                   && !$l->{$tag}{$_}{' REFTAG'}); }
+    	    push (@{$l->{$tag}{'LANG_TAGS'}}, $lTag);
+    	}
+    	foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT')
+    	{
+    	    next unless defined $l->{$tag}{$lTag};
+            next if ($l->{$tag}{$lTag}{' REFTAG'});
+    	    $fh->seek($moff + $l->{$tag}{$lTag}{' OFFSET'}, 0);
+    	    $fh->read($dat, 6);
+    	    ($l->{$tag}{$lTag}{'RE-ORDER'}, $l->{$tag}{$lTag}{'DEFAULT'}, $nFeat) 
+    	      = unpack("n3", $dat);
+    	    $fh->read($dat, $nFeat * 2);
+    	    $l->{$tag}{$lTag}{'FEATURES'} = [map {$self->{'FEATURES'}{'FEAT_TAGS'}[$_]} unpack("n*", $dat)];
+    	}
+    	foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT')
+    	{
+       	    next unless $l->{$tag}{$lTag}{' REFTAG'};
+    	    $temp = $l->{$tag}{$lTag}{' REFTAG'};
+    	    $l->{$tag}{$lTag} = &copy($l->{$tag}{$temp});
+    	    $l->{$tag}{$lTag}{' REFTAG'} = $temp;
+    	}
+    }
+    foreach $tag (keys %$l)
+    {
+        next unless $l->{$tag}{' REFTAG'};
+        $temp = $l->{$tag}{' REFTAG'};
+        $l->{$tag} = &copy($l->{$temp});
+        $l->{$tag}{' REFTAG'} = $temp;
+    }
+
+# And finally the lookups
+
+    $fh->seek($moff + $oLook, 0);
+    $fh->read($dat, 2);
+    $nLook = unpack("n", $dat);
+    $fh->read($dat, $nLook * 2);
+    $i = 0;
+    map { $self->{'LOOKUP'}[$i++]{' OFFSET'} = $_; } unpack("n*", $dat);
+
+    for ($i = 0; $i < $nLook; $i++)
+    {
+    	$l = $self->{'LOOKUP'}[$i];
+    	$fh->seek($l->{' OFFSET'} + $moff + $oLook, 0);
+    	$fh->read($dat, 6);
+    	($l->{'TYPE'}, $l->{'FLAG'}, $nSub) = unpack("n3", $dat);
+    	$fh->read($dat, $nSub * 2);
+    	$j = 0;
+    	map { $l->{'SUB'}[$j]{' OFFSET'} = $_; } unpack("n*", $dat);
+    	for ($j = 0; $j < $nSub; $j++)
+    	{
+    	    $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0);
+	        $self->read_sub($fh, $l, $j);
+	    }
+    }
+    return $self;
+}
+
+=head2 $t->read_sub($fh, $lookup, $index)
+
+This stub is to allow subclasses to read subtables of lookups in a table specific manner. A
+reference to the lookup is passed in along with the subtable index. The file is located at the
+start of the subtable to be read
+
+=cut
+
+sub read_sub
+{ }
+
+
+=head2 $t->extension()
+
+Returns the lookup number for the extension table that allows access to 32-bit offsets.
+
+=cut
+
+sub extension
+{ }
+
+
+=head2 $t->out($fh)
+
+Writes this Opentype table to the output calling $t->out_sub for each sub table
+at the appropriate point in the output. The assumption is that on entry the
+number of scripts, languages, features, lookups, etc. are all resolved and
+the relationships fixed. This includes a script's LANG_TAGS list and that all
+scripts and languages in their respective dictionaries either have a REFTAG or contain
+real data.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($i, $j, $base, $off, $tag, $t, $l, $lTag, $oScript, @script, @tags);
+    my ($end, $nTags, @offs, $oFeat, $oLook, $nSub, $nSubs, $big);
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+# First sort the features
+    $i = 0;
+    $self->{'FEATURES'}{'FEAT_TAGS'} = [sort grep {length($_) == 4 || m/\s_\d+$/o} %{$self->{'FEATURES'}}]
+            if (!defined $self->{'FEATURES'}{'FEAT_TAGS'});
+    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
+    { $self->{'FEATURES'}{$t}{'INDEX'} = $i++; }
+
+    $base = $fh->tell();
+    $fh->print(TTF_Pack("f", $self->{'Version'}));
+    $fh->print(pack("n3", 10, 0, 0));
+    $oScript = $fh->tell() - $base;
+    @script = sort grep {length($_) == 4} keys %{$self->{'SCRIPTS'}};
+    $fh->print(pack("n", $#script + 1));
+    foreach $t (@script)
+    { $fh->print(pack("a4n", $t, 0)); }
+
+    $end = $fh->tell();
+    foreach $t (@script)
+    {
+        $fh->seek($end, 0);
+        $tag = $self->{'SCRIPTS'}{$t};
+        next if ($tag->{' REFTAG'});
+    	$tag->{' OFFSET'} = tell($fh) - $base - $oScript;
+    	$fh->print(pack("n2", 0, $#{$tag->{'LANG_TAGS'}} + 1));
+    	foreach $lTag (sort @{$tag->{'LANG_TAGS'}})
+    	{ $fh->print(pack("a4n", $lTag, 0)); }
+    	foreach $lTag (@{$tag->{'LANG_TAGS'}}, 'DEFAULT')
+    	{
+    	    my ($def);
+    	    $l = $tag->{$lTag};
+    	    next if (!defined $l || $l->{' REFTAG'} ne '');
+    	    $l->{' OFFSET'} = tell($fh) - $base - $oScript - $tag->{' OFFSET'};
+    	    if (defined $l->{'DEFAULT'})
+#    	    { $def = $self->{'FEATURES'}{$l->{'FEATURES'}[$l->{'DEFAULT'}]}{'INDEX'}; }
+            { $def = $l->{'DEFAULT'}; }
+    	    else
+    	    { $def = -1; }
+    	    $fh->print(pack("n*", $l->{'RE_ORDER'}, $def, $#{$l->{'FEATURES'}} + 1,
+    	            map {$self->{'FEATURES'}{$_}{'INDEX'}} @{$l->{'FEATURES'}}));
+    	}
+    	$end = $fh->tell();
+    	if ($tag->{'DEFAULT'}{' REFTAG'} || defined $tag->{'DEFAULT'}{'FEATURES'})
+    	{
+        	$fh->seek($base + $oScript + $tag->{' OFFSET'}, 0);
+        	$off = $tag->{'DEFAULT'}{' REFTAG'} ?
+        	        $tag->{$tag->{'DEFAULT'}{' REFTAG'}}{' OFFSET'} :
+        	        $tag->{'DEFAULT'}{' OFFSET'};
+        	$fh->print(pack("n", $off));
+    	}
+    	$fh->seek($base + $oScript + $tag->{' OFFSET'} + 4, 0);
+    	foreach (sort @{$tag->{'LANG_TAGS'}})
+    	{
+    	    $off = $tag->{$_}{' REFTAG'} ? $tag->{$tag->{$_}{' REFTAG'}}{' OFFSET'} :
+    	            $tag->{$_}{' OFFSET'};
+    	    $fh->print(pack("a4n", $_, $off));
+    	}
+    }
+    $fh->seek($base + $oScript + 2, 0);
+    foreach $t (@script)
+    {
+        $tag = $self->{'SCRIPTS'}{$t};
+        $off = $tag->{' REFTAG'} ? $tag->{$tag->{' REFTAG'}}{' OFFSET'} : $tag->{' OFFSET'};
+        $fh->print(pack("a4n", $t, $off));
+    }
+
+    $fh->seek($end, 0);
+    $oFeat = $end - $base;
+    $nTags = $#{$self->{'FEATURES'}{'FEAT_TAGS'}} + 1;
+    $fh->print(pack("n", $nTags));
+    $fh->print(pack("a4n", "    ", 0) x $nTags);
+    
+    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
+    {
+        $tag = $self->{'FEATURES'}{$t};
+        $tag->{' OFFSET'} = tell($fh) - $base - $oFeat;
+        $fh->print(pack("n*", 0, $#{$tag->{'LOOKUPS'}} + 1, @{$tag->{'LOOKUPS'}}));
+    }
+    $end = $fh->tell();
+    $fh->seek($oFeat + $base + 2, 0);
+    foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}})
+    { $fh->print(pack("a4n", $t, $self->{'FEATURES'}{$t}{' OFFSET'})); }
+
+    undef $big;
+    $fh->seek($end, 0);
+    $oLook = $end - $base;
+    
+    # Start Lookup List Table
+    $nTags = $#{$self->{'LOOKUP'}} + 1;
+    $fh->print(pack("n", $nTags));
+    $fh->print(pack("n", 0) x $nTags);
+    $end = $fh->tell();		# end of LookupListTable = start of Lookups
+    foreach $tag (@{$self->{'LOOKUP'}})
+    { $nSubs += $self->num_sub($tag); }
+    for ($i = 0; $i < $nTags; $i++)
+    {
+        $fh->seek($end, 0);
+        $tag = $self->{'LOOKUP'}[$i];
+        $off = $end - $base - $oLook;	# BH 2004-03-04
+        # Is there room, from the start of this i'th lookup, for this and the remaining
+        # lookups to be wrapped in extension lookups?
+        if (!defined $big && $off + ($nTags - $i) * 6 + $nSubs * 10 > 65535) # BH 2004-03-04
+        {
+			# Not enough room -- need to start an extension!            
+            my ($k, $ext);
+            $ext = $self->extension();
+            # Must turn previous lookup into the first extension
+            $i--;
+            $tag = $self->{'LOOKUP'}[$i];
+            $end = $tag->{' OFFSET'} + $base + $oLook;
+            $fh->seek($end, 0);
+            $big = $i;
+            # For this and the remaining lookups, build extensions lookups
+            for ($j = $i; $j < $nTags; $j++)
+            {
+                $tag = $self->{'LOOKUP'}[$j];
+                $nSub = $self->num_sub($tag);
+                $fh->print(pack("nnn", $ext, $tag->{'FLAG'}, $nSub));
+                $fh->print(pack("n*", map {$_ * 8 + 6 + $nSub * 2} (0 .. $nSub-1)));	# BH 2004-03-04
+                $tag->{' EXT_OFFSET'} = $fh->tell();	# = first extension lookup subtable
+                $tag->{' OFFSET'} = $tag->{' EXT_OFFSET'} - $nSub * 2 - 6 - $base - $oLook; # offset to this extension lookup
+                for ($k = 0; $k < $nSub; $k++)
+                { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, 0)); }
+            }
+            
+            $tag = $self->{'LOOKUP'}[$i];
+            # Leave file positioned after all the extension lookups -- where the referenced lookups will start.
+        }
+        $tag->{' OFFSET'} = $off unless defined $big;	# BH 2004-03-04
+        $nSub = $self->num_sub($tag);
+        if (!defined $big)
+        {
+            $fh->print(pack("nnn", $tag->{'TYPE'}, $tag->{'FLAG'}, $nSub));
+            $fh->print(pack("n", 0) x $nSub);
+        }
+        else
+        { $end = $tag->{' EXT_OFFSET'}; }
+        @offs = ();
+        for ($j = 0; $j < $nSub; $j++)
+        {
+            push(@offs, tell($fh) - $end);
+            $self->out_sub($fh, $tag, $j);
+        }
+        $end = $fh->tell();
+        if (!defined $big)
+        {
+            $fh->seek($tag->{' OFFSET'} + $base + $oLook + 6, 0);
+            $fh->print(pack("n*", @offs));
+        }
+        else
+        {
+            $fh->seek($tag->{' EXT_OFFSET'}, 0);
+            for ($j = 0; $j < $nSub; $j++)
+            { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, $offs[$j] - $j * 8)); }
+        }
+    }
+    $fh->seek($oLook + $base + 2, 0);
+    $fh->print(pack("n*", map {$self->{'LOOKUP'}[$_]{' OFFSET'}} (0 .. $nTags - 1)));
+    $fh->seek($base + 6, 0);
+    $fh->print(pack('n2', $oFeat, $oLook));
+    $fh->seek($end, 0);
+    $self;
+}
+
+
+=head2 $t->num_sub($lookup)
+
+Asks the subclass to count the number of subtables for a particular lookup and to
+return that value. Used in out().
+
+=cut
+
+sub num_sub
+{
+    my ($self, $lookup) = @_;
+
+    return $#{$lookup->{'SUB'}} + 1;
+}
+
+
+=head2 $t->out_sub($fh, $lookup, $index)
+
+This stub is to allow subclasses to output subtables of lookups in a table specific manner. A
+reference to the lookup is passed in along with the subtable index. The file is located at the
+start of the subtable to be output
+
+=cut
+
+sub out_sub
+{ }
+
+
+=head1 Internal Functions & Methods
+
+Most of these methods are used by subclasses for handling such things as coverage
+tables.
+
+=head2 copy($ref)
+
+Internal function to copy the top level of a dictionary to create a new dictionary.
+Only the top level is copied.
+
+=cut
+
+sub copy
+{
+    my ($ref) = @_;
+    my ($res) = {};
+
+    foreach (keys %$ref)
+    { $res->{$_} = $ref->{$_}; }
+    $res;
+}
+
+
+=head2 $t->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover)
+
+Reads a coverage table and stores the results in $lookup->{' CACHE'}, that is, if
+it hasn't been read already.
+
+=cut
+
+sub read_cover
+{
+    my ($self, $offset, $base, $lookup, $fh, $is_cover) = @_;
+    my ($loc) = $fh->tell();
+    my ($cover, $str);
+
+    return undef unless $offset;
+    $str = sprintf("%X", $base + $offset);
+    return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str};
+    $fh->seek($base + $offset, 0);
+    $cover = Font::TTF::Coverage->new($is_cover)->read($fh);
+    $fh->seek($loc, 0);
+    $lookup->{' CACHE'}{$str} = $cover;
+    return $cover;
+}
+
+
+=head2 ref_cache($obj, $cache, $offset)
+
+Internal function to keep track of the local positioning of subobjects such as
+coverage and class definition tables, and their offsets.
+What happens is that the cache is a hash of
+sub objects indexed by the reference (using a string mashing of the
+reference name which is valid for the duration of the reference) and holds a
+list of locations in the output string which should be filled in with the
+offset to the sub object when the final string is output in out_final.
+
+Uses tricks for Tie::Refhash
+
+=cut
+
+sub ref_cache
+{
+    my ($obj, $cache, $offset) = @_;
+
+    return 0 unless defined $obj;
+    $cache->{"$obj"}[0] = $obj unless defined $cache->{"$obj"};
+    push (@{$cache->{"$obj"}[1]}, $offset);
+    return 0;
+}
+
+
+=head2 out_final($fh, $out, $cache_list, $state)
+
+Internal function to actually output everything to the file handle given that
+now we know the offset to the first sub object to be output and which sub objects
+are to be output and what locations need to be updated, we can now
+generate everything. $cache_list is an array of two element arrays. The first element
+is a cache object, the second is an offset to be subtracted from each reference
+to that object made in the cache.
+
+If $state is 1, then the output is not sent to the filehandle and the return value
+is the string to be output. If $state is absent or 0 then output is not limited
+by storing in a string first and the return value is "";
+
+=cut
+
+sub out_final
+{
+    my ($fh, $out, $cache_list, $state) = @_;
+    my ($len) = length($out);
+    my ($base_loc) = $state ? 0 : $fh->tell();
+    my ($loc, $t, $r, $s, $master_cache, $offs, $str);
+
+    $fh->print($out) unless $state;       # first output the current attempt
+    foreach $r (@$cache_list)
+    {
+        $offs = $r->[1];
+        foreach $t (sort keys %{$r->[0]})
+        {
+            $str = "$t";
+            if (!defined $master_cache->{$str})
+            {
+                $master_cache->{$str} = ($state ? length($out) : $fh->tell())
+                                                            - $base_loc;
+                if ($state)
+                { $out .= $r->[0]{$str}[0]->out($fh, 1); }
+                else
+                { $r->[0]{$str}[0]->out($fh, 0); }
+            }
+            foreach $s (@{$r->[0]{$str}[1]})
+            { substr($out, $s, 2) = pack('n', $master_cache->{$str} - $offs); }
+        }
+    }
+    if ($state)
+    { return $out; }
+    else
+    {
+        $loc = $fh->tell();
+        $fh->seek($base_loc, 0);
+        $fh->print($out);       # the corrected version
+        $fh->seek($loc, 0);
+    }
+}
+
+
+=head2 $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc)
+
+Internal method to read context (simple and chaining context) lookup subtables for
+the GSUB and GPOS table types. The assumed values for $type correspond to those
+for GSUB, so GPOS should adjust the values upon calling.
+
+=cut
+
+sub read_context
+{
+    my ($self, $lookup, $fh, $type, $fmt, $cover, $count, $loc) = @_;
+    my ($dat, $i, $s, $t, @subst, @srec, $mcount, $scount);
+    
+    if ($type == 5 && $fmt < 3)
+    {
+        if ($fmt == 2)
+        {
+            $fh->read($dat, 2);
+            $lookup->{'CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0);
+            $count = TTF_Unpack('S', $dat);
+        }
+        $fh->read($dat, $count << 1);
+        foreach $s (TTF_Unpack('S*', $dat))
+        {
+            if ($s == 0)
+            {
+                push (@{$lookup->{'RULES'}}, []);
+                next;
+            }
+            @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);
+                @srec = ();
+                $fh->read($dat, 4);
+                ($mcount, $scount) = TTF_Unpack('S2', $dat);
+                $mcount--;
+                $fh->read($dat, ($mcount << 1) + ($scount << 2));
+                for ($i = 0; $i < $scount; $i++)
+                { push (@srec, [TTF_Unpack('S2', substr($dat,
+                    ($mcount << 1) + ($i << 2), 4))]); }
+                push (@subst, {'ACTION' => [@srec],
+                               'MATCH' => [TTF_Unpack('S*',
+                                    substr($dat, 0, $mcount << 1))]});
+            }
+            push (@{$lookup->{'RULES'}}, [@subst]);
+        }
+        $lookup->{'ACTION_TYPE'} = 'l';
+        $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g');
+    } elsif ($type == 5 && $fmt == 3)
+    {
+        $fh->read($dat, ($cover << 1) + ($count << 2));
+        @subst = (); @srec = ();
+        for ($i = 0; $i < $cover; $i++)
+        { push (@subst, $self->read_cover(TTF_Unpack('S', substr($dat, $i << 1, 2)),
+                                $loc, $lookup, $fh, 1)); }
+        for ($i = 0; $i < $count; $i++)
+        { push (@srec, [TTF_Unpack('S2', substr($dat, ($count << 1) + ($i << 2), 4))]); }
+        $lookup->{'RULES'} = [[{'ACTION' => [@srec], 'MATCH' => [@subst]}]];
+        $lookup->{'ACTION_TYPE'} = 'l';
+        $lookup->{'MATCH_TYPE'} = 'o';
+    } elsif ($type == 6 && $fmt < 3)
+    {
+        if ($fmt == 2)
+        {
+            $fh->read($dat, 6);
+            $lookup->{'PRE_CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0) if $count;
+            ($i, $mcount, $count) = TTF_Unpack('S3', $dat);     # messy: 2 classes & count
+            $lookup->{'CLASS'} = $self->read_cover($i, $loc, $lookup, $fh, 0) if $i;
+            $lookup->{'POST_CLASS'} = $self->read_cover($mcount, $loc, $lookup, $fh, 0) if $mcount;
+        }
+        $fh->read($dat, $count << 1);
+        foreach $s (TTF_Unpack('S*', $dat))
+        {
+            if ($s == 0)
+            {
+                push (@{$lookup->{'RULES'}}, []);
+                next;
+            }
+            @subst = ();
+            $fh->seek($loc + $s, 0);
+            $fh->read($dat, 2);
+            $t = TTF_Unpack('S', $dat);
+            $fh->read($dat, $t << 1);
+            foreach $i (TTF_Unpack('S*', $dat))
+            {
+                $fh->seek($loc + $s + $i, 0);
+                @srec = ();
+                $t = {};
+                $fh->read($dat, 2);
+                $mcount = TTF_Unpack('S', $dat);
+                if ($mcount > 0)
+                {
+                    $fh->read($dat, $mcount << 1);
+                    $t->{'PRE'} = [TTF_Unpack('S*', $dat)];
+                }
+                $fh->read($dat, 2);
+                $mcount = TTF_Unpack('S', $dat);
+                if ($mcount > 1)
+                {
+                    $fh->read($dat, ($mcount - 1) << 1);
+                    $t->{'MATCH'} = [TTF_Unpack('S*', $dat)];
+                }
+                $fh->read($dat, 2);
+                $mcount = TTF_Unpack('S', $dat);
+                if ($mcount > 0)
+                {
+                    $fh->read($dat, $mcount << 1);
+                    $t->{'POST'} = [TTF_Unpack('S*', $dat)];
+                }
+                $fh->read($dat, 2);
+                $scount = TTF_Unpack('S', $dat);
+                $fh->read($dat, $scount << 2);
+                for ($i = 0; $i < $scount; $i++)
+                { push (@srec, [TTF_Unpack('S2', substr($dat, $i << 2))]); }
+                $t->{'ACTION'} = [@srec];
+                push (@subst, $t);
+            }
+            push (@{$lookup->{'RULES'}}, [@subst]);
+        }
+        $lookup->{'ACTION_TYPE'} = 'l';
+        $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g');
+    } elsif ($type == 6 && $fmt == 3)
+    {
+        $t = {};
+        unless ($cover == 0)
+        {
+            @subst = ();
+            $fh->read($dat, $cover << 1);
+            foreach $s (TTF_Unpack('S*', $dat))
+            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
+            $t->{'PRE'} = [@subst];
+        }
+        $fh->read($dat, 2);
+        $count = TTF_Unpack('S', $dat);
+        unless ($count == 0)
+        {
+            @subst = ();
+            $fh->read($dat, $count << 1);
+            foreach $s (TTF_Unpack('S*', $dat))
+            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
+            $t->{'MATCH'} = [@subst];
+        }
+        $fh->read($dat, 2);
+        $count = TTF_Unpack('S', $dat);
+        unless ($count == 0)
+        {
+            @subst = ();
+            $fh->read($dat, $count << 1);
+            foreach $s (TTF_Unpack('S*', $dat))
+            { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); }
+            $t->{'POST'} = [@subst];
+        }
+        $fh->read($dat, 2);
+        $count = TTF_Unpack('S', $dat);
+        @subst = ();
+        $fh->read($dat, $count << 2);
+        for ($i = 0; $i < $count; $i++)
+        { push (@subst, [TTF_Unpack('S2', substr($dat, $i << 2, 4))]); }
+        $t->{'ACTION'} = [@subst];
+        $lookup->{'RULES'} = [[$t]];
+        $lookup->{'ACTION_TYPE'} = 'l';
+        $lookup->{'MATCH_TYPE'} = 'o';
+    }
+    $lookup;
+}
+
+
+=head2 $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num)
+
+Provides shared behaviour between GSUB and GPOS tables during output for context
+(chained and simple) rules. In addition, support is provided here for type 4 GSUB
+tables, which are not used in GPOS. The value for $type corresponds to the type
+in a GSUB table so calling from GPOS should adjust the value accordingly.
+
+=cut
+
+sub out_context
+{
+    my ($self, $lookup, $fh, $type, $fmt, $ctables, $out, $num) = @_;
+    my ($offc, $offd, $i, $j, $r, $t, $numd);
+
+    if (($type == 4 || $type == 5 || $type == 6) && ($fmt == 1 || $fmt == 2))
+    {
+        my ($base_off);
+        
+        if ($fmt == 1)
+        {
+            $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            $num);
+            $base_off = 6;
+        } elsif ($type == 5)
+        {
+            $out = pack("nnnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                            Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 4), $num);
+            $base_off = 8;
+        } elsif ($type == 6)
+        {
+            $out = pack("n6", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2),
+                                Font::TTF::Ttopen::ref_cache($lookup->{'PRE_CLASS'}, $ctables, 4),
+                                Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 6),
+                                Font::TTF::Ttopen::ref_cache($lookup->{'POST_CLASS'}, $ctables, 8),
+                                $num);
+            $base_off = 12;
+        }
+
+        $out .= pack('n*', (0) x $num);
+        $offc = length($out);
+        for ($i = 0; $i < $num; $i++)
+        {
+            $r = $lookup->{'RULES'}[$i];
+            next unless exists $r->[0]{'ACTION'};
+            $numd = $#{$r} + 1;
+            substr($out, ($i << 1) + $base_off, 2) = pack('n', $offc);
+            $out .= pack('n*', $numd, (0) x $numd);
+            $offd = length($out) - $offc;
+            for ($j = 0; $j < $numd; $j++)
+            {
+                substr($out, $offc + 2 + ($j << 1), 2) = pack('n', $offd);
+                if ($type == 4)
+                {
+                    $out .= pack('n*', $r->[$j]{'ACTION'}[0], $#{$r->[$j]{'MATCH'}} + 2,
+                                        @{$r->[$j]{'MATCH'}});
+                } elsif ($type == 5)
+                {
+                    $out .= pack('n*', $#{$r->[$j]{'MATCH'}} + 2,
+                                        $#{$r->[$j]{'ACTION'}} + 1,
+                                        @{$r->[$j]{'MATCH'}});
+                    foreach $t (@{$r->[$j]{'ACTION'}})
+                    { $out .= pack('n2', @$t); }
+                } elsif ($type == 6)
+                {
+                    $out .= pack('n*', $#{$r->[$j]{'PRE'}} + 1, @{$r->[$j]{'PRE'}},
+                                    $#{$r->[$j]{'MATCH'}} + 2, @{$r->[$j]{'MATCH'}},
+                                    $#{$r->[$j]{'POST'}} + 1, @{$r->[$j]{'POST'}},
+                                    $#{$r->[$j]{'ACTION'}} + 1);
+                    foreach $t (@{$r->[$j]{'ACTION'}})
+                    { $out .= pack('n2', @$t); }
+                }
+                $offd = length($out) - $offc;
+            }
+            $offc = length($out);
+        }
+    } elsif ($type == 5 && $fmt == 3)
+    {
+        $out .= pack('n3', $fmt, $#{$lookup->{'RULES'}[0][0]{'MATCH'}} + 1,
+                                $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1);
+        foreach $t (@{$lookup->{'RULES'}[0][0]{'MATCH'}})
+        { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out))); }
+        foreach $t (@{$lookup->{'RULES'}[0][0]{'ACTION'}})
+        { $out .= pack('n2', @$t); }
+    } elsif ($type == 6 && $fmt == 3)
+    {
+        $r = $lookup->{'RULES'}[0][0];
+        $out .= pack('n2', $fmt, $#{$r->{'PRE'}} + 1);
+        foreach $t (@{$r->{'PRE'}})
+        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
+        $out .= pack('n', $#{$r->{'MATCH'}} + 1);
+        foreach $t (@{$r->{'MATCH'}})
+        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
+        $out .= pack('n', $#{$r->{'POST'}} + 1);
+        foreach $t (@{$r->{'POST'}})
+        { $out .= Font::TTF::Ttopen::ref_cache($t, $ctables, length($out)); }
+        $out .= pack('n', $#{$r->{'ACTION'}} + 1);
+        foreach $t (@{$r->{'ACTION'}})
+        { $out .= pack('n2', @$t); }
+    }
+    $out;
+}
+
+=head1 BUGS
+
+=over 4
+
+=item *
+
+No way to share cachable items (coverage tables, classes, anchors, device tables)
+across different lookups. The items are always output after the lookup and
+repeated if necessary. Within lookup sharing is possible.
+
+=back
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+
+1;
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Useall.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Useall.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Useall.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,52 +1,52 @@
-use Font::TTF::Cvt_;
-use Font::TTF::Fpgm;
-use Font::TTF::Glyf;
-use Font::TTF::Hdmx;
-use Font::TTF::Kern;
-use Font::TTF::Loca;
-use Font::TTF::LTSH;
-use Font::TTF::Name;
-use Font::TTF::OS_2;
-use Font::TTF::PCLT;
-use Font::TTF::Post;
-use Font::TTF::Prep;
-use Font::TTF::Vmtx;
-use Font::TTF::AATKern;
-use Font::TTF::AATutils;
-use Font::TTF::Anchor;
-use Font::TTF::Bsln;
-use Font::TTF::Delta;
-use Font::TTF::Fdsc;
-use Font::TTF::Feat;
-use Font::TTF::Fmtx;
-use Font::TTF::GPOS;
-use Font::TTF::Mort;
-use Font::TTF::Prop;
-use Font::TTF::GDEF;
-use Font::TTF::Coverage;
-use Font::TTF::GSUB;
-use Font::TTF::Hhea;
-use Font::TTF::Table;
-use Font::TTF::Ttopen;
-use Font::TTF::Glyph;
-use Font::TTF::Head;
-use Font::TTF::Hmtx;
-use Font::TTF::Vhea;
-use Font::TTF::Cmap;
-use Font::TTF::Utils;
-use Font::TTF::Maxp;
-use Font::TTF::Font;
-use Font::TTF::Kern::ClassArray;
-use Font::TTF::Kern::CompactClassArray;
-use Font::TTF::Kern::OrderedList;
-use Font::TTF::Kern::StateTable;
-use Font::TTF::Kern::Subtable;
-use Font::TTF::Mort::Chain;
-use Font::TTF::Mort::Contextual;
-use Font::TTF::Mort::Insertion;
-use Font::TTF::Mort::Ligature;
-use Font::TTF::Mort::Noncontextual;
-use Font::TTF::Mort::Rearrangement;
-use Font::TTF::Mort::Subtable;
-
-1;
+use Font::TTF::Cvt_;
+use Font::TTF::Fpgm;
+use Font::TTF::Glyf;
+use Font::TTF::Hdmx;
+use Font::TTF::Kern;
+use Font::TTF::Loca;
+use Font::TTF::LTSH;
+use Font::TTF::Name;
+use Font::TTF::OS_2;
+use Font::TTF::PCLT;
+use Font::TTF::Post;
+use Font::TTF::Prep;
+use Font::TTF::Vmtx;
+use Font::TTF::AATKern;
+use Font::TTF::AATutils;
+use Font::TTF::Anchor;
+use Font::TTF::Bsln;
+use Font::TTF::Delta;
+use Font::TTF::Fdsc;
+use Font::TTF::Feat;
+use Font::TTF::Fmtx;
+use Font::TTF::GPOS;
+use Font::TTF::Mort;
+use Font::TTF::Prop;
+use Font::TTF::GDEF;
+use Font::TTF::Coverage;
+use Font::TTF::GSUB;
+use Font::TTF::Hhea;
+use Font::TTF::Table;
+use Font::TTF::Ttopen;
+use Font::TTF::Glyph;
+use Font::TTF::Head;
+use Font::TTF::Hmtx;
+use Font::TTF::Vhea;
+use Font::TTF::Cmap;
+use Font::TTF::Utils;
+use Font::TTF::Maxp;
+use Font::TTF::Font;
+use Font::TTF::Kern::ClassArray;
+use Font::TTF::Kern::CompactClassArray;
+use Font::TTF::Kern::OrderedList;
+use Font::TTF::Kern::StateTable;
+use Font::TTF::Kern::Subtable;
+use Font::TTF::Mort::Chain;
+use Font::TTF::Mort::Contextual;
+use Font::TTF::Mort::Insertion;
+use Font::TTF::Mort::Ligature;
+use Font::TTF::Mort::Noncontextual;
+use Font::TTF::Mort::Rearrangement;
+use Font::TTF::Mort::Subtable;
+
+1;

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Utils.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Utils.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Utils.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,610 +1,610 @@
-package Font::TTF::Utils;
-
-=head1 NAME
-
-Font::TTF::Utils - Utility functions to save fingers
-
-=head1 DESCRIPTION
-
-Lots of useful functions to save my fingers, especially for trivial tables
-
-=head1 FUNCTIONS
-
-The following functions are exported
-
-=cut
-
-use strict;
-use vars qw(@ISA @EXPORT $VERSION @EXPORT_OK);
-require Exporter;
-
- at ISA = qw(Exporter);
- at EXPORT = qw(TTF_Init_Fields TTF_Read_Fields TTF_Out_Fields TTF_Pack
-             TTF_Unpack TTF_word_utf8 TTF_utf8_word TTF_bininfo);
- at EXPORT_OK = (@EXPORT, qw(XML_hexdump));
-$VERSION = 0.0001;
-
-=head2 ($val, $pos) = TTF_Init_Fields ($str, $pos)
-
-Given a field description from the C<DATA> section, creates an absolute entry
-in the fields associative array for the class
-
-=cut
-
-sub TTF_Init_Fields
-{
-    my ($str, $pos, $inval) = @_;
-    my ($key, $val, $res, $len, $rel);
-
-    $str =~ s/\r?\n$//o;
-    if ($inval)
-    { ($key, $val) = ($str, $inval); }
-    else
-    { ($key, $val) = split(',\s*', $str); }
-    return (undef, undef, 0) unless (defined $key && $key ne "");
-    if ($val =~ m/^(\+?)(\d*)(\D+)(\d*)/oi)
-    {
-        $rel = $1;
-        if ($rel eq "+")
-        { $pos += $2; }
-        elsif ($2 ne "")
-        { $pos = $2; }
-        $val = $3;
-        $len = $4;
-    }
-    $len = "" unless defined $len;
-    $pos = 0 if !defined $pos || $pos eq "";
-    $res = "$pos:$val:$len";
-    if ($val eq "f" || $val =~ m/^[l]/oi)
-    { $pos += 4 * ($len ne "" ? $len : 1); }
-    elsif ($val eq "F" || $val =~ m/^[s]/oi)
-    { $pos += 2 * ($len ne "" ? $len : 1); }
-    else
-    { $pos += 1 * ($len ne "" ? $len : 1); }
-
-    ($key, $res, $pos);
-}
-
-
-=head2 TTF_Read_Fields($obj, $dat, $fields)
-
-Given a block of data large enough to account for all the fields in a table,
-processes the data block to convert to the values in the objects instance
-variables by name based on the list in the C<DATA> block which has been run
-through C<TTF_Init_Fields>
-
-=cut
-
-sub TTF_Read_Fields
-{
-    my ($self, $dat, $fields) = @_;
-    my ($pos, $type, $res, $f, $arrlen, $arr, $frac);
-
-    foreach $f (keys %{$fields})
-    {
-        ($pos, $type, $arrlen) = split(':', $fields->{$f});
-        $pos = 0 if $pos eq "";
-        if ($arrlen ne "")
-        { $self->{$f} = [TTF_Unpack("$type$arrlen", substr($dat, $pos))]; }
-        else
-        { $self->{$f} = TTF_Unpack("$type", substr($dat, $pos)); }
-    }
-    $self;
-}
-
-
-=head2 TTF_Unpack($fmt, $dat)
-
-A TrueType types equivalent of Perls C<unpack> function. Thus $fmt consists of
-type followed by an optional number of elements to read including *. The type
-may be one of:
-
-    c       BYTE
-    C       CHAR
-    f       FIXED
-    F       F2DOT14
-    l       LONG
-    L       ULONG
-    s       SHORT
-    S       USHORT
-
-Note that C<FUNIT>, C<FWORD> and C<UFWORD> are not data types but units.
-
-Returns array of scalar (first element) depending on context
-
-=cut
-
-sub TTF_Unpack
-{
-    my ($fmt, $dat) = @_;
-    my ($res, $frac, $i, $arrlen, $type, @res);
-
-    while ($fmt =~ s/^([cfls])(\d+|\*)?//oi)
-    {
-        $type = $1;
-        $arrlen = $2;
-        $arrlen = 1 if !defined $arrlen || $arrlen eq "";
-        $arrlen = -1 if $arrlen eq "*";
-
-        for ($i = 0; ($arrlen == -1 && $dat ne "") || $i < $arrlen; $i++)
-        {
-            if ($type eq "f")
-            {
-                ($res, $frac) = unpack("nn", $dat);
-                substr($dat, 0, 4) = "";
-                $res -= 65536 if $res > 32767;
-                $res += $frac / 65536.;
-            }
-            elsif ($type eq "F")
-            {
-                $res = unpack("n", $dat);
-                substr($dat, 0, 2) = "";
-#                $res -= 65536 if $res >= 32768;
-                $frac = $res & 0x3fff;
-                $res >>= 14;
-                $res -= 4 if $res > 1;
-#                $frac -= 16384 if $frac > 8191;
-                $res += $frac / 16384.;
-            }
-            elsif ($type =~ m/^[l]/oi)
-            {
-                $res = unpack("N", $dat);
-                substr($dat, 0, 4) = "";
-                $res -= (1 << 32) if ($type eq "l" && $res >= 1 << 31);
-            }
-            elsif ($type =~ m/^[s]/oi)
-            {
-                $res = unpack("n", $dat);
-                substr($dat, 0, 2) = "";
-                $res -= 65536 if ($type eq "s" && $res >= 32768);
-            }
-            elsif ($type eq "c")
-            {
-                $res = unpack("c", $dat);
-                substr($dat, 0, 1) = "";
-            }
-            else
-            {
-                $res = unpack("C", $dat);
-                substr($dat, 0, 1) = "";
-            }
-            push (@res, $res);
-        }
-    }
-    return wantarray ? @res : $res[0];
-}
-
-
-=head2 $dat = TTF_Out_Fields($obj, $fields, $len)
-
-Given the fields table from C<TTF_Init_Fields> writes out the instance variables from
-the object to the filehandle in TTF binary form.
-
-=cut
-
-sub TTF_Out_Fields
-{
-    my ($obj, $fields, $len) = @_;
-    my ($dat) = "\000" x $len;
-    my ($f, $pos, $type, $res, $arr, $arrlen, $frac);
-    
-    foreach $f (keys %{$fields})
-    {
-        ($pos, $type, $arrlen) = split(':', $fields->{$f});
-        if ($arrlen ne "")
-        { $res = TTF_Pack("$type$arrlen", @{$obj->{$f}}); }
-        else
-        { $res = TTF_Pack("$type", $obj->{$f}); }
-        substr($dat, $pos, length($res)) = $res;
-    }
-    $dat;
-}
-
-
-=head2 $dat = TTF_Pack($fmt, @data)
-
-The TrueType equivalent to Perl's C<pack> function. See details of C<TTF_Unpack>
-for how to work the $fmt string.
-
-=cut
-
-sub TTF_Pack
-{
-    my ($fmt, @obj) = @_;
-    my ($type, $i, $arrlen, $dat, $res, $frac);
-
-    while ($fmt =~ s/^([flsc])(\d+|\*)?//oi)
-    {
-        $type = $1;
-        $arrlen = $2 || "";
-        $arrlen = $#obj + 1 if $arrlen eq "*";
-        $arrlen = 1 if $arrlen eq "";
-    
-        for ($i = 0; $i < $arrlen; $i++)
-        {
-            $res = shift(@obj);
-            if ($type eq "f")
-            {
-                $frac = int(($res - int($res)) * 65536);
-                $res = (int($res) << 16) + $frac;
-                $dat .= pack("N", $res);
-            }
-            elsif ($type eq "F")
-            {
-                $frac = int(($res - int($res)) * 16384);
-                $res = (int($res) << 14) + $frac;
-                $dat .= pack("n", $res);
-            }
-            elsif ($type =~ m/^[l]/oi)
-            {
-                $res += 1 << 32 if ($type eq 'L' && $res < 0);
-                $dat .= pack("N", $res);
-            }
-            elsif ($type =~ m/^[s]/oi)
-            {
-                $res += 1 << 16 if ($type eq 'S' && $res < 0);
-                $dat .= pack("n", $res);
-            }
-            elsif ($type eq "c")
-            { $dat .= pack("c", $res); }
-            else
-            { $dat .= pack("C", $res); }
-        }
-    }
-    $dat;
-}
-
-
-=head2 ($num, $range, $select, $shift) = TTF_bininfo($num)
-
-Calculates binary search information from a number of elements
-
-=cut
-
-sub TTF_bininfo
-{
-    my ($num, $block) = @_;
-    my ($range, $select, $shift);
-
-    $range = 1;
-    for ($select = 0; $range <= $num; $select++)
-    { $range *= 2; }
-    $select--; $range /= 2;
-    $range *= $block;
-
-    $shift = $num * $block - $range;
-    ($num, $range, $select, $shift);
-}
-
-
-=head2 TTF_word_utf8($str)
-
-Returns the UTF8 form of the 16 bit string, assumed to be in big endian order,
-including surrogate handling
-
-=cut
-
-sub TTF_word_utf8
-{
-    my ($str) = @_;
-    my ($res, $i);
-    my (@dat) = unpack("n*", $str);
-
-    return pack("U*", @dat) if ($^V && $^V ge v5.6.0);
-    for ($i = 0; $i <= $#dat; $i++)
-    {
-        my ($dat) = $dat[$i];
-        if ($dat < 0x80)        # Thanks to Gisle Aas for some of his old code
-        { $res .= chr($dat); }
-        elsif ($dat < 0x800)
-        { $res .= chr(0xC0 | ($dat >> 6)) . chr(0x80 | ($dat & 0x3F)); }
-        elsif ($dat >= 0xD800 && $dat < 0xDC00)
-        {
-            my ($dat1) = $dat[++$i];
-            my ($top) = (($dat & 0x3C0) >> 6) + 1;
-            $res .= chr(0xF0 | ($top >> 2))
-                  . chr(0x80 | (($top & 1) << 4) | (($dat & 0x3C) >> 2))
-                  . chr(0x80 | (($dat & 0x3) << 4) | (($dat1 & 0x3C0) >> 6))
-                  . chr(0x80 | ($dat1 & 0x3F));
-        } else
-        { $res .= chr(0xE0 | ($dat >> 12)) . chr(0x80 | (($dat >> 6) & 0x3F))
-                . chr(0x80 | ($dat & 0x3F)); }
-    }
-    $res;
-}
-
-
-=head2 TTF_utf8_word($str)
-
-Returns the 16-bit form in big endian order of the UTF 8 string, including
-surrogate handling to Unicode.
-
-=cut
-
-sub TTF_utf8_word
-{
-    my ($str) = @_;
-    my ($res);
-
-    return pack("n*", unpack("U*", $str)) if ($^V ge v5.6.0);
-    $str = "$str";              # copy $str
-    while (length($str))        # Thanks to Gisle Aas for some of his old code
-    {
-        $str =~ s/^[\x80-\xBF]+//o;
-        if ($str =~ s/^([\x00-\x7F]+)//o)
-        { $res .= pack("n*", unpack("C*", $1)); }
-        elsif ($str =~ s/^([\xC0-\xDF])([\x80-\xBF])//o)
-        { $res .= pack("n", ((ord($1) & 0x1F) << 6) | (ord($2) & 0x3F)); }
-        elsif ($str =~ s/^([\0xE0-\xEF])([\x80-\xBF])([\x80-\xBF])//o)
-        { $res .= pack("n", ((ord($1) & 0x0F) << 12)
-                          | ((ord($2) & 0x3F) << 6)
-                          | (ord($3) & 0x3F)); }
-        elsif ($str =~ s/^([\xF0-\xF7])([\x80-\xBF])([\x80-\xBF])([\x80-\xBF])//o)
-        {
-            my ($b1, $b2, $b3, $b4) = (ord($1), ord($2), ord($3), ord($4));
-            $res .= pack("n", ((($b1 & 0x07) << 8) | (($b2 & 0x3F) << 2)
-                            | (($b3 & 0x30) >> 4)) + 0xD600);  # account for offset
-            $res .= pack("n", ((($b3 & 0x0F) << 6) | ($b4 & 0x3F)) + 0xDC00);
-        }
-        elsif ($str =~ s/^[\xF8-\xFF][\x80-\xBF]*//o)
-        { }
-    }
-    $res;
-}
-
-
-=head2 XML_hexdump($context, $dat)
-
-Dumps out the given data as a sequence of <data> blocks each 16 bytes wide
-
-=cut
-
-sub XML_hexdump
-{
-    my ($context, $depth, $dat) = @_;
-    my ($fh) = $context->{'fh'};
-    my ($i, $len, $out);
-
-    $len = length($dat);
-    for ($i = 0; $i < $len; $i += 16)
-    {
-        $out = join(' ', map {sprintf("%02X", ord($_))} (split('', substr($dat, $i, 16))));
-        $fh->printf("%s<data addr='%04X'>%s</data>\n", $depth, $i, $out);
-    }
-}
-
-
-=head2 XML_outhints
-
-Converts a binary string of hinting code into a textual representation
-
-=cut
-
-{
-    my (@hints) = (
-    ['SVTCA[0]'], ['SVTCA[1]'], ['SPVTCA[0]'], ['SPVTCA[1]'], ['SFVTCA[0]'], ['SFVTCA[1]'], ['SPVTL[0]'], ['SPVTL[1]'],
-    ['SFVTL[0]'], ['SFVTL[1]'], ['SPVFS'], ['SFVFS'], ['GPV'], ['GFV'], ['SVFTPV'], ['ISECT'],
-# 10
-    ['SRP0'], ['SRP1'], ['SRP2'], ['SZP0'], ['SZP1'], ['SZP2'], ['SZPS'], ['SLOOP'],
-    ['RTG'], ['RTHG'], ['SMD'], ['ELSE'], ['JMPR'], ['SCVTCI'], ['SSWCI'], ['SSW'],
-# 20
-    ['DUP'], ['POP'], ['CLEAR'], ['SWAP'], ['DEPTH'], ['CINDEX'], ['MINDEX'], ['ALIGNPTS'],
-    [], ['UTP'], ['LOOPCALL'], ['CALL'], ['FDEF'], ['ENDF'], ['MDAP[0]'], ['MDAP[1]'],
-# 30
-    ['IUP[0]'], ['IUP[1]'], ['SHP[0]'], ['SHP[1]'], ['SHC[0]'], ['SHC[1]'], ['SHZ[0]'], ['SHZ[1]'],
-    ['SHPIX'], ['IP'], ['MSIRP[0]'], ['MSIRP[1]'], ['ALIGNRP'], ['RTDG'], ['MIAP[0]'], ['MIAP[1]'],
-# 40
-    ['NPUSHB', -1, 1], ['NPUSHW', -1, 2], ['WS', 0, 0], ['RS', 0, 0], ['WCVTP', 0, 0], ['RCVT', 0, 0], ['GC[0]'], ['GC[1]'],
-    ['SCFS'], ['MD[0]'], ['MD[1]'], ['MPPEM'], ['MPS'], ['FLIPON'], ['FLIPOFF'], ['DEBUG'],
-# 50
-    ['LT'], ['LTEQ'], ['GT'], ['GTEQ'], ['EQ'], ['NEQ'], ['ODD'], ['EVEN'],
-    ['IF'], ['EIF'], ['AND'], ['OR'], ['NOT'], ['DELTAP1'], ['SDB'], ['SDS'],
-# 60
-    ['ADD'], ['SUB'], ['DIV'], ['MULT'], ['ABS'], ['NEG'], ['FLOOR'], ['CEILING'],
-    ['ROUND[0]'], ['ROUND[1]'], ['ROUND[2]'], ['ROUND[3]'], ['NROUND[0]'], ['NROUND[1]'], ['NROUND[2]'], ['NROUND[3]'],
-# 70
-    ['WCVTF'], ['DELTAP2'], ['DELTAP3'], ['DELTAC1'], ['DELTAC2'], ['DELTAC3'], ['SROUND'], ['S45ROUND'],
-    ['JROT'], ['JROF'], ['ROFF'], [], ['RUTG'], ['RDTG'], ['SANGW'], [],
-# 80
-    ['FLIPPT'], ['FLIPRGON'], ['FLIPRGOFF'], [], [], ['SCANCTRL'], ['SDPVTL[0]'], ['SDPVTL[1]'],
-    ['GETINFO'], ['IDEF'], ['ROLL'], ['MAX'], ['MIN'], ['SCANTYPE'], ['INSTCTRL'], [],
-# 90
-    [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],
-# A0
-    [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],
-# B0
-    ['PUSHB1', 1, 1], ['PUSHB2', 2, 1], ['PUSHB3', 3, 1], ['PUSHB4', 4, 1], ['PUSHB5', 5, 1], ['PUSHB6', 6, 1], ['PUSHB7', 7, 1], ['PUSHB8', 8, 1],
-    ['PUSHW1', 1, 2], ['PUSHW2', 2, 2], ['PUSHW3', 3, 2], ['PUSHW4', 4, 2], ['PUSHW5', 5, 2], ['PUSHW6', 6, 2], ['PUSHW7', 7, 2], ['PUSHW8', 8, 2],
-# C0
-    ['MDRP[0]'], ['MDRP[1]'], ['MDRP[2]'], ['MDRP[3]'], ['MDRP[4]'], ['MDRP[5]'], ['MDRP[6]'], ['MDRP[7]'],
-    ['MDRP[8]'], ['MDRP[9]'], ['MDRP[A]'], ['MDRP[B]'], ['MDRP[C]'], ['MDRP[D]'], ['MDRP[E]'], ['MDRP[F]'],
-# D0
-    ['MDRP[10]'], ['MDRP[11]'], ['MDRP[12]'], ['MDRP[13]'], ['MDRP[14]'], ['MDRP[15]'], ['MDRP[16]'], ['MDRP[17]'],
-    ['MDRP[18]'], ['MDRP[19]'], ['MDRP[1A]'], ['MDRP[1B]'], ['MDRP[1C]'], ['MDRP[1D]'], ['MDRP[1E]'], ['MDRP[1F]'],
-# E0
-    ['MIRP[0]'], ['MIRP[1]'], ['MIRP[2]'], ['MIRP[3]'], ['MIRP[4]'], ['MIRP[5]'], ['MIRP[6]'], ['MIRP[7]'],
-    ['MIRP[8]'], ['MIRP[9]'], ['MIRP[A]'], ['MIRP[B]'], ['MIRP[C]'], ['MIRP[D]'], ['MIRP[E]'], ['MIRP[F]'],
-# F0
-    ['MIRP[10]'], ['MIRP[11]'], ['MIRP[12]'], ['MIRP[13]'], ['MIRP[14]'], ['MIRP[15]'], ['MIRP[16]'], ['MIRP[17]'],
-    ['MIRP[18]'], ['MIRP[19]'], ['MIRP[1A]'], ['MIRP[1B]'], ['MIRP[1C]'], ['MIRP[1D]'], ['MIRP[1E]'], ['MIRP[1F]']);
-
-    my ($i);
-    my (%hints) = map { $_->[0] => $i++ if (defined $_->[0]); } @hints;
-
-    sub XML_binhint
-    {
-        my ($dat) = @_;
-        my ($len) = length($dat);
-        my ($res, $i);
-        my ($text, $num, $size);
-
-        for ($i = 0; $i < $len; $i++)
-        {
-            ($text, $num, $size) = @{$hints[ord(substr($dat, $i, 1))]};
-            $text = sprintf("UNK[%02X]", ord(substr($dat, $i, 1))) unless defined $text;
-            $res .= $text;
-            if ($num != 0)
-            {
-                if ($num < 0)
-                {
-                    $i++;
-                    my ($nnum) = unpack($num == -1 ? 'C' : 'n', substr($dat, $i, -$num));
-                    $i += -$num - 1;
-                    $num = $nnum;
-                }
-                $res .= "\t" . join(' ', unpack($size == 1 ? 'C*' : 'n*', substr($dat, $i + 1, $num * $size)));
-                $i += $num * $size;
-            }
-            $res .= "\n";
-        }
-        $res;
-    }
-
-    sub XML_hintbin
-    {
-        my ($dat) = @_;
-        my ($l, $res, @words, $num);
-
-        foreach $l (split(/\s*\n\s*/, $dat))
-        {
-            @words = split(/\s*/, $l);
-            next unless (defined $hints{$words[0]});
-            $num = $hints{$words[0]};
-            $res .= pack('C', $num);
-            if ($hints[$num][1] < 0)
-            {
-                $res .= pack($hints[$num][1] == -1 ? 'C' : 'n', $#words);
-                $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $#words]);
-            }
-            elsif ($hints[$num][1] > 0)
-            {
-                $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $hints[$num][1]]);
-            }
-        }
-        $res;
-    }
-}
-
-
-=head2 make_circle($f, $cmap, [$dia, $sb, $opts])
-
-Adds a dotted circle to a font. This function is very configurable. The
-parameters passed in are:
-
-=over 4
-
-=item $f
-
-Font to work with. This is required.
-
-=item $cmap
-
-A cmap table (not the 'val' sub-element of a cmap) to add the glyph too. Optional.
-
-=item $dia
-
-Optional diameter for the main circle. Defaults to 80% em
-
-=item $sb
-
-Side bearing. The left and right side-bearings are always the same. This value
-defaults to 10% em.
-
-=back
-
-There are various options to control all sorts of interesting aspects of the circle
-
-=over 4
-
-=item numDots
-
-Number of dots in the circle
-
-=item numPoints
-
-Number of curve points to use to create each dot
-
-=item uid
-
-Unicode reference to store this glyph under in the cmap. Defaults to 0x25CC
-
-=item pname
-
-Postscript name to give the glyph. Defaults to uni25CC.
-
-=item -dRadius
-
-Radius of each dot.
-
-=back
-
-=cut
-
-sub make_circle
-{
-    my ($font, $cmap, $dia, $sb, %opts) = @_;
-    my ($upem) = $font->{'head'}{'unitsPerEm'};
-    my ($glyph) = Font::TTF::Glyph->new('PARENT' => $font, 'read' => 2);
-    my ($PI) = 3.1415926535;
-    my ($R, $r, $xorg, $yorg);
-    my ($i, $j, $numg, $maxp);
-    my ($numc) = $opts{'-numDots'} || 16;
-    my ($nump) = ($opts{'-numPoints'} * 2) || 8;
-    my ($uid) = $opts{'-uid'} || 0x25CC;
-    my ($pname) = $opts{'-pname'} || 'uni25CC';
-
-    $dia ||= $upem * .8;    # .95 to fit exactly
-    $sb ||= $upem * .1;
-    $R = $dia / 2;
-    $r = $opts{'-dRadius'} || ($R * .1);
-    ($xorg, $yorg) = ($R + $r, $R);
-
-    $xorg += $sb;
-    $font->{'post'}->read;
-    $font->{'glyf'}->read;
-    for ($i = 0; $i < $numc; $i++)
-    {
-        my ($pxorg, $pyorg) = ($xorg + $R * cos(2 * $PI * $i / $numc),
-                                    $yorg + $R * sin(2 * $PI * $i / $numc));
-        for ($j = 0; $j < $nump; $j++)
-        {
-            push (@{$glyph->{'x'}}, int ($pxorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * cos(2 * $PI * $j / $nump)));
-            push (@{$glyph->{'y'}}, int ($pyorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * sin(2 * $PI * $j / $nump)));
-            push (@{$glyph->{'flags'}}, $j & 1 ? 0 : 1);
-        }
-        push (@{$glyph->{'endPoints'}}, $#{$glyph->{'x'}});
-    }
-    $glyph->{'numberOfContours'} = $#{$glyph->{'endPoints'}} + 1;
-    $glyph->{'numPoints'} = $#{$glyph->{'x'}} + 1;
-    $glyph->update;
-    $numg = $font->{'maxp'}{'numGlyphs'};
-    $font->{'maxp'}->read->{'numGlyphs'}++;
-
-    $font->{'hmtx'}{'advance'}[$numg] = int($xorg + $R + $r + $sb + .5);
-    $font->{'hmtx'}{'lsb'}[$numg] = int($xorg - $R - $r + .5);
-    $font->{'loca'}{'glyphs'}[$numg] = $glyph;
-    $cmap->{'val'}{$uid} = $numg if ($cmap);
-    $font->{'post'}{'VAL'}[$numg] = $pname;
-    delete $font->{'hdmx'};
-    delete $font->{'VDMX'};
-    delete $font->{'LTSH'};
-    
-    $font->tables_do(sub {$_[0]->dirty;});
-    $font->update;
-    return ($numg - 1);
-}
-
-
-1;
-
-=head1 BUGS
-
-No known bugs
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Utils;
+
+=head1 NAME
+
+Font::TTF::Utils - Utility functions to save fingers
+
+=head1 DESCRIPTION
+
+Lots of useful functions to save my fingers, especially for trivial tables
+
+=head1 FUNCTIONS
+
+The following functions are exported
+
+=cut
+
+use strict;
+use vars qw(@ISA @EXPORT $VERSION @EXPORT_OK);
+require Exporter;
+
+ at ISA = qw(Exporter);
+ at EXPORT = qw(TTF_Init_Fields TTF_Read_Fields TTF_Out_Fields TTF_Pack
+             TTF_Unpack TTF_word_utf8 TTF_utf8_word TTF_bininfo);
+ at EXPORT_OK = (@EXPORT, qw(XML_hexdump));
+$VERSION = 0.0001;
+
+=head2 ($val, $pos) = TTF_Init_Fields ($str, $pos)
+
+Given a field description from the C<DATA> section, creates an absolute entry
+in the fields associative array for the class
+
+=cut
+
+sub TTF_Init_Fields
+{
+    my ($str, $pos, $inval) = @_;
+    my ($key, $val, $res, $len, $rel);
+
+    $str =~ s/\r?\n$//o;
+    if ($inval)
+    { ($key, $val) = ($str, $inval); }
+    else
+    { ($key, $val) = split(',\s*', $str); }
+    return (undef, undef, 0) unless (defined $key && $key ne "");
+    if ($val =~ m/^(\+?)(\d*)(\D+)(\d*)/oi)
+    {
+        $rel = $1;
+        if ($rel eq "+")
+        { $pos += $2; }
+        elsif ($2 ne "")
+        { $pos = $2; }
+        $val = $3;
+        $len = $4;
+    }
+    $len = "" unless defined $len;
+    $pos = 0 if !defined $pos || $pos eq "";
+    $res = "$pos:$val:$len";
+    if ($val eq "f" || $val =~ m/^[l]/oi)
+    { $pos += 4 * ($len ne "" ? $len : 1); }
+    elsif ($val eq "F" || $val =~ m/^[s]/oi)
+    { $pos += 2 * ($len ne "" ? $len : 1); }
+    else
+    { $pos += 1 * ($len ne "" ? $len : 1); }
+
+    ($key, $res, $pos);
+}
+
+
+=head2 TTF_Read_Fields($obj, $dat, $fields)
+
+Given a block of data large enough to account for all the fields in a table,
+processes the data block to convert to the values in the objects instance
+variables by name based on the list in the C<DATA> block which has been run
+through C<TTF_Init_Fields>
+
+=cut
+
+sub TTF_Read_Fields
+{
+    my ($self, $dat, $fields) = @_;
+    my ($pos, $type, $res, $f, $arrlen, $arr, $frac);
+
+    foreach $f (keys %{$fields})
+    {
+        ($pos, $type, $arrlen) = split(':', $fields->{$f});
+        $pos = 0 if $pos eq "";
+        if ($arrlen ne "")
+        { $self->{$f} = [TTF_Unpack("$type$arrlen", substr($dat, $pos))]; }
+        else
+        { $self->{$f} = TTF_Unpack("$type", substr($dat, $pos)); }
+    }
+    $self;
+}
+
+
+=head2 TTF_Unpack($fmt, $dat)
+
+A TrueType types equivalent of Perls C<unpack> function. Thus $fmt consists of
+type followed by an optional number of elements to read including *. The type
+may be one of:
+
+    c       BYTE
+    C       CHAR
+    f       FIXED
+    F       F2DOT14
+    l       LONG
+    L       ULONG
+    s       SHORT
+    S       USHORT
+
+Note that C<FUNIT>, C<FWORD> and C<UFWORD> are not data types but units.
+
+Returns array of scalar (first element) depending on context
+
+=cut
+
+sub TTF_Unpack
+{
+    my ($fmt, $dat) = @_;
+    my ($res, $frac, $i, $arrlen, $type, @res);
+
+    while ($fmt =~ s/^([cfls])(\d+|\*)?//oi)
+    {
+        $type = $1;
+        $arrlen = $2;
+        $arrlen = 1 if !defined $arrlen || $arrlen eq "";
+        $arrlen = -1 if $arrlen eq "*";
+
+        for ($i = 0; ($arrlen == -1 && $dat ne "") || $i < $arrlen; $i++)
+        {
+            if ($type eq "f")
+            {
+                ($res, $frac) = unpack("nn", $dat);
+                substr($dat, 0, 4) = "";
+                $res -= 65536 if $res > 32767;
+                $res += $frac / 65536.;
+            }
+            elsif ($type eq "F")
+            {
+                $res = unpack("n", $dat);
+                substr($dat, 0, 2) = "";
+#                $res -= 65536 if $res >= 32768;
+                $frac = $res & 0x3fff;
+                $res >>= 14;
+                $res -= 4 if $res > 1;
+#                $frac -= 16384 if $frac > 8191;
+                $res += $frac / 16384.;
+            }
+            elsif ($type =~ m/^[l]/oi)
+            {
+                $res = unpack("N", $dat);
+                substr($dat, 0, 4) = "";
+                $res -= (1 << 32) if ($type eq "l" && $res >= 1 << 31);
+            }
+            elsif ($type =~ m/^[s]/oi)
+            {
+                $res = unpack("n", $dat);
+                substr($dat, 0, 2) = "";
+                $res -= 65536 if ($type eq "s" && $res >= 32768);
+            }
+            elsif ($type eq "c")
+            {
+                $res = unpack("c", $dat);
+                substr($dat, 0, 1) = "";
+            }
+            else
+            {
+                $res = unpack("C", $dat);
+                substr($dat, 0, 1) = "";
+            }
+            push (@res, $res);
+        }
+    }
+    return wantarray ? @res : $res[0];
+}
+
+
+=head2 $dat = TTF_Out_Fields($obj, $fields, $len)
+
+Given the fields table from C<TTF_Init_Fields> writes out the instance variables from
+the object to the filehandle in TTF binary form.
+
+=cut
+
+sub TTF_Out_Fields
+{
+    my ($obj, $fields, $len) = @_;
+    my ($dat) = "\000" x $len;
+    my ($f, $pos, $type, $res, $arr, $arrlen, $frac);
+    
+    foreach $f (keys %{$fields})
+    {
+        ($pos, $type, $arrlen) = split(':', $fields->{$f});
+        if ($arrlen ne "")
+        { $res = TTF_Pack("$type$arrlen", @{$obj->{$f}}); }
+        else
+        { $res = TTF_Pack("$type", $obj->{$f}); }
+        substr($dat, $pos, length($res)) = $res;
+    }
+    $dat;
+}
+
+
+=head2 $dat = TTF_Pack($fmt, @data)
+
+The TrueType equivalent to Perl's C<pack> function. See details of C<TTF_Unpack>
+for how to work the $fmt string.
+
+=cut
+
+sub TTF_Pack
+{
+    my ($fmt, @obj) = @_;
+    my ($type, $i, $arrlen, $dat, $res, $frac);
+
+    while ($fmt =~ s/^([flsc])(\d+|\*)?//oi)
+    {
+        $type = $1;
+        $arrlen = $2 || "";
+        $arrlen = $#obj + 1 if $arrlen eq "*";
+        $arrlen = 1 if $arrlen eq "";
+    
+        for ($i = 0; $i < $arrlen; $i++)
+        {
+            $res = shift(@obj);
+            if ($type eq "f")
+            {
+                $frac = int(($res - int($res)) * 65536);
+                $res = (int($res) << 16) + $frac;
+                $dat .= pack("N", $res);
+            }
+            elsif ($type eq "F")
+            {
+                $frac = int(($res - int($res)) * 16384);
+                $res = (int($res) << 14) + $frac;
+                $dat .= pack("n", $res);
+            }
+            elsif ($type =~ m/^[l]/oi)
+            {
+                $res += 1 << 32 if ($type eq 'L' && $res < 0);
+                $dat .= pack("N", $res);
+            }
+            elsif ($type =~ m/^[s]/oi)
+            {
+                $res += 1 << 16 if ($type eq 'S' && $res < 0);
+                $dat .= pack("n", $res);
+            }
+            elsif ($type eq "c")
+            { $dat .= pack("c", $res); }
+            else
+            { $dat .= pack("C", $res); }
+        }
+    }
+    $dat;
+}
+
+
+=head2 ($num, $range, $select, $shift) = TTF_bininfo($num)
+
+Calculates binary search information from a number of elements
+
+=cut
+
+sub TTF_bininfo
+{
+    my ($num, $block) = @_;
+    my ($range, $select, $shift);
+
+    $range = 1;
+    for ($select = 0; $range <= $num; $select++)
+    { $range *= 2; }
+    $select--; $range /= 2;
+    $range *= $block;
+
+    $shift = $num * $block - $range;
+    ($num, $range, $select, $shift);
+}
+
+
+=head2 TTF_word_utf8($str)
+
+Returns the UTF8 form of the 16 bit string, assumed to be in big endian order,
+including surrogate handling
+
+=cut
+
+sub TTF_word_utf8
+{
+    my ($str) = @_;
+    my ($res, $i);
+    my (@dat) = unpack("n*", $str);
+
+    return pack("U*", @dat) if ($^V && $^V ge v5.6.0);
+    for ($i = 0; $i <= $#dat; $i++)
+    {
+        my ($dat) = $dat[$i];
+        if ($dat < 0x80)        # Thanks to Gisle Aas for some of his old code
+        { $res .= chr($dat); }
+        elsif ($dat < 0x800)
+        { $res .= chr(0xC0 | ($dat >> 6)) . chr(0x80 | ($dat & 0x3F)); }
+        elsif ($dat >= 0xD800 && $dat < 0xDC00)
+        {
+            my ($dat1) = $dat[++$i];
+            my ($top) = (($dat & 0x3C0) >> 6) + 1;
+            $res .= chr(0xF0 | ($top >> 2))
+                  . chr(0x80 | (($top & 1) << 4) | (($dat & 0x3C) >> 2))
+                  . chr(0x80 | (($dat & 0x3) << 4) | (($dat1 & 0x3C0) >> 6))
+                  . chr(0x80 | ($dat1 & 0x3F));
+        } else
+        { $res .= chr(0xE0 | ($dat >> 12)) . chr(0x80 | (($dat >> 6) & 0x3F))
+                . chr(0x80 | ($dat & 0x3F)); }
+    }
+    $res;
+}
+
+
+=head2 TTF_utf8_word($str)
+
+Returns the 16-bit form in big endian order of the UTF 8 string, including
+surrogate handling to Unicode.
+
+=cut
+
+sub TTF_utf8_word
+{
+    my ($str) = @_;
+    my ($res);
+
+    return pack("n*", unpack("U*", $str)) if ($^V ge v5.6.0);
+    $str = "$str";              # copy $str
+    while (length($str))        # Thanks to Gisle Aas for some of his old code
+    {
+        $str =~ s/^[\x80-\xBF]+//o;
+        if ($str =~ s/^([\x00-\x7F]+)//o)
+        { $res .= pack("n*", unpack("C*", $1)); }
+        elsif ($str =~ s/^([\xC0-\xDF])([\x80-\xBF])//o)
+        { $res .= pack("n", ((ord($1) & 0x1F) << 6) | (ord($2) & 0x3F)); }
+        elsif ($str =~ s/^([\0xE0-\xEF])([\x80-\xBF])([\x80-\xBF])//o)
+        { $res .= pack("n", ((ord($1) & 0x0F) << 12)
+                          | ((ord($2) & 0x3F) << 6)
+                          | (ord($3) & 0x3F)); }
+        elsif ($str =~ s/^([\xF0-\xF7])([\x80-\xBF])([\x80-\xBF])([\x80-\xBF])//o)
+        {
+            my ($b1, $b2, $b3, $b4) = (ord($1), ord($2), ord($3), ord($4));
+            $res .= pack("n", ((($b1 & 0x07) << 8) | (($b2 & 0x3F) << 2)
+                            | (($b3 & 0x30) >> 4)) + 0xD600);  # account for offset
+            $res .= pack("n", ((($b3 & 0x0F) << 6) | ($b4 & 0x3F)) + 0xDC00);
+        }
+        elsif ($str =~ s/^[\xF8-\xFF][\x80-\xBF]*//o)
+        { }
+    }
+    $res;
+}
+
+
+=head2 XML_hexdump($context, $dat)
+
+Dumps out the given data as a sequence of <data> blocks each 16 bytes wide
+
+=cut
+
+sub XML_hexdump
+{
+    my ($context, $depth, $dat) = @_;
+    my ($fh) = $context->{'fh'};
+    my ($i, $len, $out);
+
+    $len = length($dat);
+    for ($i = 0; $i < $len; $i += 16)
+    {
+        $out = join(' ', map {sprintf("%02X", ord($_))} (split('', substr($dat, $i, 16))));
+        $fh->printf("%s<data addr='%04X'>%s</data>\n", $depth, $i, $out);
+    }
+}
+
+
+=head2 XML_outhints
+
+Converts a binary string of hinting code into a textual representation
+
+=cut
+
+{
+    my (@hints) = (
+    ['SVTCA[0]'], ['SVTCA[1]'], ['SPVTCA[0]'], ['SPVTCA[1]'], ['SFVTCA[0]'], ['SFVTCA[1]'], ['SPVTL[0]'], ['SPVTL[1]'],
+    ['SFVTL[0]'], ['SFVTL[1]'], ['SPVFS'], ['SFVFS'], ['GPV'], ['GFV'], ['SVFTPV'], ['ISECT'],
+# 10
+    ['SRP0'], ['SRP1'], ['SRP2'], ['SZP0'], ['SZP1'], ['SZP2'], ['SZPS'], ['SLOOP'],
+    ['RTG'], ['RTHG'], ['SMD'], ['ELSE'], ['JMPR'], ['SCVTCI'], ['SSWCI'], ['SSW'],
+# 20
+    ['DUP'], ['POP'], ['CLEAR'], ['SWAP'], ['DEPTH'], ['CINDEX'], ['MINDEX'], ['ALIGNPTS'],
+    [], ['UTP'], ['LOOPCALL'], ['CALL'], ['FDEF'], ['ENDF'], ['MDAP[0]'], ['MDAP[1]'],
+# 30
+    ['IUP[0]'], ['IUP[1]'], ['SHP[0]'], ['SHP[1]'], ['SHC[0]'], ['SHC[1]'], ['SHZ[0]'], ['SHZ[1]'],
+    ['SHPIX'], ['IP'], ['MSIRP[0]'], ['MSIRP[1]'], ['ALIGNRP'], ['RTDG'], ['MIAP[0]'], ['MIAP[1]'],
+# 40
+    ['NPUSHB', -1, 1], ['NPUSHW', -1, 2], ['WS', 0, 0], ['RS', 0, 0], ['WCVTP', 0, 0], ['RCVT', 0, 0], ['GC[0]'], ['GC[1]'],
+    ['SCFS'], ['MD[0]'], ['MD[1]'], ['MPPEM'], ['MPS'], ['FLIPON'], ['FLIPOFF'], ['DEBUG'],
+# 50
+    ['LT'], ['LTEQ'], ['GT'], ['GTEQ'], ['EQ'], ['NEQ'], ['ODD'], ['EVEN'],
+    ['IF'], ['EIF'], ['AND'], ['OR'], ['NOT'], ['DELTAP1'], ['SDB'], ['SDS'],
+# 60
+    ['ADD'], ['SUB'], ['DIV'], ['MULT'], ['ABS'], ['NEG'], ['FLOOR'], ['CEILING'],
+    ['ROUND[0]'], ['ROUND[1]'], ['ROUND[2]'], ['ROUND[3]'], ['NROUND[0]'], ['NROUND[1]'], ['NROUND[2]'], ['NROUND[3]'],
+# 70
+    ['WCVTF'], ['DELTAP2'], ['DELTAP3'], ['DELTAC1'], ['DELTAC2'], ['DELTAC3'], ['SROUND'], ['S45ROUND'],
+    ['JROT'], ['JROF'], ['ROFF'], [], ['RUTG'], ['RDTG'], ['SANGW'], [],
+# 80
+    ['FLIPPT'], ['FLIPRGON'], ['FLIPRGOFF'], [], [], ['SCANCTRL'], ['SDPVTL[0]'], ['SDPVTL[1]'],
+    ['GETINFO'], ['IDEF'], ['ROLL'], ['MAX'], ['MIN'], ['SCANTYPE'], ['INSTCTRL'], [],
+# 90
+    [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],
+# A0
+    [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],
+# B0
+    ['PUSHB1', 1, 1], ['PUSHB2', 2, 1], ['PUSHB3', 3, 1], ['PUSHB4', 4, 1], ['PUSHB5', 5, 1], ['PUSHB6', 6, 1], ['PUSHB7', 7, 1], ['PUSHB8', 8, 1],
+    ['PUSHW1', 1, 2], ['PUSHW2', 2, 2], ['PUSHW3', 3, 2], ['PUSHW4', 4, 2], ['PUSHW5', 5, 2], ['PUSHW6', 6, 2], ['PUSHW7', 7, 2], ['PUSHW8', 8, 2],
+# C0
+    ['MDRP[0]'], ['MDRP[1]'], ['MDRP[2]'], ['MDRP[3]'], ['MDRP[4]'], ['MDRP[5]'], ['MDRP[6]'], ['MDRP[7]'],
+    ['MDRP[8]'], ['MDRP[9]'], ['MDRP[A]'], ['MDRP[B]'], ['MDRP[C]'], ['MDRP[D]'], ['MDRP[E]'], ['MDRP[F]'],
+# D0
+    ['MDRP[10]'], ['MDRP[11]'], ['MDRP[12]'], ['MDRP[13]'], ['MDRP[14]'], ['MDRP[15]'], ['MDRP[16]'], ['MDRP[17]'],
+    ['MDRP[18]'], ['MDRP[19]'], ['MDRP[1A]'], ['MDRP[1B]'], ['MDRP[1C]'], ['MDRP[1D]'], ['MDRP[1E]'], ['MDRP[1F]'],
+# E0
+    ['MIRP[0]'], ['MIRP[1]'], ['MIRP[2]'], ['MIRP[3]'], ['MIRP[4]'], ['MIRP[5]'], ['MIRP[6]'], ['MIRP[7]'],
+    ['MIRP[8]'], ['MIRP[9]'], ['MIRP[A]'], ['MIRP[B]'], ['MIRP[C]'], ['MIRP[D]'], ['MIRP[E]'], ['MIRP[F]'],
+# F0
+    ['MIRP[10]'], ['MIRP[11]'], ['MIRP[12]'], ['MIRP[13]'], ['MIRP[14]'], ['MIRP[15]'], ['MIRP[16]'], ['MIRP[17]'],
+    ['MIRP[18]'], ['MIRP[19]'], ['MIRP[1A]'], ['MIRP[1B]'], ['MIRP[1C]'], ['MIRP[1D]'], ['MIRP[1E]'], ['MIRP[1F]']);
+
+    my ($i);
+    my (%hints) = map { $_->[0] => $i++ if (defined $_->[0]); } @hints;
+
+    sub XML_binhint
+    {
+        my ($dat) = @_;
+        my ($len) = length($dat);
+        my ($res, $i);
+        my ($text, $num, $size);
+
+        for ($i = 0; $i < $len; $i++)
+        {
+            ($text, $num, $size) = @{$hints[ord(substr($dat, $i, 1))]};
+            $text = sprintf("UNK[%02X]", ord(substr($dat, $i, 1))) unless defined $text;
+            $res .= $text;
+            if ($num != 0)
+            {
+                if ($num < 0)
+                {
+                    $i++;
+                    my ($nnum) = unpack($num == -1 ? 'C' : 'n', substr($dat, $i, -$num));
+                    $i += -$num - 1;
+                    $num = $nnum;
+                }
+                $res .= "\t" . join(' ', unpack($size == 1 ? 'C*' : 'n*', substr($dat, $i + 1, $num * $size)));
+                $i += $num * $size;
+            }
+            $res .= "\n";
+        }
+        $res;
+    }
+
+    sub XML_hintbin
+    {
+        my ($dat) = @_;
+        my ($l, $res, @words, $num);
+
+        foreach $l (split(/\s*\n\s*/, $dat))
+        {
+            @words = split(/\s*/, $l);
+            next unless (defined $hints{$words[0]});
+            $num = $hints{$words[0]};
+            $res .= pack('C', $num);
+            if ($hints[$num][1] < 0)
+            {
+                $res .= pack($hints[$num][1] == -1 ? 'C' : 'n', $#words);
+                $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $#words]);
+            }
+            elsif ($hints[$num][1] > 0)
+            {
+                $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $hints[$num][1]]);
+            }
+        }
+        $res;
+    }
+}
+
+
+=head2 make_circle($f, $cmap, [$dia, $sb, $opts])
+
+Adds a dotted circle to a font. This function is very configurable. The
+parameters passed in are:
+
+=over 4
+
+=item $f
+
+Font to work with. This is required.
+
+=item $cmap
+
+A cmap table (not the 'val' sub-element of a cmap) to add the glyph too. Optional.
+
+=item $dia
+
+Optional diameter for the main circle. Defaults to 80% em
+
+=item $sb
+
+Side bearing. The left and right side-bearings are always the same. This value
+defaults to 10% em.
+
+=back
+
+There are various options to control all sorts of interesting aspects of the circle
+
+=over 4
+
+=item numDots
+
+Number of dots in the circle
+
+=item numPoints
+
+Number of curve points to use to create each dot
+
+=item uid
+
+Unicode reference to store this glyph under in the cmap. Defaults to 0x25CC
+
+=item pname
+
+Postscript name to give the glyph. Defaults to uni25CC.
+
+=item -dRadius
+
+Radius of each dot.
+
+=back
+
+=cut
+
+sub make_circle
+{
+    my ($font, $cmap, $dia, $sb, %opts) = @_;
+    my ($upem) = $font->{'head'}{'unitsPerEm'};
+    my ($glyph) = Font::TTF::Glyph->new('PARENT' => $font, 'read' => 2);
+    my ($PI) = 3.1415926535;
+    my ($R, $r, $xorg, $yorg);
+    my ($i, $j, $numg, $maxp);
+    my ($numc) = $opts{'-numDots'} || 16;
+    my ($nump) = ($opts{'-numPoints'} * 2) || 8;
+    my ($uid) = $opts{'-uid'} || 0x25CC;
+    my ($pname) = $opts{'-pname'} || 'uni25CC';
+
+    $dia ||= $upem * .8;    # .95 to fit exactly
+    $sb ||= $upem * .1;
+    $R = $dia / 2;
+    $r = $opts{'-dRadius'} || ($R * .1);
+    ($xorg, $yorg) = ($R + $r, $R);
+
+    $xorg += $sb;
+    $font->{'post'}->read;
+    $font->{'glyf'}->read;
+    for ($i = 0; $i < $numc; $i++)
+    {
+        my ($pxorg, $pyorg) = ($xorg + $R * cos(2 * $PI * $i / $numc),
+                                    $yorg + $R * sin(2 * $PI * $i / $numc));
+        for ($j = 0; $j < $nump; $j++)
+        {
+            push (@{$glyph->{'x'}}, int ($pxorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * cos(2 * $PI * $j / $nump)));
+            push (@{$glyph->{'y'}}, int ($pyorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * sin(2 * $PI * $j / $nump)));
+            push (@{$glyph->{'flags'}}, $j & 1 ? 0 : 1);
+        }
+        push (@{$glyph->{'endPoints'}}, $#{$glyph->{'x'}});
+    }
+    $glyph->{'numberOfContours'} = $#{$glyph->{'endPoints'}} + 1;
+    $glyph->{'numPoints'} = $#{$glyph->{'x'}} + 1;
+    $glyph->update;
+    $numg = $font->{'maxp'}{'numGlyphs'};
+    $font->{'maxp'}->read->{'numGlyphs'}++;
+
+    $font->{'hmtx'}{'advance'}[$numg] = int($xorg + $R + $r + $sb + .5);
+    $font->{'hmtx'}{'lsb'}[$numg] = int($xorg - $R - $r + .5);
+    $font->{'loca'}{'glyphs'}[$numg] = $glyph;
+    $cmap->{'val'}{$uid} = $numg if ($cmap);
+    $font->{'post'}{'VAL'}[$numg] = $pname;
+    delete $font->{'hdmx'};
+    delete $font->{'VDMX'};
+    delete $font->{'LTSH'};
+    
+    $font->tables_do(sub {$_[0]->dirty;});
+    $font->update;
+    return ($numg - 1);
+}
+
+
+1;
+
+=head1 BUGS
+
+No known bugs
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vhea.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vhea.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vhea.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,159 +1,159 @@
-package Font::TTF::Vhea;
-
-=head1 NAME
-
-TTF:Vhea - Vertical Header table
-
-=head1 DESCRIPTION
-
-This is a simple table with just standards specified instance variables
-
-=head1 INSTANCE VARIABLES
-
-    version
-    Ascender
-    Descender
-    LineGap
-    advanceHeightMax
-    minTopSideBearing
-    minBottomSideBearing
-    yMaxExtent
-    caretSlopeRise
-    caretSlopeRun
-    metricDataFormat
-    numberOfVMetrics
-
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA %fields @field_info);
-
-require Font::TTF::Table;
-use Font::TTF::Utils;
-
- at ISA = qw(Font::TTF::Table);
- at field_info = (
-    'version' => 'f',
-    'Ascender' => 's',
-    'Descender' => 's',
-    'LineGap' => 's',
-    'advanceHeightMax' => 'S',
-    'minTopSideBearing' => 's',
-    'minBottomSideBearing' => 's',
-    'yMaxExtent' => 's',
-    'caretSlopeRise' => 's',
-    'caretSlopeRun' => 's',
-    'metricDataFormat' => '+10s',
-    'numberOfVMetrics' => 's');
-
-sub init
-{
-    my ($k, $v, $c, $i);
-    for ($i = 0; $i < $#field_info; $i += 2)
-    {
-        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
-        next unless defined $k && $k ne "";
-        $fields{$k} = $v;
-    }
-}
-
-
-=head2 $t->read
-
-Reads the table into memory as instance variables
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($dat);
-
-    $self->SUPER::read or return $self;
-    init unless defined $fields{'Ascender'};
-    $self->{' INFILE'}->read($dat, 36);
-
-    TTF_Read_Fields($self, $dat, \%fields);
-    $self;
-}
-
-
-=head2 $t->out($fh)
-
-Writes the table to a file either from memory or by copying.
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-
-    return $self->SUPER::out($fh) unless $self->{' read'};
-
-    $self->{'numberOfVMetrics'} = $self->{' PARENT'}{'vmtx'}->numMetrics || $self->{'numberOfVMetrics'};
-    $fh->print(TTF_Out_Fields($self, \%fields, 36));
-    $self;
-}
-
-
-=head2 $t->update
-
-Updates various parameters in the hhea table from the hmtx table, assuming
-the C<hmtx> table is dirty.
-
-=cut
-
-sub update
-{
-    my ($self) = @_;
-    my ($vmtx) = $self->{' PARENT'}{'vmtx'};
-    my ($glyphs);
-    my ($num);
-    my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext);
-
-    return undef unless ($self->SUPER::update);
-    return undef unless (defined $vmtx && defined $self->{' PARENT'}{'loca'});
-    $vmtx->read->update;
-    $self->{' PARENT'}{'loca'}->read->update;
-    $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'};
-    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-
-    for ($i = 0; $i < $num; $i++)
-    {
-        $aw = $vmtx->{'advance'}[$i];
-        $lsb = $vmtx->{'top'}[$i];
-        if (defined $glyphs->[$i])
-        { $ext = $lsb + $glyphs->[$i]->read->{'yMax'} - $glyphs->[$i]{'yMin'}; }
-        else
-        { $ext = $aw; }
-        $maw = $aw if ($aw > $maw);
-        $mlsb = $lsb if ($lsb < $mlsb or $i == 0);
-        $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0);
-        $mext = $ext if ($ext > $mext);
-    }
-    $self->{'advanceHeightMax'} = $maw;
-    $self->{'minTopSideBearing'} = $mlsb;
-    $self->{'minBottomSideBearing'} = $mrsb;
-    $self->{'yMaxExtent'} = $mext;
-    $self->{'numberOfVMetrics'} = $vmtx->numMetrics;
-    $self;
-}
-
-
-1;
-
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Vhea;
+
+=head1 NAME
+
+TTF:Vhea - Vertical Header table
+
+=head1 DESCRIPTION
+
+This is a simple table with just standards specified instance variables
+
+=head1 INSTANCE VARIABLES
+
+    version
+    Ascender
+    Descender
+    LineGap
+    advanceHeightMax
+    minTopSideBearing
+    minBottomSideBearing
+    yMaxExtent
+    caretSlopeRise
+    caretSlopeRun
+    metricDataFormat
+    numberOfVMetrics
+
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA %fields @field_info);
+
+require Font::TTF::Table;
+use Font::TTF::Utils;
+
+ at ISA = qw(Font::TTF::Table);
+ at field_info = (
+    'version' => 'f',
+    'Ascender' => 's',
+    'Descender' => 's',
+    'LineGap' => 's',
+    'advanceHeightMax' => 'S',
+    'minTopSideBearing' => 's',
+    'minBottomSideBearing' => 's',
+    'yMaxExtent' => 's',
+    'caretSlopeRise' => 's',
+    'caretSlopeRun' => 's',
+    'metricDataFormat' => '+10s',
+    'numberOfVMetrics' => 's');
+
+sub init
+{
+    my ($k, $v, $c, $i);
+    for ($i = 0; $i < $#field_info; $i += 2)
+    {
+        ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]);
+        next unless defined $k && $k ne "";
+        $fields{$k} = $v;
+    }
+}
+
+
+=head2 $t->read
+
+Reads the table into memory as instance variables
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($dat);
+
+    $self->SUPER::read or return $self;
+    init unless defined $fields{'Ascender'};
+    $self->{' INFILE'}->read($dat, 36);
+
+    TTF_Read_Fields($self, $dat, \%fields);
+    $self;
+}
+
+
+=head2 $t->out($fh)
+
+Writes the table to a file either from memory or by copying.
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+
+    return $self->SUPER::out($fh) unless $self->{' read'};
+
+    $self->{'numberOfVMetrics'} = $self->{' PARENT'}{'vmtx'}->numMetrics || $self->{'numberOfVMetrics'};
+    $fh->print(TTF_Out_Fields($self, \%fields, 36));
+    $self;
+}
+
+
+=head2 $t->update
+
+Updates various parameters in the hhea table from the hmtx table, assuming
+the C<hmtx> table is dirty.
+
+=cut
+
+sub update
+{
+    my ($self) = @_;
+    my ($vmtx) = $self->{' PARENT'}{'vmtx'};
+    my ($glyphs);
+    my ($num);
+    my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext);
+
+    return undef unless ($self->SUPER::update);
+    return undef unless (defined $vmtx && defined $self->{' PARENT'}{'loca'});
+    $vmtx->read->update;
+    $self->{' PARENT'}{'loca'}->read->update;
+    $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'};
+    $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+
+    for ($i = 0; $i < $num; $i++)
+    {
+        $aw = $vmtx->{'advance'}[$i];
+        $lsb = $vmtx->{'top'}[$i];
+        if (defined $glyphs->[$i])
+        { $ext = $lsb + $glyphs->[$i]->read->{'yMax'} - $glyphs->[$i]{'yMin'}; }
+        else
+        { $ext = $aw; }
+        $maw = $aw if ($aw > $maw);
+        $mlsb = $lsb if ($lsb < $mlsb or $i == 0);
+        $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0);
+        $mext = $ext if ($ext > $mext);
+    }
+    $self->{'advanceHeightMax'} = $maw;
+    $self->{'minTopSideBearing'} = $mlsb;
+    $self->{'minBottomSideBearing'} = $mrsb;
+    $self->{'yMaxExtent'} = $mext;
+    $self->{'numberOfVMetrics'} = $vmtx->numMetrics;
+    $self;
+}
+
+
+1;
+
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vmtx.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vmtx.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Vmtx.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,86 +1,86 @@
-package Font::TTF::Vmtx;
-
-=head1 NAME
-
-Font::TTF::Vmtx - Vertical Metrics
-
-=head1 DESCRIPTION
-
-Contains the advance height and top side bearing for each glyph. Given the
-compressability of the data onto disk, this table uses information from
-other tables, and thus must do part of its output during the output of
-other tables
-
-=head1 INSTANCE VARIABLES
-
-The vertical metrics are kept in two arrays by glyph id. The variable names
-do not start with a space
-
-=over 4
-
-=item advance
-
-An array containing the advance height for each glyph
-
-=item top
-
-An array containing the top side bearing for each glyph
-
-=back
-
-=head1 METHODS
-
-=cut
-
-use strict;
-use vars qw(@ISA);
-require Font::TTF::Hmtx;
-
- at ISA = qw(Font::TTF::Hmtx);
-
-
-=head2 $t->read
-
-Reads the vertical metrics from the TTF file into memory
-
-=cut
-
-sub read
-{
-    my ($self) = @_;
-    my ($numh, $numg);
-
-    $numh = $self->{' PARENT'}{'vhea'}->read->{'numberOfVMetrics'};
-    $numg = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
-    $self->_read($numg, $numh, "advance", "top");
-}
-
-
-=head2 $t->out($fh)
-
-Writes the metrics to a TTF file. Assumes that the C<vhea> has updated the
-numVMetrics from here
-
-=cut
-
-sub out
-{
-    my ($self, $fh) = @_;
-    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
-    my ($numh) = $self->{' PARENT'}{'vhea'}{'numberOfVMetrics'};
-    $self->_out($fh, $numg, $numh, "advance", "top");
-}
-
-1;
-
-=head1 BUGS
-
-None known
-
-=head1 AUTHOR
-
-Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
-licensing.
-
-=cut
-
+package Font::TTF::Vmtx;
+
+=head1 NAME
+
+Font::TTF::Vmtx - Vertical Metrics
+
+=head1 DESCRIPTION
+
+Contains the advance height and top side bearing for each glyph. Given the
+compressability of the data onto disk, this table uses information from
+other tables, and thus must do part of its output during the output of
+other tables
+
+=head1 INSTANCE VARIABLES
+
+The vertical metrics are kept in two arrays by glyph id. The variable names
+do not start with a space
+
+=over 4
+
+=item advance
+
+An array containing the advance height for each glyph
+
+=item top
+
+An array containing the top side bearing for each glyph
+
+=back
+
+=head1 METHODS
+
+=cut
+
+use strict;
+use vars qw(@ISA);
+require Font::TTF::Hmtx;
+
+ at ISA = qw(Font::TTF::Hmtx);
+
+
+=head2 $t->read
+
+Reads the vertical metrics from the TTF file into memory
+
+=cut
+
+sub read
+{
+    my ($self) = @_;
+    my ($numh, $numg);
+
+    $numh = $self->{' PARENT'}{'vhea'}->read->{'numberOfVMetrics'};
+    $numg = $self->{' PARENT'}{'maxp'}->read->{'numGlyphs'};
+    $self->_read($numg, $numh, "advance", "top");
+}
+
+
+=head2 $t->out($fh)
+
+Writes the metrics to a TTF file. Assumes that the C<vhea> has updated the
+numVMetrics from here
+
+=cut
+
+sub out
+{
+    my ($self, $fh) = @_;
+    my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'};
+    my ($numh) = $self->{' PARENT'}{'vhea'}{'numberOfVMetrics'};
+    $self->_out($fh, $numg, $numh, "advance", "top");
+}
+
+1;
+
+=head1 BUGS
+
+None known
+
+=head1 AUTHOR
+
+Martin Hosken Martin_Hosken at sil.org. See L<Font::TTF::Font> for copyright and
+licensing.
+
+=cut
+

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/Win32.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/Win32.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/Win32.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,33 +1,33 @@
-package Font::TTF::Win32;
-
-# use strict;
-# use vars qw($HKEY_LOCAL_MACHINE);
-
-use Win32::Registry;
-use Win32;
-use File::Spec;
-use Font::TTF::Font;
-
-
-sub findfonts
-{
-    my ($sub) = @_;
-    my ($font_key) = 'SOFTWARE\Microsoft\Windows' . (Win32::IsWinNT() ? ' NT' : '') . '\CurrentVersion\Fonts';
-    my ($regFont, $list, $l, $font, $file);
-    
-# get entry from registry for a font of this name
-    $::HKEY_LOCAL_MACHINE->Open($font_key, $regFont);
-    $regFont->GetValues($list);
-
-    foreach $l (sort keys %{$list})
-    {
-        my ($fname) = $list->{$l}[0];
-        next unless ($fname =~ s/\(TrueType\)$//o);
-        $file = File::Spec->rel2abs($list->{$l}[2], "$ENV{'windir'}/fonts");
-        $font = Font::TTF::Font->open($file) || next;
-        &{$sub}($font, $fname);
-        $font->release;
-    }
-}
-
-1;
+package Font::TTF::Win32;
+
+# use strict;
+# use vars qw($HKEY_LOCAL_MACHINE);
+
+use Win32::Registry;
+use Win32;
+use File::Spec;
+use Font::TTF::Font;
+
+
+sub findfonts
+{
+    my ($sub) = @_;
+    my ($font_key) = 'SOFTWARE\Microsoft\Windows' . (Win32::IsWinNT() ? ' NT' : '') . '\CurrentVersion\Fonts';
+    my ($regFont, $list, $l, $font, $file);
+    
+# get entry from registry for a font of this name
+    $::HKEY_LOCAL_MACHINE->Open($font_key, $regFont);
+    $regFont->GetValues($list);
+
+    foreach $l (sort keys %{$list})
+    {
+        my ($fname) = $list->{$l}[0];
+        next unless ($fname =~ s/\(TrueType\)$//o);
+        $file = File::Spec->rel2abs($list->{$l}[2], "$ENV{'windir'}/fonts");
+        $font = Font::TTF::Font->open($file) || next;
+        &{$sub}($font, $fname);
+        $font->release;
+    }
+}
+
+1;

Modified: packages/libfont-ttf-perl/trunk/lib/Font/TTF/XMLparse.pm
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/Font/TTF/XMLparse.pm	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/Font/TTF/XMLparse.pm	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,176 +1,176 @@
-package Font::TTF::XMLparse;
-
-=head1 NAME
-
-Font::TTF::XMLparse - provides support for XML parsing. Requires Expat module XML::Parser::Expat
-
-=head1 SYNOPSIS
-
-    use Font::TTF::Font;
-    use Font::TTF::XMLparse;
-
-    $f = Font::TTF::Font->new;
-    read_xml($f, $ARGV[0]);
-    $f->out($ARGV[1]);
-
-=head1 DESCRIPTION
-
-This module contains the support routines for parsing XML and generating the
-Truetype font structures as a result. The module has been separated from the rest
-of the package in order to reduce the dependency that this would bring, of the
-whole package on XML::Parser. This way, people without the XML::Parser can still
-use the rest of the package.
-
-The package interacts with another package through the use of a context containing
-and element 'receiver' which is an object which can possibly receive one of the
-following messages:
-
-=over 4
-
-=item XML_start
-
-This message is called when an open tag occurs. It is called with the context,
-tag name and the attributes. The return value has no meaning.
-
-=item XML_end
-
-This messages is called when a close tag occurs. It is called with the context,
-tag name and attributes (held over from when the tag was opened). There are 3
-possible return values from such a message:
-
-=over 8
-
-=item undef
-
-This is the default return value indicating that default processing should
-occur in which either the current element on the tree, or the text of this element
-should be stored in the parent object.
-
-=item $context
-
-This magic value marks that the element should be deleted from the parent.
-Nothing is stored in the parent. (This rather than '' is used to allow 0 returns.)
-
-=item anything
-
-Anything else is taken as the element content to be stored in the parent.
-
-=back 4
-
-=back 4
-
-In addition, the context hash passed to these messages contains the following
-keys:
-
-=over 4
-
-=item xml
-
-This is the expat xml object. The context is also available as
-$context->{'xml'}{' mycontext'}. But that is a long winded way of not saying much!
-
-=item font
-
-This is the base object that was passed in for XML parsing.
-
-=item receiver
-
-This holds the current receiver of parsing events. It may be set in associated
-application to adjust which objects should receive messages when. It is also stored
-in the parsing stack to ensure that where an object changes it during XML_start, that
-that same object that received XML_start will receive the corresponding XML_end
-
-=item stack
-
-This is the parsing stack, used internally to hold the current receiver and attributes
-for each element open, as a complete hierarchy back to the root element.
-
-=item tree
-
-This element contains the storage tree corresponding to the parent of each element
-in the stack. The default action is to push undef onto this stack during XML_start
-and then to resolve this, either in the associated application (by changing
-$context->{'tree'}[-1]) or during XML_end of a child element, by which time we know
-whether we are dealing with an array or a hash or what.
-
-=item text
-
-Character processing is to insert all the characters into the text element of the
-context for available use later.
-
-=back 4
-
-=head1 METHODS
-
-=cut
-
-use XML::Parser::Expat;
-use Exporter;
-
-use strict;
-use vars qw(@ISA @EXPORT);
-
- at ISA = qw(Exporter);
- at EXPORT = qw(read_xml);
-
-sub read_xml
-{
-    my ($font, $fname) = @_;
-
-    my ($xml) = XML::Parser::Expat->new;
-    my ($context) = {'xml' => $xml, 'font' => $font};
-
-    $xml->setHandlers('Start' => sub {
-            my ($x, $tag, %attrs) = @_;
-            my ($context) = $x->{' mycontext'};
-            my ($fn) = $context->{'receiver'}->can('XML_start');
-
-            push(@{$context->{'tree'}}, undef);
-            push(@{$context->{'stack'}}, [$context->{'receiver'}, {%attrs}]);
-            &{$fn}($context->{'receiver'}, $context, $tag, %attrs) if defined $fn;
-        },
-        'End' => sub {
-            my ($x, $tag) = @_;
-            my ($context) = $x->{' mycontext'};
-            my ($fn) = $context->{'receiver'}->can('XML_end');
-            my ($stackinfo) = pop(@{$context->{'stack'}});
-            my ($current, $res);
-
-            $context->{'receiver'} = $stackinfo->[0];
-            $context->{'text'} =~ s/^\s*(.*?)\s*$/$1/o;
-            $res = &{$fn}($context->{'receiver'}, $context, $tag, %{$stackinfo->[1]}) if defined $fn;
-            $current = pop(@{$context->{'tree'}});
-            $current = $context->{'text'} unless (defined $current);
-            $context->{'text'} = '';
-
-            if (defined $res)
-            {
-                return if ($res eq $context);
-                $current = $res;
-            }
-            return unless $#{$context->{'tree'}} >= 0;
-            if ($tag eq 'elem')
-            {
-                $context->{'tree'}[-1] = [] unless defined $context->{'tree'}[-1];
-                push (@{$context->{'tree'}[-1]}, $current);
-            } else
-            {
-                $context->{'tree'}[-1] = {} unless defined $context->{'tree'}[-1];
-                $context->{'tree'}[-1]{$tag} = $current;
-            }
-        },
-        'Char' => sub {
-            my ($x, $str) = @_;
-            $x->{' mycontext'}{'text'} .= $str;
-        });
-
-    $xml->{' mycontext'} = $context;
-
-    $context->{'receiver'} = $font;
-    if (ref $fname)
-    { return $xml->parse($fname); }
-    else
-    { return $xml->parsefile($fname); }
-}
-
-
+package Font::TTF::XMLparse;
+
+=head1 NAME
+
+Font::TTF::XMLparse - provides support for XML parsing. Requires Expat module XML::Parser::Expat
+
+=head1 SYNOPSIS
+
+    use Font::TTF::Font;
+    use Font::TTF::XMLparse;
+
+    $f = Font::TTF::Font->new;
+    read_xml($f, $ARGV[0]);
+    $f->out($ARGV[1]);
+
+=head1 DESCRIPTION
+
+This module contains the support routines for parsing XML and generating the
+Truetype font structures as a result. The module has been separated from the rest
+of the package in order to reduce the dependency that this would bring, of the
+whole package on XML::Parser. This way, people without the XML::Parser can still
+use the rest of the package.
+
+The package interacts with another package through the use of a context containing
+and element 'receiver' which is an object which can possibly receive one of the
+following messages:
+
+=over 4
+
+=item XML_start
+
+This message is called when an open tag occurs. It is called with the context,
+tag name and the attributes. The return value has no meaning.
+
+=item XML_end
+
+This messages is called when a close tag occurs. It is called with the context,
+tag name and attributes (held over from when the tag was opened). There are 3
+possible return values from such a message:
+
+=over 8
+
+=item undef
+
+This is the default return value indicating that default processing should
+occur in which either the current element on the tree, or the text of this element
+should be stored in the parent object.
+
+=item $context
+
+This magic value marks that the element should be deleted from the parent.
+Nothing is stored in the parent. (This rather than '' is used to allow 0 returns.)
+
+=item anything
+
+Anything else is taken as the element content to be stored in the parent.
+
+=back 4
+
+=back 4
+
+In addition, the context hash passed to these messages contains the following
+keys:
+
+=over 4
+
+=item xml
+
+This is the expat xml object. The context is also available as
+$context->{'xml'}{' mycontext'}. But that is a long winded way of not saying much!
+
+=item font
+
+This is the base object that was passed in for XML parsing.
+
+=item receiver
+
+This holds the current receiver of parsing events. It may be set in associated
+application to adjust which objects should receive messages when. It is also stored
+in the parsing stack to ensure that where an object changes it during XML_start, that
+that same object that received XML_start will receive the corresponding XML_end
+
+=item stack
+
+This is the parsing stack, used internally to hold the current receiver and attributes
+for each element open, as a complete hierarchy back to the root element.
+
+=item tree
+
+This element contains the storage tree corresponding to the parent of each element
+in the stack. The default action is to push undef onto this stack during XML_start
+and then to resolve this, either in the associated application (by changing
+$context->{'tree'}[-1]) or during XML_end of a child element, by which time we know
+whether we are dealing with an array or a hash or what.
+
+=item text
+
+Character processing is to insert all the characters into the text element of the
+context for available use later.
+
+=back 4
+
+=head1 METHODS
+
+=cut
+
+use XML::Parser::Expat;
+use Exporter;
+
+use strict;
+use vars qw(@ISA @EXPORT);
+
+ at ISA = qw(Exporter);
+ at EXPORT = qw(read_xml);
+
+sub read_xml
+{
+    my ($font, $fname) = @_;
+
+    my ($xml) = XML::Parser::Expat->new;
+    my ($context) = {'xml' => $xml, 'font' => $font};
+
+    $xml->setHandlers('Start' => sub {
+            my ($x, $tag, %attrs) = @_;
+            my ($context) = $x->{' mycontext'};
+            my ($fn) = $context->{'receiver'}->can('XML_start');
+
+            push(@{$context->{'tree'}}, undef);
+            push(@{$context->{'stack'}}, [$context->{'receiver'}, {%attrs}]);
+            &{$fn}($context->{'receiver'}, $context, $tag, %attrs) if defined $fn;
+        },
+        'End' => sub {
+            my ($x, $tag) = @_;
+            my ($context) = $x->{' mycontext'};
+            my ($fn) = $context->{'receiver'}->can('XML_end');
+            my ($stackinfo) = pop(@{$context->{'stack'}});
+            my ($current, $res);
+
+            $context->{'receiver'} = $stackinfo->[0];
+            $context->{'text'} =~ s/^\s*(.*?)\s*$/$1/o;
+            $res = &{$fn}($context->{'receiver'}, $context, $tag, %{$stackinfo->[1]}) if defined $fn;
+            $current = pop(@{$context->{'tree'}});
+            $current = $context->{'text'} unless (defined $current);
+            $context->{'text'} = '';
+
+            if (defined $res)
+            {
+                return if ($res eq $context);
+                $current = $res;
+            }
+            return unless $#{$context->{'tree'}} >= 0;
+            if ($tag eq 'elem')
+            {
+                $context->{'tree'}[-1] = [] unless defined $context->{'tree'}[-1];
+                push (@{$context->{'tree'}[-1]}, $current);
+            } else
+            {
+                $context->{'tree'}[-1] = {} unless defined $context->{'tree'}[-1];
+                $context->{'tree'}[-1]{$tag} = $current;
+            }
+        },
+        'Char' => sub {
+            my ($x, $str) = @_;
+            $x->{' mycontext'}{'text'} .= $str;
+        });
+
+    $xml->{' mycontext'} = $context;
+
+    $context->{'receiver'} = $font;
+    if (ref $fname)
+    { return $xml->parse($fname); }
+    else
+    { return $xml->parsefile($fname); }
+}
+
+

Modified: packages/libfont-ttf-perl/trunk/lib/ttfmod.pl
===================================================================
--- packages/libfont-ttf-perl/trunk/lib/ttfmod.pl	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/lib/ttfmod.pl	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,174 +1,174 @@
-#       Title:      TTFMOD.PL
-#       Author:     M. Hosken
-#       Description:    Read TTF file calling user functions for each table
-#                       and output transformed tables to new TTF file.
-#       Useage:     TTFMOD provides the complete control loop for processing
-#                   the TTF files.  All that the caller need supply is an
-#                   associative array of functions to call keyed by the TTF
-#                   table name and the two filenames.
-#
-#           &ttfmod($infile, $outfile, *fns [, @must]);
-#
-#                   *fns is an associative array keyed by table name with
-#                   values of the name of the subroutine in package main to
-#                   be called to transfer the table from INFILE to OUTFILE.
-#                   The subroutine is called with the following parameters and
-#                   expected return values:
-#
-#           ($len, $csum) = &sub(*INFILE, *OUTFILE, $len);
-#
-#                   INFILE and OUTFILE are the input and output streams, $len
-#                   is the length of the table according to the directory.
-#                   The return values are $len = new length of table to be
-#                   given in the table directory.  $csum = new value of table
-#                   checksum.  A way to test that this is correct is to
-#                   checksum the whole file (e.g. using CSUM.BAT) and to
-#                   ensure that the value is 0xB1B0AFBA according to a 32 bit
-#                   checksum calculated bigendien.
-#
-#                   @must consists of a list of tables which must exist in the
-#                   final output file, either by being there alread or by being
-#                   inserted.
-#
-# Modifications:
-# MJPH  1.00    22-SEP-1994     Original
-# MJPH  1.1     18-MAR-1998     Added @must to ttfmod()
-# MJPH  1.1.1   25-MAR-1998     Added $csum to copytab (to make reusable)
-
-package ttfmod;
-
-sub main'ttfmod {
-    local($infile, $outfile, *fns, @must) = @_;
-
-    # open files as binary.  Notice OUTFILE is opened for update not just write
-    open(INFILE, "$infile") || die "Unable top open \"$infile\" for reading";
-    binmode INFILE;
-    open(OUTFILE, "+>$outfile") || die "Unable to open \"$outfile\" for writing";
-    binmode OUTFILE;
-
-    seek(INFILE, 0, 0);
-    read(INFILE, $dir_head, 12) || die "Reading table header";
-    ($dir_num) = unpack("x4n", $dir_head);
-    print OUTFILE $dir_head;
-    # read and unpack table directory
-    for ($i = 0; $i < $dir_num; $i++)
-        {
-        read(INFILE, $dir_val, 16) || die "Reading table entry";
-        $dir{unpack("a4", $dir_val)} = join(":", $i, unpack("x4NNN", $dir_val));
-        print OUTFILE $dir_val;
-        printf STDERR "%s %08x\n", unpack("a4", $dir_val), unpack("x8N", $dir_val)
-                if (defined $main'opt_z);
-        }
-    foreach $n (@must)
-    {
-        next if defined $dir{$n};
-        $dir{$n} = "$i:0:-1:0";
-        $i++; $dir_num++;
-        print OUTFILE pack("a4NNN", $n, 0, -1, 0);
-    }
-    substr($dir_head, 4, 2) = pack("n", $dir_num);
-    $csum = unpack("%32N*", $dir_head);
-    $off = tell(OUTFILE);
-    seek(OUTFILE, 0, 0);
-    print OUTFILE $dir_head;
-    seek (OUTFILE, $off, 0);
-    # process tables in order they occur in the file
-    @dirlist = sort byoffset keys(%dir);
-    foreach $tab (@dirlist)
-        {
-        @tab_split = split(':', $dir{$tab});
-        seek(INFILE, $tab_split[2], 0);         # offset
-        $tab_split[2] = tell(OUTFILE);
-        if (defined $fns{$tab})
-            {
-            $temp = "main'$fns{$tab}";
-            ($dir_len, $sum) = &$temp(*INFILE, *OUTFILE, $tab_split[3]);
-            }
-        else
-            {
-            ($dir_len, $sum) = &copytab(*INFILE, *OUTFILE, $tab_split[3]);
-            }
-        $tab_split[3] = $dir_len;               # len
-        $tab_split[1] = $sum;                   # checksum
-        $out_dir{$tab} = join(":", @tab_split);
-        }
-    # now output directory in same order as original directory
-    @dirlist = sort byindex keys(%out_dir);
-    foreach $tab (@dirlist)
-        {
-        @tab_split = split(':', $out_dir{$tab});
-        seek (OUTFILE, 12 + $tab_split[0] * 16, 0);     # directory index
-        print OUTFILE pack("A4N3", $tab, @tab_split[1..3]);
-        foreach $i (1..3, 1)        # checksum directory values with csum twice
-            {
-            $csum += $tab_split[$i];
-    # this line ensures $csum stays within 32 bit bounds, clipping as necessary
-            if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
-            }
-    # checksum the tag
-        $csum += unpack("N", $tab);
-        if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
-        }
-    # handle main checksum
-    @tab_split = split(':', $out_dir{"head"});
-    seek(OUTFILE, $tab_split[2], 0);
-    read(OUTFILE, $head_head, 12);          # read first bit of "head" table
-    @head_split = unpack("N3", $head_head);
-    $tab_split[1] -= $head_split[2];        # subtract old checksum
-    $csum -= $head_split[2] * 2;            # twice because had double effect
-                                            # already
-    if ($csum < 0 ) { $csum += 0xffffffff; $csum++; }
-    $head_split[2] = 0xB1B0AFBA - $csum;    # calculate new checksum
-    seek (OUTFILE, 12 + $tab_split[0] * 16, 0);
-    print OUTFILE pack("A4N3", "head", @tab_split[1..3]);
-    seek (OUTFILE, $tab_split[2], 0);       # rewrite first bit of "head" table
-    print OUTFILE pack("N3", @head_split);
-
-    # finish up
-    close(OUTFILE);
-    close(INFILE);
-    }
-
-# support function for sorting by table offset
-sub byoffset {
-    @t1 = split(':', $dir{$a});
-    @t2 = split(':', $dir{$b});
-    return 1 if ($t1[2] == -1);     # put inserted tables at the end
-    return -1 if ($t2[2] == -1);
-    return $t1[2] <=> $t2[2];
-    }
-
-# support function for sorting by directory entry order
-sub byindex {
-    $t1 = split(':', $dir{$a}, 1);
-    $t2 = split(':', $dir{$b}, 1);
-    return $t1 <=> $t2;
-    }
-
-# default table action: copies a table from input to output, recalculating
-#   the checksum (just to be absolutely sure).
-sub copytab {
-    local(*INFILE, *OUTFILE, $len, $csum) = @_;
-
-    while ($len > 0)
-        {
-        $count = ($len > 8192) ? 8192 : $len;       # 8K buffering
-        read(INFILE, $buf, $count) == $count || die "Copying";
-        $buf .= "\0" x (4 - ($count & 3)) if ($count & 3);      # pad to long
-        print OUTFILE $buf;
-        $csum += unpack("%32N*", $buf);
-        if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
-        $len -= $count;
-        }
-    ($_[2], $csum);
-    }
-
-# test routine to copy file from input to output, no changes
-package main;
-
-if ($test_package)
-    {
-    &ttfmod($ARGV[0], $ARGV[1], *dummy);
-    }
-else
-    { 1; }
+#       Title:      TTFMOD.PL
+#       Author:     M. Hosken
+#       Description:    Read TTF file calling user functions for each table
+#                       and output transformed tables to new TTF file.
+#       Useage:     TTFMOD provides the complete control loop for processing
+#                   the TTF files.  All that the caller need supply is an
+#                   associative array of functions to call keyed by the TTF
+#                   table name and the two filenames.
+#
+#           &ttfmod($infile, $outfile, *fns [, @must]);
+#
+#                   *fns is an associative array keyed by table name with
+#                   values of the name of the subroutine in package main to
+#                   be called to transfer the table from INFILE to OUTFILE.
+#                   The subroutine is called with the following parameters and
+#                   expected return values:
+#
+#           ($len, $csum) = &sub(*INFILE, *OUTFILE, $len);
+#
+#                   INFILE and OUTFILE are the input and output streams, $len
+#                   is the length of the table according to the directory.
+#                   The return values are $len = new length of table to be
+#                   given in the table directory.  $csum = new value of table
+#                   checksum.  A way to test that this is correct is to
+#                   checksum the whole file (e.g. using CSUM.BAT) and to
+#                   ensure that the value is 0xB1B0AFBA according to a 32 bit
+#                   checksum calculated bigendien.
+#
+#                   @must consists of a list of tables which must exist in the
+#                   final output file, either by being there alread or by being
+#                   inserted.
+#
+# Modifications:
+# MJPH  1.00    22-SEP-1994     Original
+# MJPH  1.1     18-MAR-1998     Added @must to ttfmod()
+# MJPH  1.1.1   25-MAR-1998     Added $csum to copytab (to make reusable)
+
+package ttfmod;
+
+sub main'ttfmod {
+    local($infile, $outfile, *fns, @must) = @_;
+
+    # open files as binary.  Notice OUTFILE is opened for update not just write
+    open(INFILE, "$infile") || die "Unable top open \"$infile\" for reading";
+    binmode INFILE;
+    open(OUTFILE, "+>$outfile") || die "Unable to open \"$outfile\" for writing";
+    binmode OUTFILE;
+
+    seek(INFILE, 0, 0);
+    read(INFILE, $dir_head, 12) || die "Reading table header";
+    ($dir_num) = unpack("x4n", $dir_head);
+    print OUTFILE $dir_head;
+    # read and unpack table directory
+    for ($i = 0; $i < $dir_num; $i++)
+        {
+        read(INFILE, $dir_val, 16) || die "Reading table entry";
+        $dir{unpack("a4", $dir_val)} = join(":", $i, unpack("x4NNN", $dir_val));
+        print OUTFILE $dir_val;
+        printf STDERR "%s %08x\n", unpack("a4", $dir_val), unpack("x8N", $dir_val)
+                if (defined $main'opt_z);
+        }
+    foreach $n (@must)
+    {
+        next if defined $dir{$n};
+        $dir{$n} = "$i:0:-1:0";
+        $i++; $dir_num++;
+        print OUTFILE pack("a4NNN", $n, 0, -1, 0);
+    }
+    substr($dir_head, 4, 2) = pack("n", $dir_num);
+    $csum = unpack("%32N*", $dir_head);
+    $off = tell(OUTFILE);
+    seek(OUTFILE, 0, 0);
+    print OUTFILE $dir_head;
+    seek (OUTFILE, $off, 0);
+    # process tables in order they occur in the file
+    @dirlist = sort byoffset keys(%dir);
+    foreach $tab (@dirlist)
+        {
+        @tab_split = split(':', $dir{$tab});
+        seek(INFILE, $tab_split[2], 0);         # offset
+        $tab_split[2] = tell(OUTFILE);
+        if (defined $fns{$tab})
+            {
+            $temp = "main'$fns{$tab}";
+            ($dir_len, $sum) = &$temp(*INFILE, *OUTFILE, $tab_split[3]);
+            }
+        else
+            {
+            ($dir_len, $sum) = &copytab(*INFILE, *OUTFILE, $tab_split[3]);
+            }
+        $tab_split[3] = $dir_len;               # len
+        $tab_split[1] = $sum;                   # checksum
+        $out_dir{$tab} = join(":", @tab_split);
+        }
+    # now output directory in same order as original directory
+    @dirlist = sort byindex keys(%out_dir);
+    foreach $tab (@dirlist)
+        {
+        @tab_split = split(':', $out_dir{$tab});
+        seek (OUTFILE, 12 + $tab_split[0] * 16, 0);     # directory index
+        print OUTFILE pack("A4N3", $tab, @tab_split[1..3]);
+        foreach $i (1..3, 1)        # checksum directory values with csum twice
+            {
+            $csum += $tab_split[$i];
+    # this line ensures $csum stays within 32 bit bounds, clipping as necessary
+            if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
+            }
+    # checksum the tag
+        $csum += unpack("N", $tab);
+        if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
+        }
+    # handle main checksum
+    @tab_split = split(':', $out_dir{"head"});
+    seek(OUTFILE, $tab_split[2], 0);
+    read(OUTFILE, $head_head, 12);          # read first bit of "head" table
+    @head_split = unpack("N3", $head_head);
+    $tab_split[1] -= $head_split[2];        # subtract old checksum
+    $csum -= $head_split[2] * 2;            # twice because had double effect
+                                            # already
+    if ($csum < 0 ) { $csum += 0xffffffff; $csum++; }
+    $head_split[2] = 0xB1B0AFBA - $csum;    # calculate new checksum
+    seek (OUTFILE, 12 + $tab_split[0] * 16, 0);
+    print OUTFILE pack("A4N3", "head", @tab_split[1..3]);
+    seek (OUTFILE, $tab_split[2], 0);       # rewrite first bit of "head" table
+    print OUTFILE pack("N3", @head_split);
+
+    # finish up
+    close(OUTFILE);
+    close(INFILE);
+    }
+
+# support function for sorting by table offset
+sub byoffset {
+    @t1 = split(':', $dir{$a});
+    @t2 = split(':', $dir{$b});
+    return 1 if ($t1[2] == -1);     # put inserted tables at the end
+    return -1 if ($t2[2] == -1);
+    return $t1[2] <=> $t2[2];
+    }
+
+# support function for sorting by directory entry order
+sub byindex {
+    $t1 = split(':', $dir{$a}, 1);
+    $t2 = split(':', $dir{$b}, 1);
+    return $t1 <=> $t2;
+    }
+
+# default table action: copies a table from input to output, recalculating
+#   the checksum (just to be absolutely sure).
+sub copytab {
+    local(*INFILE, *OUTFILE, $len, $csum) = @_;
+
+    while ($len > 0)
+        {
+        $count = ($len > 8192) ? 8192 : $len;       # 8K buffering
+        read(INFILE, $buf, $count) == $count || die "Copying";
+        $buf .= "\0" x (4 - ($count & 3)) if ($count & 3);      # pad to long
+        print OUTFILE $buf;
+        $csum += unpack("%32N*", $buf);
+        if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; }
+        $len -= $count;
+        }
+    ($_[2], $csum);
+    }
+
+# test routine to copy file from input to output, no changes
+package main;
+
+if ($test_package)
+    {
+    &ttfmod($ARGV[0], $ARGV[1], *dummy);
+    }
+else
+    { 1; }

Deleted: packages/libfont-ttf-perl/trunk/pmake.bat
===================================================================
--- packages/libfont-ttf-perl/trunk/pmake.bat	2005-05-25 15:18:17 UTC (rev 1049)
+++ packages/libfont-ttf-perl/trunk/pmake.bat	2005-05-25 15:22:16 UTC (rev 1050)
@@ -1,85 +0,0 @@
- at rem = '--*-Perl-*--
- at echo off
-if "%OS%" == "Windows_NT" goto WinNT
-perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
-goto endofperl
-:WinNT
-perl -x -S "%0" %*
-if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
-if %errorlevel% == 9009 echo You do not have Perl in your PATH.
-if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
-goto endofperl
- at rem ';
-#!/usr/local/bin/perl -w
-#line 15
-use 5.005;  # Need look-behind assertions
-
-use Getopt::Std;
-use Make;
-
-my %opt;
-
-getopts('Dgnpf:j:C:',\%opt);
-
-my $info = Make->new(GNU      => $opt{'g'}, 
-                     Override => { MAKE => "$^X $0" },
-                     Makefile => $opt{'f'}, 
-                     Jobs     => $opt{'j'},
-                     Dir      => $opt{'C'});
-
-if ($opt{'D'})
- {
-  require Data::Dumper;
-  print Data::Dumper::DumperX($info);
-  exit;
- }
-
-if ($opt{'p'})
- {
-  $info->Print(@ARGV);  
-  exit;
- }
-if ($opt{'n'})
- {
-  $info->Script(@ARGV);
- }
-else
- {
-  $info->Make(@ARGV);
- }
-
-=head1 NAME
-
-pmake - a perl 'make' replacement
-
-=head1 SYNOPSIS
-
-	pmake [-n] [-g] [-p] [-C directory] targets
-
-=head1 DESCRIPTION
-
-Performs the same function as make(1) but is written entirely in perl.
-A subset of GNU make extensions is supported.
-For details see L<Make> for the underlying perl module.
-
-=head1 BUGS
-
-=item *
-
-No B<-k> flag
-
-I strongly suspect there are lots more.
-
-=head1 SEE ALSO
-
-L<Make>, make(1)
-
-=head1 AUTHOR
-
-Nick Ing-Simmons 
-
-=cut
-
-
-__END__
-:endofperl




More information about the Pkg-perl-cvs-commits mailing list