diff options
author | Karl Berry <karl@freefriends.org> | 2012-04-16 23:15:11 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-04-16 23:15:11 +0000 |
commit | e8a389a2d60b6ff53118a05f72c266fc3bd725b0 (patch) | |
tree | a684b2e593b0f7cede10362be9fe321f733e1acc /Build/source/texk | |
parent | c3c415e17085b0a75a89e652d576f6a943a41649 (diff) |
fontools (6mar12)
git-svn-id: svn://tug.org/texlive/trunk@25995 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk')
7 files changed, 2237 insertions, 7570 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/fontools/afm2afm b/Build/source/texk/texlive/linked_scripts/fontools/afm2afm index 80ca105ed90..87d6ef1bbb4 100755 --- a/Build/source/texk/texlive/linked_scripts/fontools/afm2afm +++ b/Build/source/texk/texlive/linked_scripts/fontools/afm2afm @@ -1,115 +1,291 @@ -#!/usr/bin/perl +#! /usr/bin/env perl -use Getopt::Std; -use integer; -use warnings; no warnings qw(uninitialized); +=begin COPYRIGHT -getopts "e:o:", \%options; +---------------------------------------------------------------------------- -$0 =~ s!.*/!!; -die "Usage: $0 -e encoding [-o output] afmfile\n" if - @ARGV != 1 or !$options{e}; + Copyright (C) 2005-2012 Marc Penninga. -if ($options{o} and -e $options{o}) { - die "$0: output file exists\n"; + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to + Free Software Foundation, Inc., + 59 Temple Place, + Suite 330, + Boston, MA 02111-1307, + USA + +---------------------------------------------------------------------------- + +=end COPYRIGHT + +=cut + +use strict; +use warnings; + +use File::Basename; +use Getopt::Long; +use Pod::Usage; + +use v5.10; + +parse_commandline(); + +my $afm = read_afm($ARGV[0]); + +# If user specified encoding, use that; else, use encoding from .afm file +my $enc = $ARGV{encoding} ? read_enc($ARGV{encoding}) + : get_enc($afm) + ; +# Make lookup table to quickly see if a character is present in the encoding +my %char_in_enc = map { ($_ => 1) } @{$enc->{vector}}; + +print_fontinfo($afm->{fontinfo}, $enc->{scheme}); +print_charmetrics($afm->{metrics}, $enc->{vector}); +print_kerndata($afm->{kernpairs}, $afm->{trackkerns}, \%char_in_enc); +print_composites($afm->{composites}, \%char_in_enc); +print "EndFontMetrics\n"; + +close select *STDOUT if $ARGV{output}; + +print_mapentry($afm->{fontinfo}, , $enc->{scheme}) + if $ARGV{encoding} && $ARGV{output}; + +#----------------------------------------------------------------------- +# +#----------------------------------------------------------------------- +sub parse_commandline { + Getopt::Long::GetOptions( + 'help|?' => sub { pod2usage(-verbose => 1) }, + 'encoding=s' => \$ARGV{encoding}, + 'output=s' => \$ARGV{output}, + ) + or pod2usage(-verbose => 0); + + pod2usage(-verbose => 0) if @ARGV != 1; + + if ($ARGV{output}) { + $ARGV{output} .= '.afm' unless $ARGV{output} =~ m/[.]afm\z/xms; + open my $output, '>', $ARGV{output} + or die "[ERROR] can't open '$ARGV{output}': $!"; + select $output; + } + + return; } -if ((chop($fn = `kpsewhich $ARGV[0] 2>&1`) and -e $fn) or - (chop($fn = `findtexmf $ARGV[0] 2>&1`) and -e $fn)) -{ - open AFM, "<$fn" or die "Error: can't open `$fn' - $!\n"; -} -else { - open AFM, "<$ARGV[0]" or - die "Error: can't open `$ARGV[0]' - $!\n"; +#----------------------------------------------------------------------- +# +#----------------------------------------------------------------------- +sub read_afm { + my $filename = shift; + open my $afmfile, '<', $filename + or die "[ERROR] can't open '$filename': $!"; + + my %afm = ( + fontinfo => [], + metrics => [], + kernpairs => [], + trackkerns => [], + composites => [], + ); + + until ((my $line = <$afmfile>) =~ m/StartCharMetrics/xms) { + push @{$afm{fontinfo}}, $line; + } + + for (<$afmfile>) { + when (m/\A\s* C \s/xms) { push @{$afm{metrics}}, $_ } + when (m/\A\s* KPX \s/xms) { push @{$afm{kernpairs}}, $_ } + when (m/\A\s* TrackKern \s/xms) { push @{$afm{trackkerns}}, $_ } + when (m/\A\s* CC \s/xms) { push @{$afm{composites}}, $_ } + } + + close $afmfile; + + return \%afm; } -{ - local $/; - $_ = <AFM>; + +#----------------------------------------------------------------------- +# Get encoding name and vector from the specified .enc file +#----------------------------------------------------------------------- +sub read_enc { + my $filename = shift; + + open my $encfile, '<', $filename + or die "[ERROR] can't open '$filename': $!"; + my $data = join ' ', map { s/%.+|\n//xmsg; $_ } <$encfile>; + close $encfile; + + my ($scheme, $encoding) + = $data =~ m{ /([-\w]+) \s* [[] (.+) []] \s* def }xms + or die "[ERROR] parsing encoding file '$filename' failed"; + + return { scheme => $scheme, + vector => [ $encoding =~ m{ /([.\w]+) }xmsg ], + }; } -$Time = localtime; -$FontInfo = /(.*)StartCharMetrics/s ? $1 : ""; -$FontInfo =~ s/(?<=Comment ).*?$/Reencoded at $Time by $0 from $ARGV[0]/m; -$FontInfo =~ s/(?<=ItalicAngle )([\d.]+)/{$1 >= 32768 ? $1 - 65536 : $1}/me; -$FontInfo =~ s/\r+\n/\n/g; -if ($FontInfo =~ /FontName\s+([\w-]+)/) {$FontName = $1} -else {warn "Warning: no FontName found in file `$ARGV[0]'\n"} - -for (/(WX.*?$)/gm) {/N\s+([\w.]+)/ and $WX{$1} = $_} -for (/(KPX.*?$)/gm) {/\s+([\w.]+)\s+([\w.]+)\s+(-?\d+)/ and $KPX{$1}{$2} = $3} - -if ((chop($fn = `kpsewhich $options{e} 2>&1`) and -e $fn) or - (chop($fn = `findtexmf $options{e} 2>&1`) and -e $fn)) -{ - open ENC, "<$fn" or die "Error: can't open `$fn' - $!\n"; -} -else { - open ENC, "<$options{e}" or - die "Error: can't open `$options{e}' - $!\n"; +#----------------------------------------------------------------------- +# Get encoding from the input .afm file +#----------------------------------------------------------------------- +sub get_enc { + my $afm = shift; + + my %enc = ( scheme => 'FontSpecific', vector => [ ('/.undef') x 256 ] ); + + for my $line (@{$afm->{fontinfo}}) { + if ($line =~ m/EncodingScheme \s+ ([-\w]+)/xms) { + $enc{scheme} = $1; + last; + } + } + for my $line (@{$afm->{metrics}}) { + my ($pos, $name) + = $line =~ m/C \s+ ([-]?\d+) .+? N \s+ ([.\w]+)/xms + or die; + $enc{vector}[$pos] = $name unless $pos == -1; + } + + return \%enc; } -chop(@lines = <ENC>); -map s!%.*!!, @lines; -$_ = join "", @lines; -($n, $_) = m!/([\w-]+) \s* \[(.*)\] \s+ def!x; -@vector = m!([\w.]+)!g; - -for $i (0 .. $#vector) { - next if $vector[$i] eq ".notdef"; - if ($WX{$vector[$i]} =~ /WX\s+(-?\d+).*?N\s+([\w.]+).*?B\s+(.*?)\s+;/) { - ($WX, $N, $B) = ($1, $2, $3); - push @WX, "C $i ; WX $WX ; N $N ; B $B ;\n"; + +#----------------------------------------------------------------------- +# +#----------------------------------------------------------------------- +sub print_fontinfo { + my ($fontinfo, $scheme) = @_; + + for my $line (@$fontinfo) { + $line = "EncodingScheme $scheme\n" + if $line =~ m/EncodingScheme/xms; + print $line; } - for $j (0 .. $#vector) { - next if $vector[$j] eq ".notdef"; - next unless $KPX{$vector[$i]}{$vector[$j]}; - push @KPX, - "KPX $vector[$i] $vector[$j] $KPX{$vector[$i]}{$vector[$j]}\n"; + + return; +} + +#----------------------------------------------------------------------- +# Print character metrics for characters in specified encoding +#----------------------------------------------------------------------- +sub print_charmetrics { + my ($metrics, $vector) = @_; + + my %metrics = map { m/(WX .+? N \s+ ([.\w]+) .+)/xms; ($2 => $1) } + @$metrics; + + print "StartCharMetrics @{[ scalar grep { $metrics{$_} } @$vector ]}\n"; + for my $i (0 .. 255) { + next unless $metrics{$vector->[$i]}; + print "C $i ; $metrics{$vector->[$i]}"; } + print "EndCharMetrics\n"; + + return; } -if ($options{o}) { - ($e = $options{e}) =~ s!.*/!!; - ($f = $ARGV[0]) =~ s!.*/|\.afm!!g; - ($o = $options{o}) =~ s!.*/|\.afm!!g; - - $x = "pfb"; - for (qw(pfb pfa ttf otf)) { - if (-e "$f.$_" or - (chop($fn = `kpsewhich "$f.$_" 2>&1`) and -e $fn) or - (chop($fn = `findtexmf "$f.$_" 2>&1`) and -e $fn)) - { - $x = $_; - last; - } +#----------------------------------------------------------------------- +# Print kerning data for characters in specified encoding +#----------------------------------------------------------------------- +sub print_kerndata { + my ($kernpairs, $trackkerns, $char_in_enc) = @_; + + my @kernpairs = grep { m/\A\s* KPX \s+ ([.\w]+) \s+ ([.\w]+)/xms + and $char_in_enc->{$1} + and $char_in_enc->{$2} + } + @$kernpairs; + + if (@kernpairs || @$trackkerns) { + print "StartKernData\n"; + if (@kernpairs) { + print "StartKernPairs @{[ scalar @kernpairs ]}\n"; + print @kernpairs; + print "EndKernPairs\n"; + } + if (@$trackkerns) { + print "StartTrackKern @{[ scalar @$trackkerns ]}\n"; + print @$trackkerns; + print "EndTrackKern\n"; + } + print "EndKernData\n"; } - print qq($o $FontName <$f.$x <[$e "$n ReEncodeFont"\n); - - if (open OUT, ">$options{o}") { - select OUT; + + return; +} + +#----------------------------------------------------------------------- +# Print "composite" info for characters in specified encoding +#----------------------------------------------------------------------- +sub print_composites { + my ($composites, $char_in_enc) = @_; + + # Each line mentions several characters: the composite and two or more + # 'base' characters. We only print the line if all characters are + # present in the specified encoding + my @composites; + COMPOSITE: + for my $composite (@$composites) { + my @chars = $composite =~ m/(?:CC \s+ ([.\w]+))/xmsg; + for my $char (@chars) { + next COMPOSITE unless $char_in_enc->{$char}; + } + push @composites, $composite; } - else { - warn "Warning: can't create `$options{o}' - $!\n", - " printing to <STDOUT> instead\n"; + + if (@composites) { + print "StartComposites @{[ scalar @composites ]}\n"; + print @composites; + print "EndComposites\n"; } + + return; } -$WX = @WX; -$KPX = @KPX; -print <<EOF; -$FontInfo -StartCharMetrics $WX - @{WX}EndCharMetrics +#----------------------------------------------------------------------- +# +#----------------------------------------------------------------------- +sub print_mapentry { + my ($fontinfo, $scheme) = @_; + + my $fontname = ''; + (my $fontfile = basename($ARGV[0] // '')) =~ s/[.]afm\z//xms; + (my $output = basename($ARGV{output} // '')) =~ s/[.]afm\z//xms; + + for my $line (@$fontinfo) { + if ($line =~ m/FontName \s+ ([-\w]+)/xms) { + $fontname = $1; + last; + } + } -StartKernData -StartKernPairs $KPX - @{KPX}EndKernPairs -EndKernData -EndFontMetrics -EOF + print {*STDOUT} qq(${output} ${fontname} <${fontfile}.pfb ), + qq(<[$ARGV{encoding} "${scheme} ReEncodeFont"\n); + + return; + +} __END__ + +############################################################################ + + To create the documentation: + + pod2man --center="Marc Penninga" --release="fontools" --section=1 \ + afm2afm - | groff -Tps -man - | ps2pdf - afm2afm.pdf + =pod =head1 NAME @@ -118,53 +294,103 @@ afm2afm - reencode an F<afm> file =head1 SYNOPSIS -afm2afm B<-e> I<encoding> [B<-o> I<output>] I<afmfile> +=over 8 + +=item B<afm2afm> + +[B<-help>] +[B<-encoding> I<encodingfile>] +[B<-output> I<outputfile>] +B<afmfile> + +=back + =head1 DESCRIPTION -This program reencodes an F<afm> file. It's mainly intended to be used with -F<afm> files that were extracted from TrueType or OpenType fonts, since these -are often too big to be handled with tools like F<fontinst> (Adobe's -CaflischScriptPro-Regular font, for example, contains 1289 glyphs and -278678 kerning pairs, leading to an F<afm> file of nearly 9MB). +B<afm2afm> re-encodes an F<afm> file. + +Metrics (including kerning data) for characters not present in the +chosen encoding are excluded from the output, which resuls in +much smaller files. -Glyphs that are absent from the chosen encoding aren't written to the output, -which yields much smaller output files. +Note that if you don't specify an encoding file, the F<afm> file +isn't re-encoded, but the unused data is still pruned. -The program also generates an entry for a F<dvips>-style map file. +The program also generates an entry for a F<dvips>-style map file, +but only if the F<afm> file has been re-encoded and +the output was written to file +(i.e., if both the I<-encoding> and I<-output> options were specified). -=head1 OPTIONS -Option names were chosen to match those of F<ttf2afm>. +=head1 OPTIONS AND ARGUMENTS =over 4 -=item B<-e> I<encoding> +=item B<-help> -Reencode using the encoding given in file I<encoding>. +Print a short description of the syntax -=item B<-o> I<output> +=item B<-encoding> I<encodingfile> -Write the reencoded F<afm> to file I<output> instead of C<stdout>. -The mapfile entry will still be written to C<stdout>. +Re-encode to the enconding in I<encodingfile> -=back +=item B<-output> I<outputfile> + +Write the result to I<outputfile> instead of C<stdout>. -=head1 FILES +=item B<afmfile> -All input files are searched using B<kpsewhich> or B<findtexmf> when these -commands are available; otherwise only the current working directory -is searched. +The F<afm> file to be re-encoded. -=head1 SEE ALSO +=back + +Option names may be shortened to a unique prefix. -F<autoinst>, F<cmap2enc>, F<font2afm>, F<ot2kpx>, F<pfm2kpx>. =head1 AUTHOR -Marc Penninga <marc@penninga.info> +Marc Penninga <marcpenninga@gmail.com> + + +=head1 COPYRIGHT + +Copyright (C) 2005-2012 Marc Penninga. + + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published +by the Free Software Foundation, either version 2 of the License, +or (at your option) any later version. +A copy of the GNU General Public License is included with B<autoinst>; +see the file F<GPLv2.txt>. + + +=head1 DISCLAIMER + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + + +=head1 RECENT CHANGES + +(See the source code for the rest of the story.) + +=over 12 + +=item I<2012-02-01> + +Refactored the code; added the "no re-encoding, only pruning" +functionality. + +=back + -=head1 HISTORY +=begin Really_old_history =over 12 @@ -190,8 +416,8 @@ Input files searched using B<kpsewhich> or B<findtexmf> (if available) =item I<2005-04-15> -Updated creation of mapfile entry; look for font file to deduce the correct -font file format (pfb, pfa, ttf). If no font file is found, +Updated creation of mapfile entry; look for font file to deduce the correct +font file format (pfb, pfa, ttf). If no font file is found, pfb is assumed. =item I<2005-04-20> diff --git a/Build/source/texk/texlive/linked_scripts/fontools/autoinst b/Build/source/texk/texlive/linked_scripts/fontools/autoinst index d9b0665ebf1..52fe14b65b4 100755 --- a/Build/source/texk/texlive/linked_scripts/fontools/autoinst +++ b/Build/source/texk/texlive/linked_scripts/fontools/autoinst @@ -4,13 +4,12 @@ ---------------------------------------------------------------------------- - Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 Marc Penninga. + Copyright (C) 2005-2012 Marc Penninga. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License - as published by the Free Software Foundation, - either version 2 of the License, or (at your option) - any later version. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 2 + of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,11 +17,11 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to - Free Software Foundation, Inc., - 59 Temple Place, - Suite 330, - Boston, MA 02111-1307, + along with this program; if not, write to + Free Software Foundation, Inc., + 59 Temple Place, + Suite 330, + Boston, MA 02111-1307, USA ---------------------------------------------------------------------------- @@ -34,114 +33,107 @@ use strict; use warnings; -use Getopt::Long; +use File::Path (); +use File::Spec (); +use Getopt::Long (); +my ($d, $m, $y) = (localtime time)[3 .. 5]; +my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d; -my $USAGE =<<'END_USAGE'; - -'autoinst' is a wrapper around Eddie Kohler's TypeTools -(http://www.lcdf.org/type/), for installing OpenType fonts in LaTeX. - -Usage: autoinst [options] font[s] - -Possible options: - --encoding=ENC[,ENC] Use ENC as text encoding(s) (default: LY1) - - --(no)ts1 Toggle creation of TS1 fonts - --(no)smallcaps Toggle creation of smallcaps shape - --(no)swash Toggle creation of swash shape - --(no)titling Toggle creation of titling shape - --(no)superiors Toggle creation of fonts with superior characters - --(no)inferiors Toggle creation of fonts with inferior characters - --(no)ornaments Toggle creation of ornament fonts - --(no)fractions Toggle creation of fonts with digits for fractions - - --sanserif Install font as sanserif font - --typewriter Install font as typewriter font - --manual Manual mode (see documentation) - --extra="TEXT" Add TEXT to the command line for 'otftotfm' - - --help Print this text - --verbose Make some noise - - font[s] The fonts (either .otf or .ttf) to install. - -Please report any bugs or suggestions to <marc@penninga.info>. -END_USAGE +=begin Comment + The next three tables map the names of weights, widths and shapes + to NFSS codes. New entries can be added, but the names should be + all lowercase. Also make sure that the NFSS 'series' attribute + (the concatenation of weight and width) is unique! -=begin Comment + The 'book' and 'regular' weights and the 'regular' width are mapped + to an empty string rather than 'm', because the 'm' disappears when + weight and width are combined into the NFSS series (unless *both* are + 'regular', but we deal with that case separately). - The next three tables map the names of weights, widths and shapes - to NFSS codes. New entries can be added without problems, - as long as the name is in all lowercase. - The 'book' and 'regular' weights and the 'regular' width are mapped - to an empty string rather than 'm', because the 'm' disappears when - weight and width are combined into the NFSS series (unless both are - 'regular', but we deal with that case later on). The 'oblique' (aka 'slanted') shape is mapped to 'it' to make things - easier for ourselves. This means the program will fail for font - families that have both italic and oblique shapes, but I doubt + easier for ourselves. This means the program will fail for + font families that have both italic and oblique shapes, but I doubt whether these exist (apart from Computer Modern, of course). - + =end Comment =cut my %FD_WEIGHT = ( - thin => 't', - ultralight => 'ul', - extralight => 'el', - light => 'l', - book => '', - regular => '', - medium => 'mb', - demibold => 'db', - semibold => 'sb', - bold => 'b', - extrabold => 'eb', - black => 'a', # Not 'k': that means 'book' in fontname - extrablack => 'ea', - heavy => 'h', - ultra => 'ub', - ultrabold => 'ub', - ultrablack => 'ua', + thin => 't', + ultralight => 'ul', + extralight => 'el', + light => 'l', + book => '', + regular => '', + medium => 'mb', + demibold => 'db', + demi => 'db', + semibold => 'sb', + bold => 'b', + extrabold => 'eb', + ultra => 'ub', + ultrabold => 'ub', + black => 'k', + extrablack => 'ek', + ultrablack => 'uk', + heavy => 'h', + poster => 'r', ); my %FD_WIDTH = ( - ultracondensed => 'uc', - extracondensed => 'ec', - condensed => 'c', - cond => 'c', - semicondensed => 'sc', - regular => '', - semiextended => 'sx', - extended => 'x', + ultracompressed => 'up', + extracompressed => 'ep', + compressed => 'p', + comp => 'p', + cmp => 'p', + compact => 'p', + ultracondensed => 'uc', + extracondensed => 'ec', + condensed => 'c', + cond => 'c', + narrow => 'n', + semicondensed => 'sc', + regular => '', + semiextended => 'sx', + extended => 'x', + expanded => 'e', + wide => 'w', ); my %FD_SHAPE = ( - roman => 'n', - italic => 'it', - it => 'it', # Fix for (at least) some Linotype fonts - oblique => 'it', - slanted => 'it', - romani => 'n', - romanii => 'it', # Map one of Silentium Pro's two roman shapes to 'it' + roman => 'n', + upright => 'n', + italic => 'it', + ita => 'it', + it => 'it', + cursive => 'it', + kursiv => 'it', + inclined => 'it', + incline => 'it', + oblique => 'it', + slanted => 'it', + slant => 'it', + romani => 'n', # Adobe Silentium Pro has two roman shapes; + romanii => 'it', # we map the second one to 'it' ); + =begin Comment - The following tables are used for deciding which font families and shapes + The following tables are used in deciding which font families and shapes to generate. Each hash governs one of these aspects: - 'figure style' (lining, oldstyle, tabular, proportional, superior, inferior etc.); each of these will become a separate font family. - - 'variant' shape (normal, small caps, swash, titling or textcomp). - + - 'shape' (normal, small caps, swash, titling or textcomp). - Each key in the %FIGURE_STYLE hash names a figure style; the corresponding + + Each key in the %STYLE hash names a figure style; the corresponding value is an anonymous hash with four key/value pairs: - reqd A list of required OpenType features; - this style is built if the font supports at least one + reqd A list of required OpenType features; + this style is built if the font supports at least *one* of these features. nice A list of optional OpenType features; these are used if the font supports them, but don't @@ -149,35 +141,35 @@ my %FD_SHAPE = ( extra Extra options passed to otftotfm when creating this style. shape An anonymous array of 'variant' shapes to build with this figure style. - - Ornaments are treated as a separate 'figure style'. - This may seem a bit funny, but is actually the easiest way to do it. - - - Each key in the %SHAPE hash names a 'variant' shape; the corresponding - value is (again) an anonymous hash with several key/value pairs: + + Ornaments are treated as a separate 'figure style'. + This may seem a bit weird, but is actually the easiest way to do it. + + + Each key in the %SHAPE hash names a shape; the corresponding value + is (again) an anonymous hash with several key/value pairs: code An anonymous hash with two possible keys: 'n' -> the NFSS code to use for this variant shape - if the basic shape is upright; + if the 'basic shape' is upright; 'it' -> the NFSS code to use for this variant shape - if the basic shape is italic, slanted or oblique; - If the 'n' ('it') entry is missing, the upright (italic) + if the 'basic shape' is italic, slanted or oblique; + If the 'n' or 'it' entry is missing, the upright or italic version of this variant shape will not be built. - reqd A list of required OpenType features; - this shape is built if the font supports at least one + reqd A list of required OpenType features; + this shape is built if the font supports at least *one* of these features. nice A list of optional OpenType features; these are used if the font supports them, but don't prevent this shape from being built when missing. extra Extra options passed to otftotfm when creating this shape. - name A string added to the name of the generated font, + name A string added to the name of the generated font, to make it unique. - + =end Comment =cut -my %FIGURE_STYLE = ( +my %STYLE = ( TLF => { reqd => [], nice => ['lnum', 'tnum'], @@ -273,329 +265,329 @@ my %SHAPE = ( ); -# The official names -my %CODING_SCHEME = ( - fontools_ly1 => 'TEX TYPEWRITER AND WINDOWS ANSI', - fontools_t1 => 'EXTENDED TEX FONT ENCODING - LATIN', - fontools_ot1 => 'TEX TEXT', - fontools_ts1 => 'TEX TEXT COMPANION SYMBOLS 1---TS1', -); +############################################################################ -# Default values for the command line arguments -%ARGV = ( - encoding => 'LY1', - textcomp => '2', # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no) - manual => '0', # 0 = no, 1 = yes - verbose => '0', # 0 = no, 1 = yes - extra => '', - nfss => 'rm', - smallcaps => '1', # 0 = no, 1 = yes - swash => '1', # 0 = no, 1 = yes - titling => '0', # 0 = no, 1 = yes - superiors => '1', # 0 = no, 1 = yes - inferiors => '0', # 0 = no, 1 = yes - ornaments => '1', # 0 = no, 1 = yes - fractions => '0', # 0 = no, 1 = yes -); -my @time = localtime; -my $date = sprintf "%04d/%02d/%02d", $time[5] + 1900, $time[4] + 1, $time[3]; +#----------------------------------------------------------------------- +# The main routine. What else? +#----------------------------------------------------------------------- +sub main { + ARGV::parse_options(); + + my @fonts = map { Fontinfo::parse_fontinfo($_) } @ARGV; + Fontinfo::assert_unique(@fonts); + + # For each font, figure out the shapes, styles and encodings to generate + my @worklist + = cleanup(expand_encodings(expand_shapes(expand_styles(@fonts)))); + + # Organize the worklist by family, encoding, style, series and shape + my %fddata; + for my $item (@worklist) { + my $family = $item->{font}{family}; + my $encoding = $item->{encoding}[1]; + my $style = $item->{style}; + my $series = $item->{font}{fdseries}; + my $shape = $item->{fdshape}; + my $minsize = $item->{font}{minsize}; + my $maxsize = $item->{font}{maxsize}; + + push @{$fddata{$family}{$encoding}{$style}{$series}{$shape}}, + [ $minsize, $maxsize, $item->{fontname} ]; + } + while (my ($fam, $famdata) = each %fddata) { + LaTeX::write_stylefile($fam, $famdata); + while (my ($enc, $encdata) = each %$famdata) { + while (my ($sty, $stydata) = each %$encdata) { + LaTeX::write_fdfile($fam, $enc, $sty, $stydata); + } + } + } -# ----------------------- subroutine definitions ----------------------- + make_commands(@worklist); + return; +} -sub main { - parse_options(); - - my (%already_seen, %commands, @fd_data, $err_msg); - - FONTFILE: - for my $filename (@ARGV) { - my %fontinfo = read_font_info($filename); - my $unique - = join ',', @fontinfo{qw(family width weight shape min max)}; - if ( $already_seen{$unique} - and $already_seen{$unique} ne $filename) { - $err_msg .= <<"END_PARSE_ERROR"; - -ERROR: I've parsed both '$already_seen{$unique}' - and '$filename' as - - Family $fontinfo{family} - Width $fontinfo{width} - Weight $fontinfo{weight} - Shape $fontinfo{shape} - Size $fontinfo{min}-$fontinfo{max} -END_PARSE_ERROR - } - else { - $already_seen{$unique} = $filename; - } +#----------------------------------------------------------------------- +# Determine which figure styles to create for each font; +# return a list of (font, style) tuples +#----------------------------------------------------------------------- +sub expand_styles { + return map { my $font = $_; + map { { font => $font, style => $_ } } + grep { has_reqd($font, $STYLE{$_}) } + keys %STYLE + } + @_; +} - FIGURE_STYLE: - for my $figure_style (keys %FIGURE_STYLE) { - - # Does the font support this figure style? - if ( @{$FIGURE_STYLE{$figure_style}{reqd}} - and not grep { exists $fontinfo{features}{$_} } - @{$FIGURE_STYLE{$figure_style}{reqd}} ) { - next FIGURE_STYLE; - } - - # If so, create all corresponding shapes - my $basic = $FD_SHAPE{$fontinfo{shape}}; - - SHAPE: - for my $shape (@{$FIGURE_STYLE{$figure_style}{shapes}}) { - next SHAPE if not exists $SHAPE{$shape}; - next SHAPE if not exists $SHAPE{$shape}{code}{$basic}; - - # Does the font support this shape? - if ( @{$SHAPE{$shape}{reqd}} - and not grep { exists $fontinfo{features}{$_} } - @{$SHAPE{$shape}{reqd}}) { - next SHAPE; - } - - # Decide which features to use - my @features = grep { exists $fontinfo{features}{$_} } - ( - @{$FIGURE_STYLE{$figure_style}{reqd}}, - @{$FIGURE_STYLE{$figure_style}{nice}}, - @{$SHAPE{$shape}{reqd}}, - @{$SHAPE{$shape}{nice}}, - ); - - # Remove duplicate features - my %tmp_features; - for my $f (@features) { - $tmp_features{$f} = 1; - } - if ($tmp_features{onum} && $tmp_features{lnum}) { - delete $tmp_features{lnum}; - } - @features = keys %tmp_features; - - # Figure out the name and NFSS code for the encodings - my @encodings; - if ($shape eq 'textcomp') { - @encodings = (['fontools_ts1', 'ts1']); - } - elsif ($figure_style eq 'Orn') { - @encodings = ([make_ornament_encoding(%fontinfo), 'u']); - } - else { - @encodings = map { [lc $_, lc $_] } @{$ARGV{encoding}}; - } +#----------------------------------------------------------------------- +# Determine which shapes to create for each (font, style) combination; +# return a list of (font, style, shape) tuples +#----------------------------------------------------------------------- +sub expand_shapes { + return map { my ($font, $style) = @{$_}{qw(font style)}; + map { { font => $font, style => $style, shape => $_ } } + grep { has_reqd($font, $SHAPE{$_}) } + @{$STYLE{$style}{shapes}}; + } + @_; +} - ENCODING: - for my $enc_ref (@encodings) { - my ($enc_name, $enc_code) = @{$enc_ref}; - $enc_name =~ s/\A (ly1|ot1|t1) \z/fontools_$1/xms; - - # Create unique name for this font - my $fontname = join '-', - $fontinfo{name}, - lc $figure_style, - $SHAPE{$shape}{name}, - $enc_code, - ; - $fontname =~ s/[-]{2,}/-/xmsg; - - # Create the command line for otftotfm - my $command - = join ' ', - 'otftotfm', - "--encoding=$enc_name", - ($ARGV{manual} ? '--pl' : '--automatic'), - "--map-file=$fontinfo{family}.map --no-updmap", - ($filename =~ m/[.]ttf\z/xms - ? '--no-type1' - : ''), - ($CODING_SCHEME{$enc_name} - ? "--coding-scheme=" - . "\"$CODING_SCHEME{$enc_name}\"" - : ''), - (map { "--feature=$_" } @features), - # if there's no 'liga' feature, - # add ligkern commands for common ligatures - ((grep { $_ eq 'liga' } @features) - ? '' - : '--ligkern="f i =: fi" ' - . '--ligkern="f l =: fl" ' - . '--ligkern="f f =: ff" ' - . '--ligkern="ff i =: ffi" ' - . '--ligkern="ff l =: ffl" '), - $FIGURE_STYLE{$figure_style}{extra}, - $SHAPE{$shape}{extra}, - $ARGV{extra}, - '"' . $filename . '"', - $fontname, - ; - - # Save the command and the necessary data for .fd files - push @{$commands{$fontinfo{family}}}, $command; - push @fd_data, - join '|', - $fontinfo{family}, - uc $enc_code, - $figure_style, - $FD_WEIGHT{$fontinfo{weight}} - . $FD_WIDTH{$fontinfo{width}} - || 'm', - $SHAPE{$shape}{code}{$basic}, - sprintf("%04.1f",$fontinfo{min}), - sprintf("%04.1f",$fontinfo{max}), - $fontname, - ; - - if ($ARGV{verbose}) { - printf " %-42s %4s/%s-%s/%s/%s\n", - $fontname, - uc $enc_code, - $fontinfo{family}, - $figure_style, - $FD_WEIGHT{$fontinfo{weight}} - .$FD_WIDTH{$fontinfo{width}} - || 'm', - $SHAPE{$shape}{code}{$basic}, - ; - } - } - } - } - } +#----------------------------------------------------------------------- +# Check if $font has (at least one of the) features mentioned in the +# 'reqd' subtable of $target +#----------------------------------------------------------------------- +sub has_reqd { + my ($font, $target) = @_; - # If parsing failed, flush STDOUT, print the error messages and die - if (defined $err_msg) { - close STDOUT; - die $err_msg . <<'END_GENERAL_PARSE_ERROR'; - - -I suspect your font family contains some unusual weights or widths. -You might try adding missing widths and weights to the tables -'%FD_WIDTH' and '%FD_WEIGHT' at the beginning of the source code; -otherwise, please send a bug report to <marc@penninga.info>. -END_GENERAL_PARSE_ERROR - } - - @fd_data = sort @fd_data; - - for my $fd_line (@fd_data) { - my @fd_line = split /[|]/, $fd_line; - $fd_line[5] += 0; - $fd_line[6] += 0; - $fd_line = \@fd_line; - } - - # Adjust size ranges - $fd_data[0][5] = ''; - for my $i (0 .. $#fd_data - 1) { - if (grep { $fd_data[$i][$_] ne $fd_data[$i + 1][$_] } 0 .. 4) { - $fd_data[$i][6] = $fd_data[$i + 1][5] = ''; - } - else { - $fd_data[$i][6] = $fd_data[$i + 1][5]; - } - } - $fd_data[-1][6] = ''; - - # Generate .fd files - my @fd_prev = ('') x 8; - my $FD; - for my $fd_line_ref (@fd_data) { - my @fd_line = @{$fd_line_ref}; - - my $safe = $fd_line[0]; - $safe =~ s/1/One/xmsg; - $safe =~ s/2/Two/xmsg; - $safe =~ s/3/Three/xmsg; - $safe =~ s/4/Four/xmsg; - $safe =~ s/5/Five/xmsg; - $safe =~ s/6/Six/xmsg; - $safe =~ s/7/Seven/xmsg; - $safe =~ s/8/Eight/xmsg; - $safe =~ s/9/Nine/xmsg; - $safe =~ s/0/Zero/xmsg; - - write_style_file($fd_line[0], $safe, @fd_data) - if $fd_line[0] ne $fd_prev[0]; - - if (grep { $fd_line[$_] ne $fd_prev[$_] } 0 .. 2) { - end_fd_file($FD) if $fd_prev[0]; - $FD = start_fd_file(@fd_line[0 .. 2], $safe); - } - - if (grep { $fd_line[$_] ne $fd_prev[$_] } 0 .. 4) { - # Start new fontshape - if (not grep { $fd_line[$_] ne $fd_prev[$_] } 0 .. 2) { - print {$FD} "}{}\n\n"; + return 0 unless defined $target; + return 1 unless @{$target->{reqd}}; + return grep { $font->{feature}{$_} } @{$target->{reqd}}; +} + +#----------------------------------------------------------------------- +# Determine which encodings to use for each (font, style, shape) combi; +# return a list of (font, style, shape, encoding) tuples +#----------------------------------------------------------------------- +sub expand_encodings { + return + map { my ($font, $style, $shape) = @{$_}{qw(font style shape)}; + my @encodings + = $shape eq 'textcomp' ? (['fontools_ts1', 'ts1']) + : $style eq 'Orn' ? ([Fontinfo::get_orn($font), 'u']) + : map { [lc $_, lc $_] } @{$ARGV{encoding}} + ; + map { { font => $font, + style => $style, + shape => $shape, + encoding => $_, + } + } + @encodings; } - printf {$FD} "\\DeclareFontShape{%s}{%s-%s}{%s}{%s}{\n", - @fd_line[1, 0, 2, 3, 4]; + @_; +} + +#----------------------------------------------------------------------- +# Add some finishing touches to the work list +#----------------------------------------------------------------------- +sub cleanup { + my @worklist = @_; + + for my $item (@worklist) { + my ($font, $style, $shape, $encoding) + = @{$item}{qw(font style shape encoding)}; + + # generate unique name for this font + $item->{fontname} = join '-', grep { $_ } $font->{name}, + lc $style, + lc $SHAPE{$shape}{name}, + lc $encoding->[1]; + + # look up NFSS code for font's shape + $item->{fdshape} + = $SHAPE{$shape}{code}{$font->{basicshape}}; + + # compile list of OpenType features to use with this font + my %feature = map { ($_ => 1) } + grep { $font->{feature}{$_} } + ( @{$STYLE{$style}{reqd}}, + @{$STYLE{$style}{nice}}, + @{$SHAPE{$shape}{reqd}}, + @{$SHAPE{$shape}{nice}}, + ); + if ($feature{lnum} && $feature{onum}) { + delete $feature{lnum}; } - - # Write fontshape entry - printf {$FD} " %s \\%s\@\@scale %s\n", - sprintf("%5s-%-5s", '<' . $fd_line[5], $fd_line[6] . '>'), - $safe, - $fd_line[7], - ; - - @fd_prev = @fd_line; + $item->{features} = [ sort keys %feature ]; + + # add finishing touches to name and NFSS code of encoding + $item->{encoding}[0] =~ s/\A (ot1|t1|ly1) \z/fontools_$1/xms; + $item->{encoding}[1] = uc $item->{encoding}[1]; } - - end_fd_file($FD) if $fd_prev[0]; - # Print or execute the generated commands + return @worklist; +} + +#----------------------------------------------------------------------- +# Generate all otftotfm commands, and either save or execute them +#----------------------------------------------------------------------- +sub make_commands { + my @worklist = @_; + + my @commands = map { make_cmdline($_) } @worklist; + + # make sure the last command *does* call updmap + $commands[-1] =~ s/--no-updmap//xms; + if ($ARGV{manual}) { - while (my ($fam, $cmds_ref) = each %commands) { - open my $BAT, '>', "$fam.bat" - or die "ERROR: can't create '$fam.bat' - $!"; - print {$BAT} "$_\n" for @{$cmds_ref}; - close $BAT; - } + open my $BAT, '>', 'autoinst.bat' + or die "[ERROR] Can't create 'autoinst.bat': $!"; + print {$BAT} "$_\n" for @commands; + close $BAT; } else { - # Remove the --no-updmap option from the last command for each family - map { $_->[-1] =~ s/--no-updmap//xms } values %commands; - - for my $cmds_ref (values %commands) { - for my $cmd (@{$cmds_ref}) { - print "$cmd\n"; - system $cmd and warn <<'END_OTFTOTFM_WARNING'; - -WARNING: 'otftotfm' finished with a non-zero return code; - I'm afraid something went wrong! - -END_OTFTOTFM_WARNING - } + if (grep { system $_ } @commands) { + warn "[WARNING] 'otftotfm' returned non-zero; something's wrong!"; } } + + return; +} + +# The official names for various coding schemes +my %SCHEME = ( + fontools_ly1 => 'TEX TYPEWRITER AND WINDOWS ANSI', + fontools_t1 => 'EXTENDED TEX FONT ENCODING - LATIN', + fontools_ot1 => 'TEX TEXT', + fontools_ts1 => 'TEX TEXT COMPANION SYMBOLS 1---TS1', +); + +#----------------------------------------------------------------------- +# Generate a command line for otftotfm +#----------------------------------------------------------------------- +sub make_cmdline { + my $item = shift; + + return join ' ', 'otftotfm', + ($ARGV{manual} ? '--pl' : '--automatic'), + "--encoding=$item->{encoding}[0]", + set_targetdirs($item->{font}{family}), + '--no-updmap', + ($item->{font}{filename} =~ m/[.]ttf\z/xms + ? '--no-type1' + : ''), + ($SCHEME{$item->{encoding}[0]} + ? qq(--coding-scheme="$SCHEME{$item->{encoding}[0]}") + : ''), + (map { "--feature=$_" } @{$item->{features}}), + ((grep { $_ eq 'liga' } @{$item->{features}}) + ? '' + : ( '--ligkern="f i =: fi"', + '--ligkern="f l =: fl"', + '--ligkern="f f =: ff"', + '--ligkern="ff i =: ffi"', + '--ligkern="ff l =: ffl"' )), + $STYLE{$item->{style}}{extra}, + $SHAPE{$item->{shape}}{extra}, + $ARGV{extra}, + qq("$item->{font}{filename}"), + $item->{fontname}, + ; +} + +#----------------------------------------------------------------------- +# Return a string with all "directory" options for otftotfm set +#----------------------------------------------------------------------- +sub set_targetdirs { + my $family = shift; + + my %dir = map { ($_ => File::Spec->catdir( + $ARGV{target}, 'fonts', $_, 'lcdftools', $family)) + } + qw(tfm vf pl vpl type1 truetype type42); + + $dir{$_} = File::Spec->catdir( + $ARGV{target}, 'fonts', $_, 'dvips', 'lcdftools') + for qw(enc map); + + File::Path::make_path(values %dir); + + my $result = join ' ', map { "--${_}-directory=$dir{$_}" } + qw(tfm vf pl vpl type1 truetype type42); + $result .= " --encoding-directory=$dir{enc} --map-file=" + . File::Spec->catfile($dir{map}, "${family}.map"); + + return $result; } -# ------------------------------------------------------------------------ +############################################################################ + + +package ARGV; + +my $USAGE =<<'END_USAGE'; + +'autoinst' is a wrapper around Eddie Kohler's TypeTools +(http://www.lcdf.org/type/), for installing OpenType fonts in LaTeX. + +Usage: autoinst [options] font[s] + +Possible options: + -encoding=ENC[,ENC]* Specify text encoding(s) (default: OT1,T1,LY1) + + -(no)ts1 Toggle creation of TS1 fonts + -(no)smallcaps Toggle creation of smallcaps shape + -(no)swash Toggle creation of swash shape + -(no)titling Toggle creation of titling shape + -(no)superiors Toggle creation of fonts with superior characters + -(no)inferiors Toggle creation of fonts with inferior characters + -(no)ornaments Toggle creation of ornament fonts + -(no)fractions Toggle creation of fonts with digits for fractions + + -sanserif Install font as sanserif font + -typewriter Install font as typewriter font + -extra="TEXT" Add TEXT to the command line for 'otftotfm' + -target="DIRECTORY" Install files into specified TEXMF tree + -manual Manual mode (see documentation) + + -(no)figurekern Keep or remove kerns between tabular figures + + -help Print this text + -verbose Make some noise + + font[s] The fonts (either .otf or .ttf) to install. + +Please report any bugs or suggestions to <marcpenninga@gmail.com>. +END_USAGE + +# Default values for the command-line arguments +%ARGV = ( + encoding => 'OT1,T1,LY1', + textcomp => '2', # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no) + smallcaps => '1', # 0 = no, 1 = yes + swash => '1', # 0 = no, 1 = yes + titling => '1', # 0 = no, 1 = yes + superiors => '1', # 0 = no, 1 = yes + inferiors => '0', # 0 = no, 1 = yes + ornaments => '1', # 0 = no, 1 = yes + fractions => '0', # 0 = no, 1 = yes + nfss => 'rm', + extra => '', + target => '', + manual => '0', # 0 = no, 1 = yes + verbose => '0', # 0 = no, 1 = yes + figurekern => '1', # 0 = no, 1 = yes +); + +#----------------------------------------------------------------------- +# Process command-line arguments +#----------------------------------------------------------------------- sub parse_options { my $cmdline = "$0 " . join ' ', @ARGV; - - GetOptions( - 'help' => sub { print $USAGE; exit }, - 'encoding=s' => \$ARGV{encoding}, - 'ts1!' => \$ARGV{textcomp}, - 'manual' => \$ARGV{manual}, - 'verbose' => \$ARGV{verbose}, - 'extra=s' => \$ARGV{extra}, - 'sanserif' => sub { $ARGV{nfss} = 'sf' }, - 'typewriter' => sub { $ARGV{nfss} = 'tt' }, - 'smallcaps!' => \$ARGV{smallcaps}, - 'swash!' => \$ARGV{swash}, - 'titling!' => \$ARGV{titling}, - 'superiors!' => \$ARGV{superiors}, - 'inferiors!' => \$ARGV{inferiors}, - 'ornaments!' => \$ARGV{ornaments}, - 'fractions!' => \$ARGV{fractions}, + + Getopt::Long::GetOptions( + 'help|?' => sub { print $USAGE; exit; }, + 'encoding=s' => \$ARGV{encoding}, + 'ts1!' => \$ARGV{textcomp}, + 'smallcaps!' => \$ARGV{smallcaps}, + 'swash!' => \$ARGV{swash}, + 'titling!' => \$ARGV{titling}, + 'superiors!' => \$ARGV{superiors}, + 'inferiors!' => \$ARGV{inferiors}, + 'ornaments!' => \$ARGV{ornaments}, + 'fractions!' => \$ARGV{fractions}, + 'sanserif' => sub { $ARGV{nfss} = 'sf' }, + 'typewriter' => sub { $ARGV{nfss} = 'tt' }, + 'extra=s' => \$ARGV{extra}, + 'target=s' => \$ARGV{target}, + 'manual' => \$ARGV{manual}, + 'figurekern!' => \$ARGV{figurekern}, + 'verbose' => \$ARGV{verbose}, ) or die "$USAGE"; @@ -605,33 +597,57 @@ sub parse_options { if (!$ARGV{swash} ) { delete $SHAPE{swash} } if (!$ARGV{titling} ) { delete $SHAPE{titling} } - if (!$ARGV{superiors}) { delete $FIGURE_STYLE{Sup} } - if (!$ARGV{inferiors}) { delete $FIGURE_STYLE{Inf} } - if (!$ARGV{ornaments}) { delete $FIGURE_STYLE{Orn} } - if (!$ARGV{fractions}) { delete @FIGURE_STYLE{qw(Numr Dnom)} } - + if (!$ARGV{superiors}) { delete $STYLE{Sup} } + if (!$ARGV{inferiors}) { delete $STYLE{Inf} } + if (!$ARGV{ornaments}) { delete $STYLE{Orn} } + if (!$ARGV{fractions}) { delete @STYLE{qw(Numr Dnom)} } + $ARGV{encoding} =~ s/\s+//xmsg; my @textencodings = grep { $_ ne 'TS1' } - map { uc } + map { uc } split /,/, $ARGV{encoding}; $ARGV{encoding} = \@textencodings; # TS1-encoded fonts are generated if: - # - text encoding is T1 and the user didn't turn off TS1, or - # - the user explicitly asked for TS1 - if ( - !( (grep { $_ eq 'T1' } @{$ARGV{encoding}} and $ARGV{textcomp}) - or $ARGV{textcomp} == 1 - )) { + # - the user explicitly asked for TS1, or + # - the text encodings contain T1 and the user didn't turn off TS1 + unless ( (grep { $_ eq 'T1' } @{$ARGV{encoding}} and $ARGV{textcomp}) + or $ARGV{textcomp} == 1) + { delete $SHAPE{textcomp}; } - + + if ($ARGV{manual}) { + warn "[WARNING] option '--target' overridden by '--manual'!" + if $ARGV{target}; + $ARGV{target} = File::Spec->curdir(); + } + elsif (not $ARGV{target}) { + my @dirs = grep { -w $_ } + map { split m/:/xms, substr $_, 0, -1 } + ( `kpsewhich --expand-path='\$TEXMFLOCAL'`, + `kpsewhich --expand-path='\$TEXMFHOME'`, ); + $ARGV{target} = $dirs[0] || File::Spec->curdir(); + } + + if (!$ARGV{figurekern}) { + my @digits = qw(zero one two three four five six seven eight nine); + my $tkern + = join ' ', map { my $left = $_; + map { qq(--ligkern="$left {} $_") } @digits + } + @digits; + + $STYLE{TLF}{extra} = $tkern; + $STYLE{TOsF}{extra} = $tkern; + } + if ($ARGV{verbose}) { print <<"END_ARGUMENTS"; $cmdline - + I'm using the following options: encoding(s): @{[ join ', ', @{$ARGV{encoding}} ]} @@ -639,279 +655,379 @@ I'm using the following options: : $ARGV{nfss} eq 'sf' ? '(sanserif)' : $ARGV{nfss} eq 'tt' ? '(typewriter)' : '(unknown)' - ]} + ]} + + (no)ts1: @{[ $SHAPE{textcomp} ? 'ts1' : 'nots1' ]} + (no)smallcaps: @{[ $ARGV{smallcaps} ? 'smallcaps' : 'nosmallcaps' ]} + (no)swash: @{[ $ARGV{swash} ? 'swash' : 'noswash' ]} + (no)titling: @{[ $ARGV{titling} ? 'titling' : 'notitling' ]} + (no)superiors: @{[ $ARGV{superiors} ? 'superiors' : 'nosuperiors' ]} + (no)inferiors: @{[ $ARGV{inferiors} ? 'inferiors' : 'noinferiors' ]} + (no)ornaments: @{[ $ARGV{ornaments} ? 'ornaments' : 'noornaments' ]} + (no)fractions: @{[ $ARGV{fractions} ? 'fractions' : 'nofractions' ]} - (no)ts1: @{[ $SHAPE{textcomp} ? 'ts1' : 'nots1' ]} - (no)smallcaps: @{[ $ARGV{smallcaps} ? 'smallcaps' : 'nosmallcaps' ]} - (no)swash: @{[ $ARGV{swash} ? 'swash' : 'noswash' ]} - (no)titling: @{[ $ARGV{titling} ? 'titling' : 'notitling' ]} - (no)superiors: @{[ $ARGV{superiors} ? 'superiors' : 'nosuperiors' ]} - (no)inferiors: @{[ $ARGV{inferiors} ? 'inferiors' : 'noinferiors' ]} - (no)ornaments: @{[ $ARGV{ornaments} ? 'ornaments' : 'noornaments' ]} - (no)fractions: @{[ $ARGV{fractions} ? 'fractions' : 'nofractions' ]} + verbosity: @{[ $ARGV{verbose} ? 'verbose' : 'quiet' ]} + target: $ARGV{target} + auto/manual: @{[ $ARGV{manual} ? 'manual' : 'automatic' ]} extra: @{[ $ARGV{extra} || 'empty' ]} - auto/manual: @{[ $ARGV{manual} ? 'manual' : 'automatic' ]} - verbosity: @{[ $ARGV{verbose} ? 'verbose' : 'silent' ]} + figurekern: @{[ $ARGV{figurekern} ? 'keep' : 'discard' ]} END_ARGUMENTS } } -# ------------------------------------------------------------------------ - -sub read_font_info { - my ($fontfile) = @_; - - my %info = (); - - # Read some general info about the font - open my $OTFINFO, '-|', "otfinfo --info \"$fontfile\"" - or die "ERROR: 'otfinfo --info \"$fontfile\"' failed"; - - LINE: - for my $line (<$OTFINFO>) { - my ($key, $val) = $line =~ m/([^:]+) :\s* ([^\n]+)/xms - or next LINE; - $val =~ s/[^-\w]//xmsg; - $info{$key} = $val; - } - close $OTFINFO; - if ($info{Family} =~ m/\A (.+ (?: OT | Pro))/xms) { - $info{Family} = $1; +############################################################################ + + +package Fontinfo; + +#----------------------------------------------------------------------- +# Return ref to hash with all relevant info about this font +#----------------------------------------------------------------------- +sub parse_fontinfo { + my ($filename) = @_; + + my $info = { + filename => $filename, + width => 'regular', + weight => 'regular', + shape => 'roman', + minsize => 0, + maxsize => 0, + }; + + parse_basicinfo($info); + parse_sizeinfo($info); + parse_features($info); + + if ($ARGV{verbose}) { + print <<"END_FONTINFO"; +$info->{filename} + Name: $info->{name} + Family: $info->{family} + Subfamily: $info->{subfamily} + Width: $info->{width} + Weight: $info->{weight} + Shape: $info->{shape} + Size: $info->{minsize}-$info->{maxsize} + Features: @{[ join ', ', sort keys %{$info->{feature}} ]} + +END_FONTINFO } - - $info{'Full name'} =~ s/$info{Family}//xmsg; - $info{'Full name'} = lc $info{'Full name'}; - $info{Family} =~ s/\A (?: Adobe | ITC ) | LT | MT//xmsg; - - # Set default - my %fontinfo = ( - filename => $fontfile, - name => $info{'PostScript name'}, - family => $info{Family}, - width => 'regular', - weight => 'regular', - shape => 'roman', - min => 0, - max => 0, - features => {}, - ); - - # Try to match width, weight and (basic) shape - WIDTH: - for my $width (map { quotemeta } - reverse sort - { length($a) <=> length($b) || $a cmp $b } - keys %FD_WIDTH) - { - if ($info{'Full name'} =~ s/$width//xmsi) { - $fontinfo{width} = $width; - last WIDTH; + + return $info; +} + +# table for converting digits in font names to text (safer for LaTeX) +my @DIGITS = qw(Zero One Two Three Four Five Six Seven Eight Nine); + +#----------------------------------------------------------------------- +# Get some basic info (family, weight, width, shape) about this font +#----------------------------------------------------------------------- +sub parse_basicinfo { + my $info = shift; + + open my $otfinfo, '-|', qq(otfinfo --info "$info->{filename}") + or die "[ERROR] 'otfinfo --info $info->{filename}' failed"; + my %data = map { my ($k,$v) = m/\A\s* ([^:]+?) \s*:\s* ([^\r\n]+)/xms; + $k =~ s/\s+//xmsg; + $v =~ s/\s+//xmsg; + (lc $k => $v); + } + grep { m/\A\s* [^:]+? \s*:\s* [^\r\n]+/xms } <$otfinfo>; + close $otfinfo; + + $data{family} = $data{preferredfamily} || $data{family}; + $data{subfamily} = $data{preferredsubfamily} || $data{subfamily}; + $data{fullname} =~ s/\A$data{family}//xms; + $data{fullname} = lc $data{fullname}; + $data{family} =~ s/\A(?: Adobe | ITC | LT | MT)//xms; + $data{family} =~ s/(\d)/$DIGITS[$1]/xmsge; + + for my $width (mqrs(keys %FD_WIDTH)) { + if ($data{fullname} =~ s/${width}//xmsi) { + $info->{width} = $width; + last; } } - - WEIGHT: - for my $weight (map { quotemeta } - reverse sort - { length($a) <=> length($b) || $a cmp $b } - keys %FD_WEIGHT) - { - if ($info{'Full name'} =~ s/$weight//xmsi) { - $fontinfo{weight} = $weight; - last WEIGHT; + + for my $weight (mqrs(keys %FD_WEIGHT)) { + if ($data{fullname} =~ s/${weight}//xmsi) { + $info->{weight} = $weight; + last; } } - SHAPE: - for my $shape (map { quotemeta } - reverse sort - { length($a) <=> length($b) || $a cmp $b } - keys %FD_SHAPE) - { - if ($info{'Full name'} =~ s/$shape//xmsi) { - $fontinfo{shape} = $shape; - last SHAPE; + + for my $shape (mqrs(keys %FD_SHAPE)) { + if ($data{fullname} =~ s/${shape}//xmsi) { + $info->{shape} = $shape; + last; } } - - # Read optical size info - open $OTFINFO, '-|',"otfinfo --optical-size \"$fontfile\"" - or die "ERROR: 'otfinfo --optical-size \"$fontfile\"' failed"; - if (my ($fm, $to) - = <$OTFINFO> =~ m/ - [(] - ( [\d.]+ ) \s* pt, \s* - ( [\d.]+ ) \s* pt \s* - []] - /xms) { - # Work around some known bugs - if ($fontinfo{name} eq 'GaramondPremrPro-It' - && $fm == 6 - && $to == 8.9) { - @fontinfo{qw(min max)} = (8.9, 14.9); - } - elsif ($fontinfo{family} eq 'KeplerStd' - && $info{Subfamily} =~ m/Caption/xms - && $fm == 8.9 - && $to == 13.9) { - @fontinfo{qw(min max)} = (6, 8.9); - } - elsif ($fontinfo{family} eq 'KeplerStd' - && $info{Subfamily} =~ m/Subhead/xms - && $fm == 8.9 - && $to == 13.9) { - @fontinfo{qw(min max)} = (13.9, 23); - } - elsif ($fontinfo{family} eq 'KeplerStd' - && $info{Subfamily} =~ m/Display/xms - && $fm == 8.9 - && $to == 13.9) { - @fontinfo{qw(min max)} = (23, 72); - } - else { - @fontinfo{qw(min max)} = ($fm, $to); + + $data{subfamily} =~ s/$info->{width}//xmsi; + $data{subfamily} =~ s/$info->{weight}//xmsi; + $data{subfamily} =~ s/$info->{shape}//xmsi; + + $info->{name} = $data{postscriptname}; + $info->{family} = $data{family}; + $info->{subfamily} = $data{subfamily}; + + $info->{basicshape} = $FD_SHAPE{$info->{shape}}; + $info->{fdseries} + = ($FD_WEIGHT{$info->{weight}} . $FD_WIDTH{$info->{width}}) || 'm'; + + return $info; +} + +#----------------------------------------------------------------------- +# When matching against data, try longer strings before shorter ones +#----------------------------------------------------------------------- +sub mqrs { + return map { quotemeta } reverse sort { length($a) <=> length($b) } @_; +} + +#----------------------------------------------------------------------- +# Get all features this font supports +#----------------------------------------------------------------------- +sub parse_features { + my $info = shift; + + open my $otfinfo, '-|', qq(otfinfo --features "$info->{filename}") + or die "[ERROR] 'otfinfo --features $info->{filename}' failed"; + %{$info->{feature}} = map { (substr($_, 0, 4) => 1) } <$otfinfo>; + close $otfinfo; + + open $otfinfo, '-|', qq(otfinfo --tables "$info->{filename}") + or die "[ERROR] 'otfinfo --tables $info->{filename}' failed"; + $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>; + close $otfinfo; + + return $info; +} + +#----------------------------------------------------------------------- +# Get the optical sizes for this font +#----------------------------------------------------------------------- +sub parse_sizeinfo { + my $info = shift; + + open my $otfinfo, '-|', qq(otfinfo --optical-size "$info->{filename}") + or die "[ERROR] 'otfinfo --optical-size $info->{filename}' failed"; + + if (my ($minsize, $maxsize) = <$otfinfo> =~ m/[(] ([\d.]+) \s* pt, \s* + ([\d.]+) \s* pt \s* []]/xms ) + { + # fix some known bugs + if ($info->{name} eq 'GaramondPremrPro-It' + && $minsize == 6 && $maxsize == 8.9) + { + ($minsize, $maxsize) = (8.9, 14.9); } - } - close $OTFINFO; - - # See what features this font provides - open $OTFINFO, '-|',"otfinfo --features \"$fontfile\"" - or die "ERROR: 'otfinfo --features \"$fontfile\"' failed"; - for my $line (<$OTFINFO>) { - if ($line =~ m/\A (\w{4}) \s+/xms) { - $fontinfo{features}{$1} = 1; + elsif ($info->{family} eq 'KeplerStd' + && $info->{subfamily} =~ m/Caption/xms + && $minsize == 8.9 && $maxsize == 13.9) + { + ($minsize, $maxsize) = (6, 8.9); } - } - close $OTFINFO; - - # Check if there's a "kern" table - open $OTFINFO, '-|',"otfinfo --tables \"$fontfile\"" - or die "ERROR: 'otfinfo --tables \"$fontfile\"' failed"; - for my $line (<$OTFINFO>) { - if ($line =~ m/\d+ \s+ (\w{4}) \s+/xms && $1 eq 'kern') { - $fontinfo{features}{kern} = 1; - last; + elsif ($info->{family} eq 'KeplerStd' + && $info->{subfamily} =~ m/Subhead/xms + && $minsize == 8.9 && $maxsize == 13.9) + { + ($minsize, $maxsize) = (13.9, 23); } - } - close $OTFINFO; - - if ($ARGV{verbose}) { - print <<"END_FONT_INFO"; - -$fontfile: - Family $fontinfo{family} - Width $fontinfo{width} - Weight $fontinfo{weight} - Shape $fontinfo{shape} - Size @{[ $fontinfo{min} || '']}-@{[ $fontinfo{max} || '' ]} -END_FONT_INFO - - my @features = sort keys %{$fontinfo{features}}; - my $prefix = ' Features '; - while (@features) { - print $prefix, join(' ', splice @features, 0, 10), "\n"; - $prefix = ' ' x length $prefix; + elsif ($info->{family} eq 'KeplerStd' + && $info->{subfamily} =~ m/Display/xms + && $minsize == 8.9 && $maxsize == 13.9) + { + ($minsize, $maxsize) = (23, 72); } - print "\n"; + + @{$info}{qw(minsize maxsize)} = ($minsize, $maxsize); } - - return %fontinfo; + close $otfinfo; + + return $info; } -=begin Comment +# Error messages, used in assert_unique() +my $WARN_PARSE =<<'END_WARN_PARSE'; +[WARNING] I failed to parse all fonts in a unique way, so I will split + your font family into multiple subfamilies and try again: - Ornament glyph names vary across fonts, so we generate font-specific - encoding vectors. - This is skipped if a file `<family>_orn.enc' is found in the current - directory, so the user can provide her own vector if she wants to. + %s -=end Comment + Please check the output! -=cut +END_WARN_PARSE -sub make_ornament_encoding { - my (%fontinfo) = @_; +my $ERR_PARSE =<<'END_ERR_PARSE'; +[ERROR] I failed to parse all fonts in a unique way; + presumably some fonts have unusual widths, weights or shapes. - my $fontfile = $fontinfo{filename}; - my $enc_name = $fontinfo{family} . '_orn'; - - if (not -e "$enc_name.enc") { + Try one of the following: + - Run 'autoinst' on a smaller set of fonts, + omitting the ones that weren't parsed correctly; + - Add the missing widths, weights or shapes to the tables + '%FD_WIDTH', '%FD_WEIGHT' or '%FD_SHAPE' near the top + of the source code; + + Please also send a bug report to the author. + +END_ERR_PARSE + +my $ERR_DETAIL =<<'END_ERR_DETAIL'; +[ERROR] I've parsed both %s + and %s as + + Family: %s + Width: %s + Weight: %s + Shape: %s + Size: %s-%s + +END_ERR_DETAIL +#----------------------------------------------------------------------- +# Assert all font infos are unique +#----------------------------------------------------------------------- +sub assert_unique { + my @fonts = @_; + + # These attributes should uniquely identify each font + my @attributes = qw(family width weight shape minsize maxsize); + + ATTEMPT: + for my $attempt (1 .. 2) { + my (%seen, $err_details); + for my $font (@fonts) { + my $key + = join "\x00", + @{$font}{ @attributes }; + + if ($seen{$key}) { + $err_details .= sprintf $ERR_DETAIL, + $seen{$key}{filename}, + $font->{filename}, + @{$font}{ @attributes }; + } + else { + $seen{$key} = $font; + } + } + + # If the font infos aren't unique, append 'Subfamily' to 'Family' + # and try again + if ($err_details) { + if ($attempt == 1) { + $err_details =~ s/\[ERROR\]/[WARNING]/xmsg; + warn $err_details; + + for my $font (@fonts) { + $font->{family} .= $font->{subfamily}; + } + + my @subfamilies + = sort keys %{{ map { ($_->{family} => 1) } @fonts }}; + warn sprintf $WARN_PARSE, join ', ', @subfamilies; + + next ATTEMPT; + } + else { + die $err_details, $ERR_PARSE; + } + } + + last ATTEMPT; + } + + return 1; +} + +#----------------------------------------------------------------------- +# Generate (font-specific) encoding vector for ornament glyphs +#----------------------------------------------------------------------- +sub get_orn { + my ($font) = @_; + + my $fontfile = $font->{filename}; + my $enc_name = $font->{family} . '_orn'; + + if (not -e "$enc_name.enc") { # Default ornament names: 'orn.' plus three digits my @encoding = map { sprintf "orn.%03d", $_ } 1 .. 256; - - open my $OTFINFO, '-|', "otfinfo --glyphs \"$fontfile\"" - or die "ERROR: 'otfinfo --glyphs \"$fontfile\"' failed"; + + open my $OTFINFO, '-|', qq(otfinfo --glyphs "$font->{filename}") + or die "[ERROR] 'otfinfo --glyphs $font->{filename}' failed"; chop(my @glyphnames = <$OTFINFO>); close $OTFINFO; # Test for some known alternative names (probably not exhaustive) - my @ornaments - = sort grep { m/\A (?:orn|u2022[.]|word[.]|hand|bullet[.]) | [.]orn \z/xms } + my @ornaments + = sort grep { m/\A (?: orn|u2022[.]|word[.]|hand|bullet[.]) + | [.]orn \z/xms + } @glyphnames; - - if (@ornaments > 256) { - @encoding = @ornaments[0 .. 255]; - } - else { - @encoding[0 .. $#ornaments] = @ornaments; - } - open my $ORNAMENTS, '>', "$enc_name.enc" - or die "ERROR: can't create '$enc_name.enc' - $!"; - - print {$ORNAMENTS} "/$fontinfo{family}OrnamentEncoding [\n"; - map { print {$ORNAMENTS} " /$_\n" } @encoding; - print {$ORNAMENTS} "] def\n"; - close $ORNAMENTS; + @encoding[0 .. $#ornaments] = @ornaments; + + open my $ORN, '>', "$enc_name.enc" + or die "[ERROR] Can't create '$enc_name.enc': $!"; + + print {$ORN} "/$font->{family}OrnamentEncoding [\n"; + map { print {$ORN} " /$_\n" } @encoding[0 .. 255]; + print {$ORN} "] def\n"; + close $ORN; } - + return $enc_name; } -# ------------------------------------------------------------------------ - -sub write_style_file { - my ($family, $safe, @fd_data) = @_; - - my (%seen_enc, %seen_style, %seen_series, %seen_shape); - - LINE: - for my $line_ref (@fd_data) { - my ($fam, $enc, $style, $series, $shape) = @{$line_ref}[0 .. 4]; - next LINE if $fam ne $family; - $seen_enc{$enc} = 1; - $seen_style{$style} = 1; - $seen_series{$series} = 1; - $seen_shape{$shape} = 1; - } - - open my $STYLE, '>', "$family.sty" - or die "ERROR: can't create '$family.sty' - $!"; - print {$STYLE} <<"END_STY_HEADER"; -%%Generayed by autoinst on $date + +############################################################################ + + +package LaTeX; + +#----------------------------------------------------------------------- +# Create a style file for LaTeX +#----------------------------------------------------------------------- +sub write_stylefile { + my ($fam, $data) = @_; + + my %seen = %{ get_keys($data) }; + + my $fn = sprintf "%s.sty", $fam; + my $dir = File::Spec->catdir($ARGV{target}, 'tex', 'latex', $fam); + File::Path::make_path($dir); + $fn = File::Spec->catfile($dir, $fn); + open my $STY, '>', $fn or die "[ERROR] Can't create '$fn': $!"; + + print {$STY} <<"END_STY_HEADER"; +%% Generated by autoinst on $TODAY %% \\NeedsTeXFormat{LaTeX2e} -\\ProvidesPackage{$family} - [$date (autoinst) Style file for $family.] - +\\ProvidesPackage{$fam} + [$TODAY (autoinst) Style file for $fam.] + END_STY_HEADER - - my $textenc = join ',', grep { $_ ne 'OT1' } @{$ARGV{encoding}}; - - print {$STYLE} "\\RequirePackage[$textenc]{fontenc}\n" if $textenc; - print {$STYLE} "\\RequirePackage{textcomp}\n" if $seen_enc{TS1}; - - print {$STYLE} <<'END_STY_FONTAXES_START'; + + my $enc = join ',', grep { $_ ne 'OT1' } @{$ARGV{encoding}}; + + print {$STY} "\\RequirePackage[$enc]{fontenc}\n" if $enc; + print {$STY} "\\RequirePackage{textcomp}\n" if $seen{TS1}; + + print {$STY} <<'END_STY_FONTAXES_START'; \IfFileExists{fontaxes.sty}{ \RequirePackage{fontaxes} END_STY_FONTAXES_START - if ($seen_shape{tl} || $seen_shape{tlit}) { - print {$STYLE} <<'END_STY_FONTAXES_TL'; + if ($seen{tl} or $seen{tlit}) { + print {$STY} <<'END_STY_FONTAXES_TL'; \providecommand{\tldefault}{tl} \DeclareRobustCommand\tlshape{\not@math@alphabet\tlshape\relax \fontsecondaryshape\tldefault\selectfont} @@ -919,82 +1035,79 @@ END_STY_FONTAXES_START \let\texttitling\texttl \fa@naming@exception{shape}{{n}{tl}}{tl} \fa@naming@exception{shape}{{it}{tl}}{tlit} - + END_STY_FONTAXES_TL } - if ($seen_shape{nw} || $seen_shape{sw}) { - print {$STYLE} <<'END_STY_FONTAXES_SW'; + if ($seen{nw} or $seen{sw}) { + print {$STY} <<'END_STY_FONTAXES_SW'; \DeclareRobustCommand\swshape{\not@math@alphabet\swshape\relax \fontprimaryshape\itdefault\fontsecondaryshape\swdefault\selectfont} \fa@naming@exception{shape}{{n}{sw}}{nw} \fa@naming@exception{shape}{{it}{sw}}{sw} - + END_STY_FONTAXES_SW } - if ($seen_style{Sup}) { - print {$STYLE} <<'END_STY_FONTAXES_SUP'; + if ($seen{Sup}) { + print {$STY} <<'END_STY_FONTAXES_SUP'; \fa@naming@exception{figures}{{superior}{proportional}}{Sup} \fa@naming@exception{figures}{{superior}{tabular}}{Sup} \def\sufigures{\@nomath\sufigures \fontfigurestyle{superior}\selectfont} \DeclareTextFontCommand{\textsu}{\sufigures} \let\textsuperior\textsu - + END_STY_FONTAXES_SUP } - if ($seen_style{Inf}) { - print {$STYLE} <<'END_STY_FONTAXES_INF'; + if ($seen{Inf}) { + print {$STY} <<'END_STY_FONTAXES_INF'; \fa@naming@exception{figures}{{inferior}{proportional}}{Inf} \fa@naming@exception{figures}{{inferior}{tabular}}{Inf} \def\infigures{\@nomath\infigures \fontfigurestyle{inferior}\selectfont} \DeclareTextFontCommand{\textin}{\infigures} \let\textinferior\textin - + END_STY_FONTAXES_INF } - if ($seen_style{Orn}) { - print {$STYLE} <<'END_STY_FONTAXES_ORN'; + if ($seen{Orn}) { + print {$STY} <<'END_STY_FONTAXES_ORN'; \fa@naming@exception{figures}{{ornament}{proportional}}{Orn} \fa@naming@exception{figures}{{ornament}{tabular}}{Orn} \def\ornaments{\@nomath\ornaments \fontencoding{U}\fontfigurestyle{ornament}\selectfont} \DeclareTextFontCommand{\textornaments}{\ornaments} \providecommand{\ornament}[1]{\textornaments{\char##1}} - + END_STY_FONTAXES_ORN } - if ($seen_style{Numr}) { - print {$STYLE} <<'END_STY_FONTAXES_NUMR'; + if ($seen{Numr}) { + print {$STY} <<'END_STY_FONTAXES_NUMR'; \fa@naming@exception{figures}{{numerators}{proportional}}{Numr} \fa@naming@exception{figures}{{numerators}{tabular}}{Numr} END_STY_FONTAXES_NUMR } - if ($seen_style{Dnom}) { - print {$STYLE} <<'END_STY_FONTAXES_DNOM'; + if ($seen{Dnom}) { + print {$STY} <<'END_STY_FONTAXES_DNOM'; \fa@naming@exception{figures}{{denominators}{proportional}}{Dnom} \fa@naming@exception{figures}{{denominators}{tabular}}{Dnom} END_STY_FONTAXES_DNOM } - print {$STYLE} <<'END_STY_FONTAXES_END'; -}{} - -END_STY_FONTAXES_END + print {$STY} "}{}\n\n"; - print {$STYLE} <<"END_STY_XKEYVAL"; + print {$STY} <<"END_STY_XKEYVAL"; \\IfFileExists{xkeyval.sty}{ - \\newcommand*{\\$safe\@scale}{1} + \\newcommand*{\\$fam\@scale}{1} \\RequirePackage{xkeyval} - \\DeclareOptionX{scaled}{\\renewcommand*{\\$safe\@scale}{##1}} + \\DeclareOptionX{scaled}{\\renewcommand*{\\$fam\@scale}{##1}} }{ \\let\\DeclareOptionX\\DeclareOption \\let\\ExecuteOptionsX\\ExecuteOptions @@ -1002,163 +1115,197 @@ END_STY_FONTAXES_END } END_STY_XKEYVAL - - if ($seen_style{LF} or $seen_style{TLF}) { - print {$STYLE} - "\\DeclareOptionX{lining}{\\edef\\$safe\@figurestyle{LF}}\n"; + + if ($seen{LF} or $seen{TLF}) { + print {$STY} + "\\DeclareOptionX{lining}{\\edef\\$fam\@figurestyle{LF}}\n"; } - if ($seen_style{OsF} or $seen_style{TOsF}) { - print {$STYLE} - "\\DeclareOptionX{oldstyle}{\\edef\\$safe\@figurestyle{OsF}}\n"; + if ($seen{OsF} or $seen{TOsF}) { + print {$STY} + "\\DeclareOptionX{oldstyle}{\\edef\\$fam\@figurestyle{OsF}}\n"; } - if ($seen_style{TLF} or $seen_style{TOsF}) { - print {$STYLE} - "\\DeclareOptionX{tabular}{\\edef\\$safe\@figurealign{T}}\n"; + if ($seen{TLF} or $seen{TOsF}) { + print {$STY} + "\\DeclareOptionX{tabular}{\\edef\\$fam\@figurealign{T}}\n"; } - if ($seen_style{LF} or $seen_style{OsF}) { - print {$STYLE} - "\\DeclareOptionX{proportional}{\\edef\\$safe\@figurealign{}}\n"; + if ($seen{LF} or $seen{OsF}) { + print {$STY} + "\\DeclareOptionX{proportional}{\\edef\\$fam\@figurealign{}}\n"; } - + my $defaults - = $seen_style{OsF} ? 'oldstyle,proportional' - : $seen_style{TOsF} ? 'oldstyle,tabular' - : $seen_style{LF} ? 'lining,proportional' - : $seen_style{TLF} ? 'lining,tabular' - : die "ERROR: encountered un unknown bug"; - + = $seen{OsF} ? 'oldstyle,proportional' + : $seen{TOsF} ? 'oldstyle,tabular' + : $seen{LF} ? 'lining,proportional' + : $seen{TLF} ? 'lining,tabular' + : die "[ERROR] Internal bug, please report!"; + my $default_bold; for my $series ( - qw(ultrablack ultrabold heavy extrablack black + qw(ultrablack ultrabold heavy extrablack black extrabold demibold semibold bold)) { - if ($seen_series{$FD_WEIGHT{$series}}) { - printf {$STYLE} + if ($seen{$FD_WEIGHT{$series}}) { + printf {$STY} "\\DeclareOptionX{%s}{\\renewcommand*{\\bfdefault}{%s}}\n", $series, $FD_WEIGHT{$series}; $default_bold = $series; } } $defaults .= ",$default_bold" if $default_bold; - + my $default_regular; for my $series ( qw(light medium regular)) { - if ($seen_series{$FD_WEIGHT{$series} || 'm'}) { - printf {$STYLE} + if ($seen{$FD_WEIGHT{$series} || 'm'}) { + printf {$STY} "\\DeclareOptionX{%s}{\\renewcommand*{\\mddefault}{%s}}\n", $series, $FD_WEIGHT{$series} || 'm'; $default_regular = $series; } } $defaults .= ",$default_regular" if $default_regular; - - print {$STYLE} <<"END_STYLE_REST"; + + print {$STY} <<"END_STYLE_REST"; \\ExecuteOptionsX{$defaults} \\ProcessOptionsX\\relax \\renewcommand* {\\$ARGV{nfss}default} - {$family-\\$safe\@figurealign\\$safe\@figurestyle} + {$fam-\\$fam\@figurealign\\$fam\@figurestyle} \\renewcommand*{\\familydefault}{\\$ARGV{nfss}default} \\endinput END_STYLE_REST - close $STYLE; + close $STY; + + return; } -# ------------------------------------------------------------------------ +#----------------------------------------------------------------------- +# Walk a nested dictionary, return lookup table with all keys +#----------------------------------------------------------------------- +sub get_keys { + my $dict = shift; + my $seen = shift || {}; + + while (my ($k, $v) = each %$dict) { + $seen->{$k} = 1; + get_keys($v, $seen) if ref $v eq 'HASH'; + } + + return $seen; +} + +#----------------------------------------------------------------------- +# Create a .fd file for LaTeX's NFSS +#----------------------------------------------------------------------- +sub write_fdfile { + my ($fam, $enc, $sty, $data) = @_; + + my $fn = sprintf "%s%s-%s.fd", $enc, $fam, $sty; + my $dir = File::Spec->catdir($ARGV{target}, 'tex', 'latex', $fam); + File::Path::make_path($dir); + $fn = File::Spec->catfile($dir, $fn); + open my $FD, '>', $fn or die "[ERROR] Can't create '$fn': $!"; -sub start_fd_file { - my ($fam, $enc, $fig, $safe) = @_; - - open my $FD, '>', "$enc$fam-$fig.fd" - or die "ERROR: can't create '$enc$fam-$fig.fd' - $!"; - print {$FD} <<"END_FD_HEADER"; -%%Generated by autoinst on $date +%% Generated by autoinst on $TODAY %% -\\ProvidesFile{$enc$fam-$fig.fd} - [$date (autoinst) Font definitions for $enc/$fam-$fig.] +\\ProvidesFile{${enc}${fam}-${sty}.fd} + [$TODAY (autoinst) Font definitions for ${enc}/${fam}-${sty}.] -\\expandafter\\ifx\\csname $safe\@scale\\endcsname\\relax - \\let\\$safe\@\@scale\\\@empty +\\expandafter\\ifx\\csname ${fam}\@scale\\endcsname\\relax + \\let\\${fam}\@\@scale\\\@empty \\else - \\edef\\$safe\@\@scale{s*[\\csname $safe\@scale\\endcsname]}% + \\edef\\${fam}\@\@scale{s*[\\csname ${fam}\@scale\\endcsname]}% \\fi - -\\DeclareFontFamily{$enc}{$fam-$fig}{} + +\\DeclareFontFamily{${enc}}{${fam}-${sty}}{} END_FD_HEADER - return $FD; + while (my ($series, $fdseries) = each %$data) { + while (my ($shape, $fdshape) = each %$fdseries) { + print {$FD} + "\\DeclareFontShape{$enc}{${fam}-${sty}}{$series}{$shape}{\n"; + my @items = sort { $a->[0] <=> $b->[0] } + @{$fdshape}; + $items[0][0] = $items[-1][1] = ''; + $items[$_][0] = $items[$_ - 1][1] for (1 .. $#items); + for my $item (@items) { + print {$FD} " <$item->[0]-$item->[1]>", + " \\${fam}\@\@scale $item->[2]\n"; + } + print {$FD} "}{}\n\n"; + } + } + print {$FD} "\\endinput\n"; + + close $FD; + + return; } -# ------------------------------------------------------------------------ -sub end_fd_file { - my ($FD) = @_; - - print {$FD} "}{}\n\n\\endinput\n"; - close $FD; -} +############################################################################ + +package main; -main() +main(); __END__ - pod2man --center="fontools" --date=`date +"%Y-%m-%d"` \ - --release="fontools" --section=1 autoinst autoinst.1 - - man -t ./autoinst.1 | ps2pdf - autoinst.pdf +############################################################################ + + + To create the documentation: + + pod2man --center="Marc Penninga" --release="fontools" --section=1 \ + autoinst - | groff -Tps -man - | ps2pdf - autoinst.pdf =pod =head1 NAME -autoinst - wrapper script around the F<LCDF TypeTools>, +autoinst - wrapper around the F<LCDF TypeTools>, for installing OpenType fonts in LaTeX. =head1 SYNOPSIS -autoinst [options] I<fontfile> [I<fontfile> ...] +B<autoinst> [I<options>] B<font(s)> =head1 DESCRIPTION -Eddie Kohler's F<TypeTools>, especially F<otftotfm>, are great tools for -installing OpenType fonts for use with LaTeX, but their use (even in -automatic mode) is quite complicated because it needs lots of long -command lines and doesn't generate the F<fd> and F<sty> files LaTeX needs. -B<autoinst> simplifies the font installation -process by generating and executing all commands for F<otftotfm> -and by creating all necessary F<fd> and F<sty> files. +Eddie Kohler's F<TypeTools>, especially F<otftotfm>, are superb tools +for installing OpenType fonts in LaTeX, but their use +(even in automatic mode) is complicated: they need many long +command lines and don't generate the F<fd> and F<sty> files LaTeX needs. +B<autoinst> simplifies the font installation process with F<otftotfm> +by generating and executing all command lines +and by creating and installing all F<fd> and F<sty> files. -All the user then needs -to do is move these files to a suitable location -(F<< $LOCALTEXMF/tex/latex/<Supplier>/<FontFamily>/ >> is the -official choice) and update TeX's filename database. - -Given a family of font files (in either F<.ttf> or F<.otf> format), +Given a family of font files (in either F<otf> or F<ttf> format), B<autoinst> will create several LaTeX font families: =over 2 -=over 2 +=over 3 -=item B<-> +=item - -Four text families (with lining and oldstyle figures, in tabular and +Four text families (with lining and oldstyle digits, in tabular and proportional variants), each with the following shapes: =over 2 -=over 4 +=over 6 =item I<n> @@ -1170,19 +1317,20 @@ Small caps =item I<nw> -`Upright swash'; usually normal text with some extra `oldstyle' ligatures, +"Upright swash"; usually normal text with some extra "oldstyle" ligatures, such as ct, sp and st. =item I<tl> -Titling shape. Meant for all-caps text only (even though it sometimes contains -lowercase glyphs as well), where letterspacing and the positioning of -punctuation characters have been adjusted to suit all-caps text. -This shape is generated only for the families with lining figures. +Titling shape. Meant for all-caps text only (even though it sometimes contains +lowercase glyphs as well), where letterspacing and the positioning of +punctuation characters have been adjusted to suit all-caps text. +This shape is generated only for the families with lining digits, since +all-caps text doesn't mix with old-style digits. =item I<it> -Italic or oblique text +Italic (or oblique) text =item I<scit> @@ -1200,17 +1348,17 @@ Italic titling =back -=item B<-> +=item - -For each text family: a family of TS1-encoded symbol fonts, +For each text family: a family of TS1-encoded symbol fonts, in roman and italic shapes. -=item B<-> +=item - Four families with superiors, inferiors, numerators and denominators, in roman and italic shapes. -=item B<-> +=item - An ornament family, in roman and italic shapes. @@ -1218,12 +1366,12 @@ An ornament family, in roman and italic shapes. =back -Of course, if the font doesn't contain oldstyle figures, small caps etc., -the corresponding shapes or families are not created; -furthermore, the creation of most families and shapes can be controlled by -command-line options (see below). +Of course, if the fonts don't contain oldstyle digits, small caps etc., +the corresponding shapes and families are not created. +Furthermore, the creation of most families and shapes can be controlled by +command-line options (see L</"COMMAND-LINE OPTIONS"> below). -The generated font families are named I<< <FontFamily>-<Suffix> >>, +The generated font families are named I<< <FontFamily>-<Suffix> >>, where I<< <Suffix> >> is one of =over 8 @@ -1246,13 +1394,13 @@ tabular oldstyle figures =item I<Sup> -superior characters (many fonts only have an incomplete set -of superiors: figures, some punctuation and the letters -I<abdeilmnorst>; normal forms will be used for the other characters) +superior characters (many fonts have only an incomplete set of superiors: +digits, punctuation and the letters I<abdeilmnorst>; +normal forms will be used for the other characters) =item I<Inf> -inferior characters; usually only figures and punctuation, +inferior characters; usually only digits and punctuation, normal forms for the other characters =item I<Orn> @@ -1269,29 +1417,30 @@ denominators =back -The generated fonts are named I<< <FontFile>-<suffix>-<shape>-<enc> >>, -where I<< <FontFile> >> is the name of the OpenType file, I<< <suffix> >> -is the same as above (but in lowercase), I<< <shape> >> is either empty, -`sc', `swash' or `titling', and I<< <enc> >> is the encoding. -A typical name in this scheme is F<MinionPro-Regular-osf-sc-ly1>. +The generated fonts are named I<< <FontName>-<suffix>-<shape>-<enc> >>, +where I<< <suffix> >> is the same as above (but in lowercase), +I<< <shape> >> is either empty, "sc", "swash" or "titling", +and I<< <enc> >> is the encoding. +A typical name in this scheme would be "MinionPro-Regular-osf-sc-ly1". =head2 On the choice of text encoding -By default, all text families use the LY1 encoding. This has been chosen -over T1 (Cork) because many OpenType fonts contain additional ligatures -such as fj and Th, and LY1 has a number of empty slots to accommodate these. -Different encodings can be selected using the B< --encoding> -command line option (see below). +By default, B<autoinst> generates text fonts with OT1, T1 and LY1 +encodings, and the generated style files use LY1 as the default text encoding. +LY1 has been chosen over T1 because it has some empty slots to accomodate +the additional ligatures and alternate glyphs provided by many OpenType fonts. +Different encodings can be selected using the I<-encoding> +command-line option (see L</"COMMAND-LINE OPTIONS"> below). -=head2 Using the fonts with LaTeX +=head2 Using the fonts in your LaTeX documents -B<autoinst> generates a style file for using the font in LaTeX documents, -named `<I<FontFamily>>.sty'. This style file also takes care of loading the +B<autoinst> generates a style file for using the font in LaTeX documents, +named F<< <FontFamily>.sty >>. This style file also takes care of loading the F<fontenc> and F<textcomp> packages, if necessary. -To use the font, simply put C<\usepackage{MinionPro}> -(or whatever the font is called) in the preamble of your document. +To use the font, simply put C<<< \usepackage{I<< <FontFamily> >>} >>> +in the preamble of your document. This style file defines a number of options: @@ -1299,268 +1448,321 @@ This style file defines a number of options: =item I<lining, oldstyle, tabular, proportional> -Choose which figures will be used for the text fonts. -The defaults are `oldstyle' and `proportional' (if available). +Choose which digits will be used for the text fonts. +The defaults are "oldstyle" and "proportional" (if available). =item I<ultrablack, ultrabold, heavy, extrablack, black, extrabold, demibold, semibold, bold> -Choose the weight that LaTeX will use for the `bold' weight +Choose the weight that LaTeX will use for the "bold" weight (i.e., the value of C<\bfdefault>). =item I<light, medium, regular> -Choose the weight that LaTeX will use for the `regular' weight +Choose the weight that LaTeX will use for the "regular" weight (i.e., the value of C<\mddefault>). =item I<< scaled=<scale> >> -Scale the font by a factor of I<< <scale> >>. +Scale the font by a factor of I<< <scale> >>. For example: to increase the size of the font by 5%, use the command -C<\usepackage[scaled=1.05]{MyriadPro}>. +C<<< \usepackage[scaled=1.05]{I<< <FontFamily> >>} >>>. This option is only available when the F<xkeyval> package is found in your TeX installation. =back -The style file will also try to load the F<fontaxes> package (part of -the MinionPro for LaTeX project), which gives easy access to various font -shapes and styles. This package can be downloaded from the project's homepage -(F<http://developer.berlios.de/projects/minionpro>) or directly through -the CVS web interface -(F<http://cvs.berlios.de/cgi-bin/viewcvs.cgi/minionpro/MinionPro/tex/>), -and is also available from CTAN as part of the archive F<metrics-base.zip> -(F<http://www.ctan.org/tex-archive/fonts/minionpro/metrics-base.zip>). - -Using the machinery set up by F<fontaxes>, the generated style file -also defines a few commands (which take the text to be typeset as argument) -and declarations (which don't take arguments, but affect all text up to +The style file will also try to load the F<fontaxes> package, +which gives easy access to various font shapes and styles. +It is available from CTAN +(F<http://www.ctan.org/tex-archive/macros/latex/contrib/fontaxes>). +Using the machinery set up by F<fontaxes>, the generated style file also +defines a number of commands (which take the text to be typeset as argument) +and declarations (which don't take arguments, but affect all text up to the end of the current group) of its own: DECLARATION COMMAND SHORT FORM OF COMMAND - + \tlshape \texttitling \texttl - \sufigures \textsuperior \textsu - \infigures \textinferior \textin - + \sufigures \textsuperior \textsu + \infigures \textinferior \textin + In addition, the C<\swshape> and C<\textsw> commands are redefined to place -swash on the secondary shape axis (F<fontaxes> places it on the primary -shape axis); this allows the use of `upright swash'. -Just saying C<\swshape> will still give normal (italic) swash, -but C<\swshape\upshape> results in upright swash. - -Note that there is no separate command for accessing the italic titling shape; -but these commands behave properly when nested, so C<\tlshape\itshape> gives -italic titling. -There are also no commands for accessing the numerator and denominator -fonts; these can be selected using F<fontaxes>' low-level commands, +swash on the secondary shape axis (F<fontaxes> places it on the primary +shape axis); this makes these commands behave properly when nested, so that +C<\swshape\upshape> will give upright swash. + +There are no commands for accessing the numerator and denominator +fonts; these can be selected using F<fontaxes>' standard commands, e.g., C<\fontfigurestyle{numerator}\selectfont>. -The style file also provides a command C<<< \ornament{I<< <number> >>} >>>, -where C<<< I<< <number> >> >>> is a number from 0 to the total number of -ornaments minus one. Ornaments are always typeset using the current family, +The style file also provides a command C<<< \ornament{I<< <number> >>} >>>, +where C<<< I<< <number> >> >>> is a number from 0 to the total number of +ornaments minus one. Ornaments are always typeset using the current family, series and shape. A list of all ornaments in a font can be created by -running LaTeX on the file F<nfssfont.tex> (part of a standard -LaTeX installation) and specifying the ornament font -(e.g., I<MinionPro-Regular-orn-u>). +running LaTeX on the file F<nfssfont.tex> (part of a standard +LaTeX installation) and supplying the name of the ornament font. + +To access the ornaments, B<autoinst> creates a font-specific encoding file +F<< <FontFamily>_orn.enc >>, but only if that file doesn't yet exist. +This means you can provide your own encoding vector, +e.g. if your fonts use non-standard glyph names for ornaments. These commands are only generated for shapes and number styles -that actually exist; no commands are generated for shapes and styles +that actually exist; no commands are generated for shapes and styles that don't exist, or whose generation has been turned off. - -This whole machinery builds on F<fontaxes>; if that package cannot be found, -the style file doesn't provide high-level access to the more `exotic' -font shapes and styles. In that case, you're limited to using the lower-level -commands from standard NFSS. +Please note that these commands are built on top of F<fontaxes>; +if that package cannot be found, you're limited to using the +lower-level commands from standard NFSS (C<\fontfamily>, C<\fontseries>, +C<\fontshape> etc.). =head2 Using multiple font families in one document -If you want to use several font families in one document, make sure -all fonts were installed using the same version of B<autoinst>. -B<autoinst> has seen some non-backward-compatible changes in the past, -and F<.sty> and F<.fd> files that were generated by different versions -of B<autoinst> may not be able to coexist peacefully. +If you want to use more than one font family in a document, be aware +that style files generated by versions of B<autoinst> older dan 2009 +are incompatible with those generated by newer versions. =head2 NFSS codes -In NFSS, weight and width are concatenated into a single `series' attribute. -B<autoinst> maps widths, weights and shapes to NFSS codes using -the following tables. These are based on the tables in Lehman's -F<Font Installation Guide>, but some changes had to be made to avoid -name clashes for font families with many different widths and weights -(such as Helvetica Neue). - - - WEIGHT WIDTH - - Thin t Ultra Condensed uc - Ultra Light ul Extra Condensed ec - Extra Light el Condensed c - Light l Semicondensed sc - Book [1] Regular [1] - Regular [1] Semiextended sx - Medium mb Extended x - Demibold db - Semibold sb - Bold b - Extra Bold eb SHAPES - Black a - Extra Black ea Roman n - Heavy h Italic it - Ultra ub Oblique it [2] - Ultra Bold ub RomanI n [3] - Ultra Black ua RomanII it [3] - +NFSS identifies fonts by a combination of family, series (weight plus width), +shape and size. +B<autoinst> parses the output of C<otfinfo --info> to determine +these parameters. When this fails +(e.g., because the font family contains unusual widths or weights), +B<autoinst> ends up with different fonts having the I<same> values +for the font parameters, which means that these fonts cannot be used in NFSS. +B<autoinst> will then split the font family into multiple subfamilies +(based on the font's "Subfamily" value) and try again. +(Since many font families overdo the "Subfamily" by making each font +a separate subfamily, this strategy is only used as a last resort.) + +If this proliferation of font families is unwanted, +either rerun B<autoinst> on a smaller set of fonts (omitting the ones that +failed to parse correctly) +or else add the missing widths, weights and shapes to the tables C<%FD_WIDTH>, +C<%FD_WEIGHT> and C<%FD_SHAPE>, near the top of the source code. +Please also send a bug report (see L<AUTHOR> below). + +B<autoinst> maps widths, weights and shapes to NFSS codes using +the following tables. These are based both on the standard I<Fontname> scheme +and on the tables in Philipp Lehman's F<Font Installation Guide>, +but some changes had to be made to avoid name clashes in font families +with many different widths and weights. + + + WEIGHT WIDTH + + Thin t Ultra Compressed up + Ultra Light ul Extra Compressed ep + Extra Light el Compressed, Compact p + Light l Compact p + Book [1] Ultra Condensed uc + Regular [1] Extra Condensed ec + Medium mb Condensed c + Demibold db Narrow n + Semibold sb Semicondensed sc + Bold b Regular [1] + Extra Bold eb Semiextended sx + Ultra ub Extended x + Ultra Bold ub Expanded e + Black k Wide w + Extra Black ek + Ultra Black uk + Heavy h SHAPE + Poster r + Roman, Upright n [2] + Italic it + Cursive, Kursiv it + Oblique, Slanted it [3] + Incline(d) it [3] + + +=head3 Notes: =over 4 =item [1] -When I<both> weight and width are empty, the `series' attribute becomes `m'. +When I<both> weight and width are empty, the "series" attribute becomes "m". =item [2] -Mapping the `Oblique' shape to `it' instead of the canonical `sl' simplifies -B<autoinst>. Since font families with both `Italic' and `Oblique' shapes -probably do not exist (apart from Computer Modern), -this shouldn't cause problems in real life. +Adobe Silentium Pro contains two "Roman" shapes ("RomanI" and "RomanII"); +the first of these is mapped to "n", the second one to "it". =item [3] -To the best of my knowledge, the only font family that has two `Roman' shapes -is Silentium; since this has no `Italic' shape, -the `it' code is (ab)used for the `RomanII' shape. +Mapping the "Slanted", "Oblique" or "Inclined" shape to "it" instead of "sl" +simplifies B<autoinst>. Since font families with both italic and slanted +shapes do - to the best of my knowledge - not exist +(apart from Computer Modern, of course), +this shouldn't cause problems in real life. =back - -=head2 A note for MikTeX users -Calling F<otftotfm> with the B< --automatic> option (as B<autoinst> does by -default) requires a TeX-installation that uses the F<kpathsea> library; with -TeX-installations that implement their own directory searching -(such as MiKTeX) F<otftotfm> might complain that it -cannot find a writable F<texmf> directory and leave all generated F<tfm>, -F<vf>, F<enc> and F<map> files in the current working directory. -In that case, you need to move these to their correct destinations. -You also need to tell the dvi-driver (F<dvips>, F<dvipdfm>, F<pdfTeX> etc.) -about the new font map files; see the documentation for how this is done. +=head2 A note for MiKTeX users + +Automatically installing the fonts into a suitable TEXMF tree +(as B<autoinst> does by default) requires a TeX-installation that uses +the F<kpathsea> library; with TeX distributions that implement their +own directory searching (such as MiKTeX), B<autoinst> will complain that +it cannot find the F<kpsewhich> program and install all generated files +into subdirectories of the current directory. +If you use such a TeX distribution, you should either move these files +to their correct destinations by hand, or use the I<-target> option +(see L</"COMMAND-LINE OPTIONS"> below) to specify a TEXMF tree. -Also, some OpenType fonts lead to F<pl> and F<vpl> files that are too -big for MiKTeX's F<pltotf> and F<vptovf>; the versions from TeXLive -(F<http://tug.org/ftp/texlive/Contents/live/bin/win32/>) don't have this -problem. +Also, some OpenType fonts lead to F<pl> and F<vpl> files that +are too big for MiKTeX's F<pltotf> and F<vptovf>; +the versions that come with W32TeX (F<http://www.w32tex.org>) +and TeXLive (F<http://tug.org/texlive>) don't have this problem. =head1 COMMAND-LINE OPTIONS +You may use either one or two dashes before options, +and option names may be shortened to a unique prefix +(e.g., B<-enc> instead of B<-encoding>). + =over 4 -=item B< --encoding>=I<encoding[,encoding]> +=item B<-encoding>=I<encoding[,encoding]> + +Use the specified encodings for the text fonts. The default is "OT1,T1,LY1". +For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>) +should be somewhere where F<otftotfm> can find it. Suitable encoding files +for OT1, T1/TS1 and LY1 come with B<autoinst>. (Note that these files are +called F<fontools_ot1.enc> etc. to avoid name clashes with other packages; +the "fontools_" prefix doesn't need to be specified.) -Use the encoding I<encoding> for the text fonts. The default is `LY1'. -A file named `<I<encoding>>.enc' (in all I<lowercase>) should be somewhere -where F<otftotfm> can find it. Suitable encoding files -for LY1, OT1 and T1/TS1 come with I<fontools>. (Note that these files are -called I<fontools_xxx.enc> to avoid name clashes with other packages; -the `fontools_' prefix doesn't need to be specified.) +Multiple text encodings can be specified as a comma-separated list: +C<-encoding=OT1,T1>. The encodings are passed to F<fontenc> in the order +specified, so the last one will be the default text encoding. -Multiple text encodings can be specified as well: C< --encoding=OT1,T1,LY1>. -The encodings are passed to F<fontenc> in the order specified, -so the last one will be the default text encoding. +=item B<-sanserif> -=item B< --sanserif> +Install the font as a sanserif font, accessed via C<\sffamily> and C<\textsf>. +Note that the generated style file redefines C<\familydefault>, +so including it will still make this font the default text font. -Install the font as a sanserif font, accessed via C<\sffamily> and C<\textsf>. -Note that the generated style file redefines C<\familydefault>, -so including it will make this font the default text font. +=item B<-typewriter> -=item B< --typewriter> +Install the font as a typewriter font, accessed via C<\ttfamily> and +C<\texttt>. +Note that the generated style file redefines C<\familydefault>, +so including it will still make this font the default text font. -Install the font as a typewriter font, accessed via C<\ttfamily> and -C<\texttt>. -Note that the generated style file redefines C<\familydefault>, -so including it will make this font the default text font. +=item B<-ts1> -=item B< --ts1> +=item B<-nots1> -=item B< --nots1> +Turn the creation of TS1-encoded fonts on or off. The default is B<-ts1> +if the text encodings (see I<-encoding> above) include T1, +B<-nots1> otherwise. -Turn the creation of TS1-encoded fonts on or off. The default is B< --ts1> -if the text encodings (see I< --encoding> above) include T1, -B< --nots1> otherwise. +=item B<-smallcaps> -=item B< --smallcaps> +=item B<-nosmallcaps> -=item B< --nosmallcaps> +Turn the creation of small caps fonts on or off. The default is +B<-smallcaps>. -Turn the creation of small caps fonts on or off. The default is -B< --smallcaps>. +=item B<-swash> -=item B< --swash> +=item B<-noswash> -=item B< --noswash> +Turn the creation of swash fonts on or off. The default is B<-swash>. -Turn the creation of swash fonts on or off. The default is B< --swash>. +=item B<-titling> -=item B< --titling> +=item B<-notitling> -=item B< --notitling> +Turn the creation of titling fonts on or off. The default is B<-titling>. -Turn the creation of titling fonts on or off. The default is B< --notitling>. +=item B<-superiors> -=item B< --superiors> +=item B<-nosuperiors> -=item B< --nosuperiors> +Turn the creation of fonts with superior characters on or off. +The default is B<-superiors>. -Turn the creation of fonts with superior characters on or off. -The default is B< --superiors>. +=item B<-inferiors> -=item B< --inferiors> +=item B<-noinferiors> -=item B< --noinferiors> +Turn the creation of fonts with inferior digits on or off. +The default is B<-noinferiors>. -Turn the creation of fonts with inferior figures on or off. -The default is B< --noinferiors>. +=item B<-fractions> -=item B< --fractions> +=item B<-nofractions> -=item B< --nofractions> +Turn the creation of fonts with numerators and denominators on or off. +The default is B<-nofractions>. -Turn the creation of fonts with numerators and denominators on or off. -The default is B< --nofractions>. +=item B<-ornaments> -=item B< --ornaments> +=item B<-noornaments> -=item B< --noornaments> +Turn the creation of ornament fonts on or off. The default is B<-ornaments>. -Turn the creation of ornament fonts on or off. The default is B< --ornaments>. +=item B<-target>=I<DIRECTORY> -=item B< --manual> +Install all generated files into the TEXMF tree at I<DIRECTORY>. -Manual mode. By default, B<autoinst> immediately executes all F<otftotfm> -command lines it generates; with the B< --manual> option, these commands are -instead written to a batch command file (named `<I<font>>.bat', to make things -easier for our friends on Windows). Also, the generated F<otftotfm> command -lines specify the I< --pl> option and leave out the I< --automatic> option; -this causes human readable (and editable) F<pl> and F<vpl> files to be created -instead of the default F<tfm> and F<vf> files. +By default, B<autoinst> searches your $TEXMFLOCAL and $TEXMFHOME paths +and installs all files into subdirectories of the first writable TEXMF tree +it finds (or into subdirectories of the current directory, +if no writable directory is found). -=item B< --verbose> +B<Note>: this option gets overriden by the B<-manual> option! + +=item B<-manual> + +Manual mode. By default, B<autoinst> immediately executes all F<otftotfm> +command lines it generates; with the B<-manual> option, these commands are +instead written to a file F<autoinst.bat>. +Also, the generated F<otftotfm> command lines specify the I< --pl> option +(which tells F<otftotfm> to generate readable/editable F<pl> and F<vpl> files +instead of the default F<tfm> and F<vf> files) +and leave out the I< --automatic> option (which tells F<otftotfm> to +leave all generated files in the current directory, rather than install +them into your TEXMF tree). + +When using this option, you should run F<pltotf> and F<vptovf> after +executing all commands, +to convert the F<pl> and F<vf> files to F<tfm> and F<vf> format. + +B<Note>: this option overrides the B<-target> option! + +=item B<-verbose> Verbose mode; print detailed info about what B<autoinst> thinks it's doing. -=item B< --extra>=I<text> +=item B<-extra>=I<text> -Pass I<text> as options to I<otftotfm>. To prevent I<text> from accidentily +Pass I<text> as options to I<otftotfm>. To prevent I<text> from accidentily being interpreted as options to B<autoinst>, it should be properly quoted. +=item B<-figurekern> + +=item B<-nofigurekern> + +Some fonts provide kerning pairs for tabular figures. +This is probably unwanted (e.g., numbers in tables won't line up exactly). +The option B<-nofigurekern> adds extra I< --ligkern> options +to the command lines for I<otftotfm> to suppress such kerns +(but only for the "TLF" and "TOsF" families). +Since this leads to very long command lines (it adds one hundred such options) +and the problem affects only few fonts, the default is B<-figurekern>. + =back @@ -1568,52 +1770,48 @@ being interpreted as options to B<autoinst>, it should be properly quoted. Eddie Kohler's TypeTools (F<http://www.lcdf.org/type>). -Perl is usually pre-installed on Linux and Unix systems; -on Windows, try ActivePerl (available from F<http://www.activestate.com>) -or Strawberry Perl (F<http://strawberryperl.com>). +Perl is pre-installed on most Linux and Unix systems; +on Windows, try ActiveState's ActivePerl +(available from F<http://www.activestate.com>) +or Strawberry Perl (F<http://strawberryperl.com>). -XeTeX (F<http://www.tug.org/xetex>) is an extension of TeX -that can natively use any font installed in the operating system -(including both flavours of OpenType fonts) -without additional support files. +XeTeX (F<http://www.tug.org/xetex>) and LuaTeX (F<http://www.luatex.org>) +are TeX extensions that can use any font (including both flavours of OpenType) +without TeX-specific support files. -John Owens' F<otfinst> (available from CTAN) is another wrapper +John Owens' F<otfinst> (available from CTAN) is another wrapper around F<otftotfm>, and may work when B<autoinst> doesn't. -The MinionPro for LaTeX project -(F<http://developer.berlios.de/projects/minionpro/>, also on CTAN) -developed very complete support files for Minion Pro (including math), +The MinionPro for LaTeX project +(F<http://developer.berlios.de/projects/minionpro/>, also on CTAN) +developed very complete support files for Minion Pro (including math), but the project appears to have been abandoned; -these files don't work with recent versions of Minion Pro. +these files don't work with the latest versions of Minion Pro. =head1 AUTHOR -Marc Penninga <marc@penninga.info> - -When sending a bug report, please give as much relevant information as -possible; this usually includes (but may not be limited to) the output from -running B<autoinst> with the B< --verbose> option. -Please make sure that this output includes all error messages (if any); -this can be done using the command +Marc Penninga <marcpenninga@gmail.com> -C<< autoinst I<(... all options and files ...)> E<gt>autoinst.log 2>&1 >> +When sending a bug report, please give as much relevant information as +possible; this includes at least (but may not be limited to) the output +from running B<autoinst> with the I<-verbose> option. +Please make sure that this output includes all (if any) error messages. =head1 COPYRIGHT -Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 Marc Penninga. +Copyright (C) 2005-2012 Marc Penninga. =head1 LICENSE This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License -as published by the Free Software Foundation, -either version 2 of the License, or (at your option) -any later version. -A copy of the GNU General Public License is included with the I<fontools> -collection; see the file F<GPLv2.txt>. +it under the terms of the GNU General Public License as published +by the Free Software Foundation, either version 2 of the License, +or (at your option) any later version. +A copy of the GNU General Public License is included with B<autoinst>; +see the file F<GPLv2.txt>. =head1 DISCLAIMER @@ -1627,36 +1825,60 @@ GNU General Public License for more details. =head1 RECENT CHANGES -(See the source code for the full story.) +(See the source code for the rest of the story.) =over 12 +=item I<2012-03-06> + +Implemented the "splitting the font family into multiple subfamilies" +emergency strategy when font info parsing fails. +Added recognition for a number of unusual widths, weights and shapes. + +=item I<2012-02-29> + +Fixed a bug in the font parsing code, +where possible widths, weights and shapes where tested in the wrong order; +this led to "ExtraLight" fonts being recognised as "Light". +Added recognition for "Narrow" and "Wide" widths. +Also added the I<-(no)figurekern> command-line option. + +=item I<2012-02-01> + +Reorganised the code, and fixed some bugs in the process. +Added the I<-target> command-line option. +Made B<autoinst> install the F<fd> and F<sty> files in +the same TEXMF tree as the other generated files. +Generate OT1, T1 and LY1 encoded text fonts by default. +Made I<-titling> a default option (instead of I<-notitling>). +Updated the documentation. + =item I<2011-06-15> Fixed the font info parsing code for some fonts that are -too lazy to spell out 'Italic' in full. +too lazy to spell out "Italic" in full. =item I<2010-04-29> -The C< --feature=kern> option is only used for fonts that +The I< --feature=kern> option is only used for fonts that contain either a I<kern> feature or a I<kern> table. -Font feature selection commands in the F<.sty> file are only -generated for shapes and figure styles that are supported +Font feature selection commands in the F<sty> file are only +generated for shapes and figure styles that are supported by the current font, and whose generation has not been -turned off using the command line options. +turned off using the command-line options. Fixed the font info parsing to work with the Condensed fonts in the Minion Pro family. =item I<2010-04-23> -Always provide the C< --feature=kern> option to F<otftotfm>, -even if the font doesn't have a I<kern> feature; +Always provide the I< --feature=kern> option to F<otftotfm>, +even if the font doesn't have a I<kern> feature; this will make F<otftotfm> use the I<kern> table if present. -For fonts without a I<liga> feature, add C< --ligkern> +For fonts without a I<liga> feature, add I< --ligkern> options for the common f-ligatures to the F<otftotfm> command line, so that any ligatures present in the font will still be used. -Bug fix: the generated F<.sty> files now work for font families -with names containing digits. +Bug fix: the generated F<sty> files now work for font families +with names containing digits. =item I<2009-04-09> @@ -1665,13 +1887,16 @@ I<fontools_>, to prevent name clashes with other packages. =item I<2009-04-06> -A small patch to the C<make_ornament_encoding> subroutine; -it now also recognises the I<bullet.xxx> ornament glyphs -in Adobe's Kepler Pro. +A small patch to the C<get_orn> subroutine: +it now also recognises the I<bullet.xxx> ornament glyphs +in Adobe Kepler Pro. + +=back =begin Really_old_history +=over 12 =item I<2007-08-07> @@ -1680,17 +1905,17 @@ Fixed a small bug with filename quoting on Windows. =item I<2007-07-31> Changed the tables that map weights and widths to NFSS codes: -in some extended families (Helvetica Neue), different combinations of -weight and width were mapped to the same `series'. +in some extended families, different combinations of +weight and width were mapped to the same series. Added a work-around for incorrect size info in some Kepler fonts. -Fixed a small bug in the generated commands for otftotfm -(sometimes, the I< --onum> feature was included twice). +Fixed a small bug in the generated commands for otftotfm +(sometimes, the "onum" feature was included twice). Added encoding file for OT1 to the I<fontools> collection. =item I<2007-07-27> -Two bugfixes: a closing brace was missing in the generated style file, -and the NFSS series was formed as `width plus weight' instead of the reverse. +Two bugfixes: a closing brace was missing in the generated style file, +and the NFSS series was formed as "width plus weight" instead of the reverse. =item I<2007-06-10> @@ -1700,92 +1925,92 @@ caused problems for some other packages. =item I<2007-06-04> -Added the F< --no-updmap> option to all generated commands for F<otftotfm> +Added the I< --no-updmap> option to all generated commands for F<otftotfm> (except the last); this should yield a significant speed-up for large families (suggested by Steven E. Harris). Tweaked the font info parsing to work around a bug in the naming of some FontFont fonts, where every font is in a family of its own. -Added the `scaled' option (including the loading of F<xkeyval>) +Added the "scaled" option (including the loading of F<xkeyval>) to the generated style file. -Extended the output of the F< --verbose> option. +Extended the output of the I<-verbose> option. =item I<2007-02-08> -Yet Another Complete Rewrite. -The code is now much more readable and more flexible; +Yet Another Complete Rewrite. +The code is now much more readable and more flexible; the program can now handle fonts from different families, -as well as multiple text encodings. +as well as multiple text encodings. Rewrote the font info parsing code to work for Arno Pro. =item I<2006-10-11> The program determines the fonts' weights, widths and shapes by parsing -the output from F<otfinfo --info> instead of the font filename. -This should make B<autoinst> work for non-Adobe fonts. +the output from C<otfinfo --info> instead of the font filename. +This should make B<autoinst> work for non-Adobe fonts. Filenames with spaces now work as well. =item I<2006-08-31> -Made the generated style files try to include `fontaxes.sty'; -changed the names of the generated fonts and families +Made the generated style files try to include "fontaxes.sty"; +changed the names of the generated fonts and families (to make the previous change possible); -added command line options for most font styles and shapes; +added command-line options for most font styles and shapes; tweaked the filename parsing code for Cronos Pro and Gill Sans Pro; added runtime generation of encoding vectors for ornament fonts (because GaramondPremier's ornament names differ from other fonts); -changed the NFSS-code for italic small caps and titling to `scit' and `tlit' -(to work with F<fontaxes>); +changed the NFSS-code for italic small caps and titling to "scit" and "tlit" +(to work with F<fontaxes>); and edited (and hopefully improved) the documentation. =item I<2005-10-03> -When creating LY1, T1, OT1 or TS1 encoded fonts, the I< --coding-scheme> -option is added to the commands for F<otftotfm>; this should make the +When creating LY1, T1, OT1 or TS1 encoded fonts, the I<-coding-scheme> +option is added to the commands for F<otftotfm>; this should make the generated F<pl> and F<vpl> files acceptable to I<fontinst>. Also elaborated the documentation somewhat and fixed a small bug. =item I<2005-09-22> -Added check to see if filename parsing succeeded; -updated the filename parsing code to cater for GaramondPremier, Silentium +Added check to see if filename parsing succeeded; +updated the filename parsing code to cater for GaramondPremier, Silentium and some non-Adobe fonts; -added the B< --sanserif> and B< --typewriter> options and hacked the +added the I<-sanserif> and I<-typewriter> options and hacked the style files to support using several different font families in one document. =item I<2005-09-12> Cleaned up the code (it now runs under the F<strict> and F<warnings> pragmas); -fixed a (rather obscure) bug that occurred when creating TS1-encoded -fonts for families with multiple optical masters and oldstyle figures; +fixed a (rather obscure) bug that occurred when creating TS1-encoded +fonts for families with multiple optical masters and oldstyle digits; added the I<medium, semibold> etc. options to the style file; and improved the layout of the generated files. =item I<2005-08-11> The generated commands weren't actually executed, only printed.... -Also added a small hack to cater for fonts -(such as some recent versions of MinionPro) -that contain swash characters but don't provide a `swsh' feature. +Also added a small hack to cater for fonts +(such as some recent versions of MinionPro) +that contain swash characters but don't provide a "swsh" feature. =item I<2005-08-10> -Dropped the `fontname' scheme in favor of a more verbose naming scheme, -since many filenames were still more than eight characters long anyway. +Dropped the "fontname" scheme in favor of a more verbose naming scheme, +since many filenames were still more than eight characters long anyway. Added F<nfssext.sty>-like commands to the generated style file. -Changed the default encoding to LY1 and added the `inferior' shape. +Changed the default encoding to LY1 and added the "inferior" shape. =item I<2005-08-01> -Rewrote (and hopefully improved) the user interface; -changed the program to by default execute the generated F<otftotfm> command -lines rather than writing them to a file; -added automatic determination of the `fontname' code for the font family; -changed the NFSS code for italic small caps to `si'; added titling shapes; -changed the generated style -file to include an interface for the ornaments and to load Lehman's NFSS -extensions F<nfssext.sty> if this is installed; corrected the `fontname' codes +Rewrote (and hopefully improved) the user interface; +changed the program to by default execute the generated F<otftotfm> command +lines rather than writing them to a file; +added automatic determination of the "fontname" code for the font family; +changed the NFSS code for italic small caps to "si"; added titling shapes; +changed the generated style +file to include an interface for the ornaments and to load Lehman's NFSS +extensions F<nfssext.sty> if this is installed; corrected the "fontname" codes for OT1, T1, LY1 and user-specific encodings; extended the output generated by -the B< --verbose> option; and rewrote and extended the documentation. +the I<-verbose> option; and rewrote and extended the documentation. =item I<2005-06-16> diff --git a/Build/source/texk/texlive/linked_scripts/fontools/cmap2enc b/Build/source/texk/texlive/linked_scripts/fontools/cmap2enc deleted file mode 100755 index 4ba6842e179..00000000000 --- a/Build/source/texk/texlive/linked_scripts/fontools/cmap2enc +++ /dev/null @@ -1,5307 +0,0 @@ -#!/usr/bin/perl - -=begin COPYRIGHT ------------------------------------------------------------ - - cmap2enc - convert glyph indices in a TrueType-flavored OpenType font to - Adobe glyph names - - Copyright (c) 2005, 2006 Marc Penninga. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to - - Free Software Foundation, Inc., - 59 Temple Place, - Suite 330, - Boston, MA 02111-1307, - USA - -=end ------------------------------------------------------------------------ - -=cut - -use Getopt::Std; -use integer; -use warnings; no warnings qw(uninitialized); - -%friendly_name = ( - aalt => "Access All Alternates", - afrc => "Alternate Fractions", - alts => "Alternate Forms", - calt => "Contextual Alternates", - case => "Case-Sensitive Forms", - clig => "Contextual Ligatures", - cpsp => "Capital Spacing", - cswh => "Contextual Swash", - c2sc => "Small Capitals From Capitals", - dlig => "Discretionary Ligatures", - dnom => "Denominators", - expt => "Expert Forms", - fina => "Terminal Forms", - frac => "Fractions", - hist => "Historical Forms", - hlig => "Historical Ligatures", - init => "Initial Forms", - liga => "Standard Ligatures", - lnum => "Lining Figures", - numr => "Numerators", - onum => "Oldstyle Figures", - ordn => "Ordinals", - ornm => "Ornaments", - pnum => "Proportional Figures", - rlig => "Required Ligatures", - salt => "Stylistic Alternates", - sinf => "Scientific Inferiors", - smcp => "Small Caps", - subs => "Subscripts", - sups => "Superscripts", - swsh => "Swash", - titl => "Titling", - tnum => "Tabular Figures", - zero => "Slashed Zero", -); - -sub getu($) { - my $arg = shift; - my $n = length $arg; - my $r = 0; - - for my $i (0 .. $n - 1) { - $r = ($r << 8) + unpack("C", substr($arg, $i, 1)); - } - - return $r; -} - -sub getcov($) { - my $Coverage = shift; - my $CoverageFormat = getu(substr $Coverage, 0, 2); - my @r = (); - if ($CoverageFormat == 1) { - my $GlyphCount = getu(substr $Coverage, 2, 2); - for my $i (0 .. $GlyphCount - 1) { - push @r, getu(substr $Coverage, 4 + 2 * $i, 2); - } - } elsif ($CoverageFormat == 2) { - my $RangeCount = getu(substr $Coverage, 2, 2); - for my $i (0 .. $RangeCount - 1) { - my $RangeRecord = substr $Coverage, 4 + 6 * $i, 6; - my $Start = getu(substr $RangeRecord, 0, 2); - my $End = getu(substr $RangeRecord, 2, 2); - for my $j ($Start .. $End) { - push @r, $j; - } - } - } else { - warn "Warning: unknown CoverageFormat `$CoverageFormat'\n"; - } - return @r; -} - - -############################################################################## - - -getopts "f:l:ps:x:", \%options; -if ($options{f}) { - for (split ",", $options{f}) { - $feature_selected{$_} = 1; - } -} -$suffix = $feature_selected{ pnum } ? '-' : '-t'; -$suffix .= $feature_selected{ onum } ? 'osf' : 'lf'; -$suffix .= $feature_selected{ smcp } ? '-sc' : ''; -$suffix .= $feature_selected{ swsh } ? '-swash' : ''; -$suffix .= $feature_selected{ titl } ? '-titling' : ''; - -if ( $feature_selected{ sups } ) { $suffix = '-sup' } -if ( $feature_selected{ ornm } ) { $suffix = '-orn' } - -$options{s} ||= "latn"; -$options{l} ||= "DFLT"; - -$0 =~ s!.*/!!; -die "Usage: $0 [options] fontfile encfile\n" - unless ($options{p} and @ARGV == 1) or @ARGV == 2; - -chop(@glyph = <DATA>); -for (@glyph) { - next if /^\s*\#/; - /(.+);([\dA-Fa-f]{4})/ and $code{$1} = $2; -} - -if ((chop($fn = `kpsewhich $ARGV[0] 2>&1`) and -e $fn) or - (chop($fn = `findtexmf $ARGV[0] 2>&1`) and -e $fn)) -{ - open FONT, "<$fn" or die "Error: can't open `$fn' - $!\n"; -} else { - open FONT, "<$ARGV[0]" or - die "Error: can't open `$ARGV[0]' - $!\n"; -} -binmode FONT; -{ - local $/; - $font = <FONT>; -} - -$OffsetTable = substr $font, 0, 12; -$numTables = getu(substr $OffsetTable, 4, 2); - -$TableDirectory = substr $font, 12, 16 * $numTables; -for $i (0 .. $numTables - 1) { - $entry = substr $TableDirectory, 16 * $i, 16; - - $tag = substr $entry, 0, 4; - $offset{$tag} = getu(substr $entry, 8, 4); - $length{$tag} = getu(substr $entry, 12, 4); -} - -if (exists $offset{GSUB}) { - $GSUB = substr $font, $offset{GSUB}, $length{GSUB}; - $ScriptList = substr $GSUB, getu(substr $GSUB, 4, 2); - $FeatureList = substr $GSUB, getu(substr $GSUB, 6, 2); - $LookupList = substr $GSUB, getu(substr $GSUB, 8, 2); - - $LookupCount = getu(substr $LookupList, 0, 2); - undef @Lookup; - undef @LookupType; - for $i (0 .. $LookupCount - 1) { - $Lookup = substr $LookupList, getu(substr $LookupList, 2 + 2 * $i, 2); - $LookupType[$i] = getu(substr $Lookup, 0, 2); - next unless $LookupType[$i] == 1; - $SubTableCount = getu(substr $Lookup, 4, 2); - for $j (0 .. $SubTableCount - 1) { - $SubTable = substr $Lookup, getu(substr $Lookup, 6 + 2 * $j, 2); - $SubstFormat = getu(substr $SubTable, 0, 2); - if ($SubstFormat == 1) { - $Coverage = substr $SubTable, getu(substr $SubTable, 2, 2); - @Coverage = getcov($Coverage); - $DeltaGlyphID = getu(substr $SubTable, 4, 2); - for $k (0 .. $#Coverage) { - $Lookup[$i]{$Coverage[$k]} = $Coverage[$k] + $DeltaGlyphID; - } - } elsif ($SubstFormat == 2) { - $Coverage = substr $SubTable, getu(substr $SubTable, 2, 2); - @Coverage = getcov($Coverage); - $GlyphCount = getu(substr $SubTable, 4, 2); - if ($GlyphCount != scalar(@Coverage)) { - warn "Error: SingleSubstFormat2 subtable - " . - "GlyphCount wrong\n"; - next; - } - for $k (0 .. $#Coverage) { - $Lookup[$i]{$Coverage[$k]} = - getu(substr $SubTable, 6 + 2 * $k, 2); - } - } else { - warn "Error: unknown SingleSubstFormat `$SubstFormat'\n"; - next; - } - } - } - - undef @FeatureTag; - undef @FeatureLookupListIndex; - $FeatureCount = getu(substr $FeatureList, 0, 2); - for $i (0 .. $FeatureCount - 1) { - $FeatureRecord = substr $FeatureList, 2 + 6 * $i, 6; - $FeatureTag[$i] = substr $FeatureRecord, 0, 4; - $Feature = substr $FeatureList, getu(substr $FeatureRecord, 4, 2); - $LookupCount = getu(substr $Feature, 2, 2); - $feature_supported{$FeatureTag[$i]} = 1; - for $j (0 .. $LookupCount - 1) { - $FeatureLookupListIndex[$i][$j] = - getu(substr $Feature, 4 + 2 * $j, 2); - if ($LookupType[$FeatureLookupListIndex[$i][$j]] != 1) { - $feature_supported{$FeatureTag[$i]} = 0; - } - } - } - - undef %Script; - undef %FeatureIndex; - $ScriptCount = getu(substr $ScriptList, 0, 2); - for $i (0 .. $ScriptCount - 1) { - $ScriptRecord = substr $ScriptList, 2 + 6 * $i, 6; - $ScriptTag = substr $ScriptRecord, 0, 4; - $Script = substr $ScriptList, getu(substr $ScriptRecord, 4, 2); - if (substr($Script, 0, 2)) { - $LangSysTag = "DFLT"; - push @{$Script{$ScriptTag}}, $LangSysTag; - $LangSys = substr $Script, getu(substr $Script, 0, 2); - $FeatureCount = getu(substr $LangSys, 4, 2); - for $k (0 .. $FeatureCount - 1) { - push @{$FeatureIndex{$ScriptTag}{$LangSysTag}}, - getu(substr $LangSys, 6 + 2 * $k, 2); - } - } - $LangSysCount = getu(substr $Script, 2, 2); - for $j (0 .. $LangSysCount - 1) { - $LangSysRecord = substr $Script, 4 + 6 * $j, 6; - $LangSysTag = substr $LangSysRecord, 0, 4; - push @{$Script{$ScriptTag}}, $LangSysTag; - $LangSys = substr $Script, getu(substr $LangSysRecord, 4, 2); - $FeatureCount = getu(substr $LangSys, 4, 2); - for $k (0 .. $FeatureCount - 1) { - push @{$FeatureIndex{$ScriptTag}{$LangSysTag}}, - getu(substr $LangSys, 6 + 2 * $k, 2); - } - } - } -} - -if (exists $offset{GPOS}) { - $GPOS = substr $font, $offset{GPOS}, $length{GPOS}; - $FeatureList = substr $GPOS, getu(substr $GPOS, 6, 2); - $FeatureCount = getu(substr $FeatureList, 0, 2); - for $i (0 .. $FeatureCount - 1) { - $FeatureRecord = substr $FeatureList, 2 + 6 * $i, 6; - $FeatureTag = substr $FeatureRecord, 0, 4; - $feature_supported{$FeatureTag} = 0; - } -} - -if ($options{p}) { - if (exists $offset{name}) { - $name = substr $font, $offset{name}, $length{name}; - $count = getu(substr $name, 2, 2); - $stringOffset = getu(substr $name, 4, 2); - for $i (0 .. $count - 1) { - $nameRecord = substr $name, 6 + 12 * $i, 12; - $platformID = getu(substr $nameRecord, 0, 2); - $encodingID = getu(substr $nameRecord, 2, 2); - $languageID = getu(substr $nameRecord, 4, 2); - $nameID = getu(substr $nameRecord, 6, 2); - $length = getu(substr $nameRecord, 8, 2); - $offset = getu(substr $nameRecord, 10, 2); - $string = substr $name, $stringOffset + $offset, $length; - $string{"$platformID,$encodingID,$languageID,$nameID"} = $string; - } - print "\n", "-" x 80, "\n\n"; - for $i ((6,10,0)) { - if (exists $string{"0,3,0,$i"}) { - print $string{"0,3,0,$i"}, "\n\n"; - } elsif (exists $string{"0,4,0,$i"}) { - print $string{"0,4,0,$i"}, "\n\n"; - } elsif (exists $string{"3,1,1033,$i"}) { - print $string{"3,1,1033,$i"}, "\n\n"; - } elsif (exists $string{"3,10,1033,$i"}) { - print $string{"3,10,1033,$i"}, "\n\n"; - } - } - print "-" x 80, "\n\n"; - } - print "SCRIPT\tLANG\tFEATURES\n\n"; - for $script (keys %Script) { - print "$script"; - for $lang (@{$Script{$script}}) { - print "\t$lang\t"; - for (sort {$a <=> $b} @{$FeatureIndex{$script}{$lang}}) { - print "$FeatureTag[$_]", - exists $friendly_name{$FeatureTag[$_]} - ? " - $friendly_name{$FeatureTag[$_]}" - : " - Unknown Feature", - $feature_supported{$FeatureTag[$_]} - ? "" - : " (not supported by $0)", - "\n\t\t"; - } - print "\n"; - } - } - print "-" x 80, "\n\n"; -} - -undef @subst; -for $i (0 .. 0xFFFF) { - $subst[$i] = $i; -} - -undef %lookup_selected; -for $feature (sort {$a <=> $b} @{$FeatureIndex{$options{s}}{$options{l}}}) { - if (!$feature_selected{$FeatureTag[$feature]}) { - next; - } - if (!$feature_supported{$FeatureTag[$feature]}) { - warn "Warning: feature `$FeatureTag[$feature]' not supported\n"; - next; - } - for (@{$FeatureLookupListIndex[$feature]}) { - $lookup_selected{$_} = 1; - } -} -for $lookup (sort {$a <=> $b} keys %lookup_selected) { - for (sort {$a <=> $b} keys %{$Lookup[$lookup]}) { - $subst[$_] = $Lookup[$lookup]{$_}; - } -} - -if ($options{x}) { - open SUB, "<$options{x}" - or warn "Warning: can't open `$options{x}' - $!\n\tfile skipped\n"; - for (<SUB>) { - if (/^\s*\#/) { - next; - } elsif (/([0-9A-Fa-f]{4});([0-9A-Fa-f]{4})/) { - $subst[hex($1)] = hex($2); - $subst[hex($2)] = hex($2); - } elsif (/(\w+);([0-9A-Fa-f]{4})/) { - $glyphName{$1} ||= sprintf - hex($2) < 256 ? "index0x%02X" : "index0x%04X", hex $2; - delete $code{$1}; - $subst[hex($2)] = hex($2); - } - } -} - -$cmap = substr $font, $offset{cmap}, $length{cmap}; -$numTables = getu(substr $cmap, 2, 2); - -for $i (0 .. $numTables - 1) { - $EncodingRecord = substr $cmap, 4 + $i * 8, 8; - $platformID = getu(substr $EncodingRecord, 0, 2); - $encodingID = getu(substr $EncodingRecord, 2, 2); - $offset = getu(substr $EncodingRecord, 4, 4); - $format = getu(substr $cmap, $offset, 2); - $length = getu(substr $cmap, $offset + 2, 2); - $subtable = substr $cmap, $offset, $length; - - next unless ($platformID == 0 and ($encodingID == 3 or $encodingID == 4)) - or ($platformID == 3 and ($encodingID == 1 or $encodingID == 10)); - - if ($format == 4) { - $segCountX2 = getu(substr $subtable, 6, 2); - $segCount = $segCountX2 / 2; - - $endCount = substr $subtable, 14, $segCountX2; - $startCount = substr $subtable, 16 + $segCountX2, $segCountX2; - $idDelta = substr $subtable, 16 + 2 * $segCountX2, $segCountX2; - $idRangeOffset = substr $subtable, 16 + 3 * $segCountX2, $segCountX2; - - for $j (0 .. $segCount - 1) { - $endCount[$j] = getu(substr $endCount, 2 * $j, 2); - $startCount[$j] = getu(substr $startCount, 2 * $j, 2); - $idDelta[$j] = getu(substr $idDelta, 2 * $j, 2); - $idRangeOffset[$j] = getu(substr $idRangeOffset, 2 * $j, 2); - - next if $startCount[$j] == 0xFFFF; - - for $characterCode ($startCount[$j] .. $endCount[$j]) { - if ($idRangeOffset[$j] != 0) { - $ptr = $idRangeOffset[$j] / 2 - + $characterCode - $startCount[$j] - + 8 + 3 * $segCount - + $j; - $tmp = getu(substr $subtable, 2 * $ptr, 2); - if ($tmp) { - $glyphIndex = ($tmp + $idDelta[$j]) % 65536; - } else { - $glyphIndex = 0; - } - } else { - $glyphIndex = ($characterCode + $idDelta[$j]) % 65536; - } - $glyphIndex = $subst[$glyphIndex]; - $uni = sprintf "%04X", $characterCode; - $glyphName{$uni} ||= sprintf - $glyphIndex < 256 ? "index0x%02X" : "index0x%04X", - $glyphIndex; - } - } - last; - } else { - warn "Warning: unsupported format `$format'\n"; - } -} -if (!keys %glyphName) { - die "Error: no supported platformID/encodingID found in `cmap' table\n"; -} - -if (!$options{p}) { - if ((chop($fn = `kpsewhich $ARGV[1] 2>&1`) and -e $fn) or - (chop($fn = `findtexmf $ARGV[1] 2>&1`) and -e $fn)) - { - open ENC, "<$fn" or die "Error: can't open `$fn' - $!\n"; - } else { - open ENC, "<$ARGV[1]" or die "Error: can't open `$ARGV[1]' - $!\n"; - } - chop(@lines = <ENC>); - map s/%.+//, @lines; - $_ = join "", @lines; - ($name, $_) = /\/([\w-]+)\s*\[(.*)\]\s*def/; - @vector = /([\w.]+)/g; - - $ARGV[0] =~ /(.+)\.(?:ttf|otf)/ and $fontname = $1; - $ARGV[1] =~ /(.+)\.enc/ and $encname = $1; - open ENC, ">${encname}${suffix}-${fontname}.enc" or die - "Error: can't open `${encname}${suffix}-${fontname}.enc' - $!\n"; - print ENC "/${name}${suffix}-${fontname} [\n"; - for ($i = 0; $i < 256; $i += 16) { - printf ENC "%% 0x%04x\n", $i; - for ($j = 0; $j < 16; $j += 4) { - for $k (0 .. 3) { - print ENC " /", - $glyphName{$code{$vector[$i + $j + $k]}} || - $glyphName{$vector[$i + $j + $k]} || - $vector[$i + $j + $k]; - } - print ENC "\n"; - } - } - print ENC "] def\n"; - - open MTX, ">reset${fontname}-${encname}${suffix}.mtx" - or die "Error: can't open " . - "'reset${fontname}-${encname}${suffix}.mtx' - $!\n"; - print MTX <<EOF; -\\relax -\\metrics -\\needsfontinstversion{1.900} - -\\setcommand\\deleteGlyph#1{ - \\ifisglyph{#1}\\then - \\unsetglyph{#1} - \\noleftrightkerning{#1} - \\fi -} - -\\setcommand\\renameGlyph#1#2{ - \\ifisglyph{#1}\\then - \\setglyph{#2} - \\glyph{#1}{1000} - \\endsetglyph - \\setleftrightkerning{#2}{#1}{1000} - \\deleteGlyph{#1} - \\fi -} - -EOF - - for (@vector) { - if ($glyphName{$code{$_}}) { - print MTX "\\renameGlyph{$glyphName{$code{$_}}}{$_}\n"; - } elsif ($glyphName{$_}) { - print MTX "\\renameGlyph{$glyphName{$_}}{$_}\n"; - } - } - print MTX "\n\\endmetrics\n"; -} - -__END__ - -=pod - - -=head1 NAME - -cmap2enc - convert glyph indices in a TrueType-flavored OpenType font to -Adobe glyph names - - -=head1 SYNOPSIS - -cmap2enc [options] I<fontfile> I<encoding> - - -=head1 DESCRIPTION - -Many TrueType-flavored OpenType fonts contain no glyph names. -When creating an F<afm> file with F<ttf2afm>, this causes all glyphs to be -named something -like C<index0x01E7>, which makes the F<afm> file almost useless for use with -F<fontinst> or F<afm2tfm>. - -B<cmap2enc> uses the font's `cmap' table to map glyph indices to -Unicode values, and Adobe's F<glyphlist.txt> file to map these to glyph names. - -B<cmap2enc> creates a new encoding file (for downloading with the font file) -and a F<mtx> file (for use with F<fontinst>). The encoding file contains the -same glyphs as the original one, but has all glyph names replaced with -the corresponding glyph indices; the F<mtx> file maps these glyph indices back -to the original glyph names (it consists of many commands of the form -C<\renameGlyph{index0x01E7}{Euro}>, plus a definition of that -C<\renameGlyph> command). - -Some of the glyph substitution features of OpenType fonts are supported; -e.g. when the `smcp' (Small Caps) feature is specified, the glyph names -of the lowercase glyphs will be mapped to the glyph indices of the -small capitals. - -A list of features supported by the font can be generated using the B<-p> -option, see below. - - -=head1 EXAMPLES - -NOTE: the F<examples/> subdirectory in the I<fontools> distribution contains -several complete examples of the use of B<cmap2enc> and other tools from -the I<fontools> collection. - -=over 2 - -=item B<-> - -To display all scripts, languages and features supported by Linotype Palatino: - - cmap2enc -p pala.ttf - - -=item B<-> - -To install Linotype Palatino in T1 encoding, with oldstyle figures: - -=over 3 - -=item B<1.> - -Generate an encoding file F<t1-tosf-pala.enc> and a metrics file -F<resetpala-t1-osf.mtx>: - - cmap2enc -f onum pala.ttf t1.enc - - -=item B<2.> - -Create an F<afm> file for the font; this is done best using I<font2afm> -(also in the I<fontools> collection): - - font2afm pala.ttf - - -=item B<3.> - -Reencode the F<afm> file using the F<t1-tosf-pala.enc> encoding to create -a `raw' font I<rlplrj9d>, with either I<afm2afm> (also in the I<fontools> -collection) or I<fontinst> (but be warned that I<fontinst> might take a long -time, and can even crash if the F<afm> is really big): - - afm2afm -e t1-tosf-pala.enc -o rlplrj9d.afm pala.afm - -or - - \transformfont{rlplrj9d}{\reencodefont{t1-tosf-pala}{\fromafm{pala}}} - - -=item B<4.> - -Create a `value-added' F<vpl> file from this raw font by adding -ligatures, faking missing glyphs etc. with I<fontinst>: - - \installfont{lplrj9d}{rlplrj9d,resetpala-t1-tosf,newlatin} - {t1}{T1}{lplj}{m}{n}{} - - -=back - -=back - - -=head1 OPTIONS - -B<cmap2enc> supports the following command-line options: - -=over 4 - -=item B<-p> - -Print some info about the font, plus a list of all scripts, languages and -features contained in this font's GSUB table; then exit. (When using -this option, the I<encoding> need not be specified.) - -=item B<-f> I<feature>[,I<feature>]* - -Use the specified features when matching glyph indices to glyph names. -Multiple features can be specified as a comma-separated list, -B<without> spaces between the items. - -=item B<-x> I<extra> - -Use the user-specified substitutions from I<extra> (see below). - -=item B<-l> I<language> - -Select the specified language. The default is `DFLT' (surprise!). - -=item B<-s> I<script> - -Select the specified script. The default is `latn'. - -=back - - -=head1 FILES - -All input files are searched using B<kpsewhich> or B<findtexmf> when these -commands are available; otherwise only the current working directory -is searched. - -=over 4 - -=item I<fontfile> - -The font file can be any OpenType font, though B<cmap2enc> is probably only -useful for the TrueType-flavored variant (PostScript-flavored ones always -contain glyph names in the `CFF' table). - -=item I<encoding> - -The encoding files read and written by B<cmap2enc> are in standard F<dvips> -format. The name of the output encoding file is -C<< <encoding>-<suffix>-<font>.enc >>, - -where - -=over 10 - -=item B<encoding> - -is the name of the input encoding file (without the extension `.enc'); - -=item B<suffix> - -names the OpenType features you specified: - -=over 10 - -=item I<tlf> - -for tabular lining figures (when neither the `onum' nor the `pnum' features -have been chosen) - -=item I<lf> - -for proportional width lining figures (when you've specified `pnum', -but not `onum') - -=item I<tosf> - -for tabular oldstyle figures (when you've specified `onum', but not `pnum') - -=item I<osf> - -for proportional width oldstyle figures (when both `onum' and `pnum' have been -chosen) - -=item I<sc> - -for small caps (`smcp' feature) - -=item I<swash> - -for swash (`swsh' feature) - -=item I<titling> - -for a titling font (`titl' feature) - -=item I<sup> - -for superior figures and (some) letters (`sups' feature) - -=item I<orn> - -for ornaments (`ornm' feature) - -=back - -When several features have been specified, the B<suffix> is a combination -of the appropriate items; e.g., when you specify -f onum,pnum,swsh (for a -swash font with proportional oldstyle figures) the B<suffix> is -C<osf-swash>. - -=item B<font> - -is the name of the input font file, without the `.ttf' or `.otf' extension. - -=back - -=item I<mtx> - -The output F<mtx> file is in standard F<fontinst> format. The name of this file -is C<< reset<font>-<encoding>-<suffix>.mtx >>, - -where I<font>, I<encoding> and I<suffix> have the same meaning as above. - -=item I<extra> - -The option B<-x> can be used to name a file containing extra substitutions -that complement or override the ones specified by the selected features. -It consists of one substitution per line; each is either of the form -C<< <from>;<to> >>, where I<from> and I<to> are both glyph indices -(specified as four hexadecimal digits), or of the form -C<< <glyph name>;<glyph index> >>, where I<glyph name> is any glyph name -and I<glyph index> the glyph index (again, four hex digits) that is to be -mapped to the specified glyph name. The F<examples/> subdirectory in the -I<fontools> distribution contains some examples of user-defined -substitution files. - - -=back - -=head1 CAVEATS - -=over 2 - -=item B<-> - -Most OpenType fonts contain several tables in the `cmap' table, -for different platforms and different encodings. -B<cmap2enc> only reads the first table that implements Unicode, that is, -the first table with either platformID = 0 and encodingID = 3 or 4 -or platformID = 3 and encodingID = 1 or 10. -At least one of those will probably always be present, and (afaik) it doesn't -matter which of these is used. - -The fact that only tableFormat = 4 is supported might be more of a restriction, -though I haven't yet found any font that used a different tableFormat. - -=item B<-> - -OpenType fonts implement features using so-called `Lookup Tables'. -B<cmap2enc> supports only features from the `GSUB' table that have -LookupType = 1 (single substitution). - -Some features are implemented as a combination of lookups from both -the `GSUB' and the `GPOS' tables; these features are (currently?) -not supported. An example of this are the `sinf' (Scientific Inferiors) and -'subs' (Subscripts) features of Linotype Palatino; these are implemented -by first replacing the standard numerals with smaller ones and then -adjusting their position. - -=item B<-> - -Some of the font's features may yield surprising results. E.g., Linotype -Palatino doesn't have small-caps forms of dotlessi, germandbls and the -standard f-ligatures, so it will give you the lowercase forms of these glyphs -even when the `smcp' feature is specified. -(The F<examples/palatinox> subdirectory contains a file F<unsetSCaps.mtx> -that deletes these lowercase forms; F<fontinst>'s F<newlatin.mtx> file -will then create fake small-caps forms of these glyphs.) - -=item B<-> - -If the user-defined substitution file substitutes glyph1 with glyph2, -B<cmap2enc> will also substitute glyph2 with glyph2; this may seem silly, -but it means that any selected feature that would substitute glyph2 with glyph3 -gets overridden. - -=item B<-> - -The glyph names are independent of the features selected, e.g., when using -features like `smcp' or `onum', glyph names still come out as `a' and `zero' -rather than `Asmall' and `zerooldstyle'. When installing the font with -F<fontinst>, you should therefore always use F<t1.etx> rather than F<t1c.etx> -or F<t1j.etx>. - -=back - - -=head1 SEE ALSO - -The other programs in the I<fontools> bundle: F<afm2afm>, F<autoinst>, -F<font2afm>, F<ot2kpx>, F<pfm2kpx>, F<showglyphs>. - -A good free (as in beer) Perl-implementation for Windows (and Linux) -is ActivePerl, available from F<http://www.activestate.com>. - - -=head1 AUTHOR - -Marc Penninga <marc@penninga.info> - -If you're sending a bug report, please give as much information as possible. -Also be sure to mention the name I<fontools> somewhere in the subject line, -or risk being caught by my spam filter. - - -=head1 COPYRIGHT - -Copyright (c) 2005, 2006 Marc Penninga. - - -=head1 LICENSE - -This program is free software; you can redistribute it and/or modify -it under the terms of version 2 of the GNU General Public License -as published by the Free Software Foundation. - -A copy of the GNU General Public License is included with the I<fontools> -collection; see the file F<GPLv2.txt>. - - -=head1 DISCLAIMER - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - - -=head1 HISTORY - -=over 12 - -=item I<2006-01-17> - -Changed the names of the generated output files; extended the documentation. - -=item I<2005-08-01> - -Removed some warning messages that didn't convey any useful information; -added contents of F<glyphlist.txt> to the program itself and removed -the file from the F<fontools> collection; -expanded the example in the documentation - -=item I<2005-04-29> - -Improved the documentation - -=item I<2005-03-21> - -Fixed somed bugs; added `titl' feature - -=item I<2005-03-15> - -Input files searched using B<kpsewhich> or B<findtexmf> - -=item I<2005-03-08> - -Input files searched via B<kpsewhich> (where available) - -=item I<2005-02-18> - -Rewrote some of the code, fixed a few bugs - -=item I<2005-01-10> - -First version - -=back - -=cut - - - -# Contents: The Adobe Glyph List, followed by extensions for TeX fonts and -# encodings. We also extend the second field so that it can contain -# multiple Unicode scalar values, separated by semicolons, analogous to -# otftotfm's "% UNICODING" comments. -############################################################################### -# Name: Adobe Glyph List -# Table version: 2.0 -# Date: September 20, 2002 -# -# See http://partners.adobe.com/asn/developer/typeforum/unicodegn.html -# -# Format: Semicolon-delimited fields: -# (1) glyph name -# (2) Unicode scalar value -A;0041 -AE;00C6 -AEacute;01FC -AEmacron;01E2 -AEsmall;F7E6 -Aacute;00C1 -Aacutesmall;F7E1 -Abreve;0102 -Abreveacute;1EAE -Abrevecyrillic;04D0 -Abrevedotbelow;1EB6 -Abrevegrave;1EB0 -Abrevehookabove;1EB2 -Abrevetilde;1EB4 -Acaron;01CD -Acircle;24B6 -Acircumflex;00C2 -Acircumflexacute;1EA4 -Acircumflexdotbelow;1EAC -Acircumflexgrave;1EA6 -Acircumflexhookabove;1EA8 -Acircumflexsmall;F7E2 -Acircumflextilde;1EAA -Acute;F6C9 -Acutesmall;F7B4 -Acyrillic;0410 -Adblgrave;0200 -Adieresis;00C4 -Adieresiscyrillic;04D2 -Adieresismacron;01DE -Adieresissmall;F7E4 -Adotbelow;1EA0 -Adotmacron;01E0 -Agrave;00C0 -Agravesmall;F7E0 -Ahookabove;1EA2 -Aiecyrillic;04D4 -Ainvertedbreve;0202 -Alpha;0391 -Alphatonos;0386 -Amacron;0100 -Amonospace;FF21 -Aogonek;0104 -Aring;00C5 -Aringacute;01FA -Aringbelow;1E00 -Aringsmall;F7E5 -Asmall;F761 -Atilde;00C3 -Atildesmall;F7E3 -Aybarmenian;0531 -B;0042 -Bcircle;24B7 -Bdotaccent;1E02 -Bdotbelow;1E04 -Becyrillic;0411 -Benarmenian;0532 -Beta;0392 -Bhook;0181 -Blinebelow;1E06 -Bmonospace;FF22 -Brevesmall;F6F4 -Bsmall;F762 -Btopbar;0182 -C;0043 -Caarmenian;053E -Cacute;0106 -Caron;F6CA -Caronsmall;F6F5 -Ccaron;010C -Ccedilla;00C7 -Ccedillaacute;1E08 -Ccedillasmall;F7E7 -Ccircle;24B8 -Ccircumflex;0108 -Cdot;010A -Cdotaccent;010A -Cedillasmall;F7B8 -Chaarmenian;0549 -Cheabkhasiancyrillic;04BC -Checyrillic;0427 -Chedescenderabkhasiancyrillic;04BE -Chedescendercyrillic;04B6 -Chedieresiscyrillic;04F4 -Cheharmenian;0543 -Chekhakassiancyrillic;04CB -Cheverticalstrokecyrillic;04B8 -Chi;03A7 -Chook;0187 -Circumflexsmall;F6F6 -Cmonospace;FF23 -Coarmenian;0551 -Csmall;F763 -D;0044 -DZ;01F1 -DZcaron;01C4 -Daarmenian;0534 -Dafrican;0189 -Dcaron;010E -Dcedilla;1E10 -Dcircle;24B9 -Dcircumflexbelow;1E12 -Dcroat;0110 -Ddotaccent;1E0A -Ddotbelow;1E0C -Decyrillic;0414 -Deicoptic;03EE -Delta;2206 -Deltagreek;0394 -Dhook;018A -Dieresis;F6CB -DieresisAcute;F6CC -DieresisGrave;F6CD -Dieresissmall;F7A8 -Digammagreek;03DC -Djecyrillic;0402 -Dlinebelow;1E0E -Dmonospace;FF24 -Dotaccentsmall;F6F7 -Dslash;0110 -Dsmall;F764 -Dtopbar;018B -Dz;01F2 -Dzcaron;01C5 -Dzeabkhasiancyrillic;04E0 -Dzecyrillic;0405 -Dzhecyrillic;040F -E;0045 -Eacute;00C9 -Eacutesmall;F7E9 -Ebreve;0114 -Ecaron;011A -Ecedillabreve;1E1C -Echarmenian;0535 -Ecircle;24BA -Ecircumflex;00CA -Ecircumflexacute;1EBE -Ecircumflexbelow;1E18 -Ecircumflexdotbelow;1EC6 -Ecircumflexgrave;1EC0 -Ecircumflexhookabove;1EC2 -Ecircumflexsmall;F7EA -Ecircumflextilde;1EC4 -Ecyrillic;0404 -Edblgrave;0204 -Edieresis;00CB -Edieresissmall;F7EB -Edot;0116 -Edotaccent;0116 -Edotbelow;1EB8 -Efcyrillic;0424 -Egrave;00C8 -Egravesmall;F7E8 -Eharmenian;0537 -Ehookabove;1EBA -Eightroman;2167 -Einvertedbreve;0206 -Eiotifiedcyrillic;0464 -Elcyrillic;041B -Elevenroman;216A -Emacron;0112 -Emacronacute;1E16 -Emacrongrave;1E14 -Emcyrillic;041C -Emonospace;FF25 -Encyrillic;041D -Endescendercyrillic;04A2 -Eng;014A -Enghecyrillic;04A4 -Enhookcyrillic;04C7 -Eogonek;0118 -Eopen;0190 -Epsilon;0395 -Epsilontonos;0388 -Ercyrillic;0420 -Ereversed;018E -Ereversedcyrillic;042D -Escyrillic;0421 -Esdescendercyrillic;04AA -Esh;01A9 -Esmall;F765 -Eta;0397 -Etarmenian;0538 -Etatonos;0389 -Eth;00D0 -Ethsmall;F7F0 -Etilde;1EBC -Etildebelow;1E1A -Euro;20AC -Ezh;01B7 -Ezhcaron;01EE -Ezhreversed;01B8 -F;0046 -Fcircle;24BB -Fdotaccent;1E1E -Feharmenian;0556 -Feicoptic;03E4 -Fhook;0191 -Fitacyrillic;0472 -Fiveroman;2164 -Fmonospace;FF26 -Fourroman;2163 -Fsmall;F766 -G;0047 -GBsquare;3387 -Gacute;01F4 -Gamma;0393 -Gammaafrican;0194 -Gangiacoptic;03EA -Gbreve;011E -Gcaron;01E6 -Gcedilla;0122 -Gcircle;24BC -Gcircumflex;011C -Gcommaaccent;0122 -Gdot;0120 -Gdotaccent;0120 -Gecyrillic;0413 -Ghadarmenian;0542 -Ghemiddlehookcyrillic;0494 -Ghestrokecyrillic;0492 -Gheupturncyrillic;0490 -Ghook;0193 -Gimarmenian;0533 -Gjecyrillic;0403 -Gmacron;1E20 -Gmonospace;FF27 -Grave;F6CE -Gravesmall;F760 -Gsmall;F767 -Gsmallhook;029B -Gstroke;01E4 -H;0048 -H18533;25CF -H18543;25AA -H18551;25AB -H22073;25A1 -HPsquare;33CB -Haabkhasiancyrillic;04A8 -Hadescendercyrillic;04B2 -Hardsigncyrillic;042A -Hbar;0126 -Hbrevebelow;1E2A -Hcedilla;1E28 -Hcircle;24BD -Hcircumflex;0124 -Hdieresis;1E26 -Hdotaccent;1E22 -Hdotbelow;1E24 -Hmonospace;FF28 -Hoarmenian;0540 -Horicoptic;03E8 -Hsmall;F768 -Hungarumlaut;F6CF -Hungarumlautsmall;F6F8 -Hzsquare;3390 -I;0049 -IAcyrillic;042F -IJ;0132 -IUcyrillic;042E -Iacute;00CD -Iacutesmall;F7ED -Ibreve;012C -Icaron;01CF -Icircle;24BE -Icircumflex;00CE -Icircumflexsmall;F7EE -Icyrillic;0406 -Idblgrave;0208 -Idieresis;00CF -Idieresisacute;1E2E -Idieresiscyrillic;04E4 -Idieresissmall;F7EF -Idot;0130 -Idotaccent;0130 -Idotbelow;1ECA -Iebrevecyrillic;04D6 -Iecyrillic;0415 -Ifraktur;2111 -Igrave;00CC -Igravesmall;F7EC -Ihookabove;1EC8 -Iicyrillic;0418 -Iinvertedbreve;020A -Iishortcyrillic;0419 -Imacron;012A -Imacroncyrillic;04E2 -Imonospace;FF29 -Iniarmenian;053B -Iocyrillic;0401 -Iogonek;012E -Iota;0399 -Iotaafrican;0196 -Iotadieresis;03AA -Iotatonos;038A -Ismall;F769 -Istroke;0197 -Itilde;0128 -Itildebelow;1E2C -Izhitsacyrillic;0474 -Izhitsadblgravecyrillic;0476 -J;004A -Jaarmenian;0541 -Jcircle;24BF -Jcircumflex;0134 -Jecyrillic;0408 -Jheharmenian;054B -Jmonospace;FF2A -Jsmall;F76A -K;004B -KBsquare;3385 -KKsquare;33CD -Kabashkircyrillic;04A0 -Kacute;1E30 -Kacyrillic;041A -Kadescendercyrillic;049A -Kahookcyrillic;04C3 -Kappa;039A -Kastrokecyrillic;049E -Kaverticalstrokecyrillic;049C -Kcaron;01E8 -Kcedilla;0136 -Kcircle;24C0 -Kcommaaccent;0136 -Kdotbelow;1E32 -Keharmenian;0554 -Kenarmenian;053F -Khacyrillic;0425 -Kheicoptic;03E6 -Khook;0198 -Kjecyrillic;040C -Klinebelow;1E34 -Kmonospace;FF2B -Koppacyrillic;0480 -Koppagreek;03DE -Ksicyrillic;046E -Ksmall;F76B -L;004C -LJ;01C7 -LL;F6BF -Lacute;0139 -Lambda;039B -Lcaron;013D -Lcedilla;013B -Lcircle;24C1 -Lcircumflexbelow;1E3C -Lcommaaccent;013B -Ldot;013F -Ldotaccent;013F -Ldotbelow;1E36 -Ldotbelowmacron;1E38 -Liwnarmenian;053C -Lj;01C8 -Ljecyrillic;0409 -Llinebelow;1E3A -Lmonospace;FF2C -Lslash;0141 -Lslashsmall;F6F9 -Lsmall;F76C -M;004D -MBsquare;3386 -Macron;F6D0 -Macronsmall;F7AF -Macute;1E3E -Mcircle;24C2 -Mdotaccent;1E40 -Mdotbelow;1E42 -Menarmenian;0544 -Mmonospace;FF2D -Msmall;F76D -Mturned;019C -Mu;039C -N;004E -NJ;01CA -Nacute;0143 -Ncaron;0147 -Ncedilla;0145 -Ncircle;24C3 -Ncircumflexbelow;1E4A -Ncommaaccent;0145 -Ndotaccent;1E44 -Ndotbelow;1E46 -Nhookleft;019D -Nineroman;2168 -Nj;01CB -Njecyrillic;040A -Nlinebelow;1E48 -Nmonospace;FF2E -Nowarmenian;0546 -Nsmall;F76E -Ntilde;00D1 -Ntildesmall;F7F1 -Nu;039D -O;004F -OE;0152 -OEsmall;F6FA -Oacute;00D3 -Oacutesmall;F7F3 -Obarredcyrillic;04E8 -Obarreddieresiscyrillic;04EA -Obreve;014E -Ocaron;01D1 -Ocenteredtilde;019F -Ocircle;24C4 -Ocircumflex;00D4 -Ocircumflexacute;1ED0 -Ocircumflexdotbelow;1ED8 -Ocircumflexgrave;1ED2 -Ocircumflexhookabove;1ED4 -Ocircumflexsmall;F7F4 -Ocircumflextilde;1ED6 -Ocyrillic;041E -Odblacute;0150 -Odblgrave;020C -Odieresis;00D6 -Odieresiscyrillic;04E6 -Odieresissmall;F7F6 -Odotbelow;1ECC -Ogoneksmall;F6FB -Ograve;00D2 -Ogravesmall;F7F2 -Oharmenian;0555 -Ohm;2126 -Ohookabove;1ECE -Ohorn;01A0 -Ohornacute;1EDA -Ohorndotbelow;1EE2 -Ohorngrave;1EDC -Ohornhookabove;1EDE -Ohorntilde;1EE0 -Ohungarumlaut;0150 -Oi;01A2 -Oinvertedbreve;020E -Omacron;014C -Omacronacute;1E52 -Omacrongrave;1E50 -Omega;2126 -Omegacyrillic;0460 -Omegagreek;03A9 -Omegaroundcyrillic;047A -Omegatitlocyrillic;047C -Omegatonos;038F -Omicron;039F -Omicrontonos;038C -Omonospace;FF2F -Oneroman;2160 -Oogonek;01EA -Oogonekmacron;01EC -Oopen;0186 -Oslash;00D8 -Oslashacute;01FE -Oslashsmall;F7F8 -Osmall;F76F -Ostrokeacute;01FE -Otcyrillic;047E -Otilde;00D5 -Otildeacute;1E4C -Otildedieresis;1E4E -Otildesmall;F7F5 -P;0050 -Pacute;1E54 -Pcircle;24C5 -Pdotaccent;1E56 -Pecyrillic;041F -Peharmenian;054A -Pemiddlehookcyrillic;04A6 -Phi;03A6 -Phook;01A4 -Pi;03A0 -Piwrarmenian;0553 -Pmonospace;FF30 -Psi;03A8 -Psicyrillic;0470 -Psmall;F770 -Q;0051 -Qcircle;24C6 -Qmonospace;FF31 -Qsmall;F771 -R;0052 -Raarmenian;054C -Racute;0154 -Rcaron;0158 -Rcedilla;0156 -Rcircle;24C7 -Rcommaaccent;0156 -Rdblgrave;0210 -Rdotaccent;1E58 -Rdotbelow;1E5A -Rdotbelowmacron;1E5C -Reharmenian;0550 -Rfraktur;211C -Rho;03A1 -Ringsmall;F6FC -Rinvertedbreve;0212 -Rlinebelow;1E5E -Rmonospace;FF32 -Rsmall;F772 -Rsmallinverted;0281 -Rsmallinvertedsuperior;02B6 -S;0053 -SF010000;250C -SF020000;2514 -SF030000;2510 -SF040000;2518 -SF050000;253C -SF060000;252C -SF070000;2534 -SF080000;251C -SF090000;2524 -SF100000;2500 -SF110000;2502 -SF190000;2561 -SF200000;2562 -SF210000;2556 -SF220000;2555 -SF230000;2563 -SF240000;2551 -SF250000;2557 -SF260000;255D -SF270000;255C -SF280000;255B -SF360000;255E -SF370000;255F -SF380000;255A -SF390000;2554 -SF400000;2569 -SF410000;2566 -SF420000;2560 -SF430000;2550 -SF440000;256C -SF450000;2567 -SF460000;2568 -SF470000;2564 -SF480000;2565 -SF490000;2559 -SF500000;2558 -SF510000;2552 -SF520000;2553 -SF530000;256B -SF540000;256A -Sacute;015A -Sacutedotaccent;1E64 -Sampigreek;03E0 -Scaron;0160 -Scarondotaccent;1E66 -Scaronsmall;F6FD -Scedilla;015E -Schwa;018F -Schwacyrillic;04D8 -Schwadieresiscyrillic;04DA -Scircle;24C8 -Scircumflex;015C -Scommaaccent;0218 -Sdotaccent;1E60 -Sdotbelow;1E62 -Sdotbelowdotaccent;1E68 -Seharmenian;054D -Sevenroman;2166 -Shaarmenian;0547 -Shacyrillic;0428 -Shchacyrillic;0429 -Sheicoptic;03E2 -Shhacyrillic;04BA -Shimacoptic;03EC -Sigma;03A3 -Sixroman;2165 -Smonospace;FF33 -Softsigncyrillic;042C -Ssmall;F773 -Stigmagreek;03DA -T;0054 -Tau;03A4 -Tbar;0166 -Tcaron;0164 -Tcedilla;0162 -Tcircle;24C9 -Tcircumflexbelow;1E70 -Tcommaaccent;0162 -Tdotaccent;1E6A -Tdotbelow;1E6C -Tecyrillic;0422 -Tedescendercyrillic;04AC -Tenroman;2169 -Tetsecyrillic;04B4 -Theta;0398 -Thook;01AC -Thorn;00DE -Thornsmall;F7FE -Threeroman;2162 -Tildesmall;F6FE -Tiwnarmenian;054F -Tlinebelow;1E6E -Tmonospace;FF34 -Toarmenian;0539 -Tonefive;01BC -Tonesix;0184 -Tonetwo;01A7 -Tretroflexhook;01AE -Tsecyrillic;0426 -Tshecyrillic;040B -Tsmall;F774 -Twelveroman;216B -Tworoman;2161 -U;0055 -Uacute;00DA -Uacutesmall;F7FA -Ubreve;016C -Ucaron;01D3 -Ucircle;24CA -Ucircumflex;00DB -Ucircumflexbelow;1E76 -Ucircumflexsmall;F7FB -Ucyrillic;0423 -Udblacute;0170 -Udblgrave;0214 -Udieresis;00DC -Udieresisacute;01D7 -Udieresisbelow;1E72 -Udieresiscaron;01D9 -Udieresiscyrillic;04F0 -Udieresisgrave;01DB -Udieresismacron;01D5 -Udieresissmall;F7FC -Udotbelow;1EE4 -Ugrave;00D9 -Ugravesmall;F7F9 -Uhookabove;1EE6 -Uhorn;01AF -Uhornacute;1EE8 -Uhorndotbelow;1EF0 -Uhorngrave;1EEA -Uhornhookabove;1EEC -Uhorntilde;1EEE -Uhungarumlaut;0170 -Uhungarumlautcyrillic;04F2 -Uinvertedbreve;0216 -Ukcyrillic;0478 -Umacron;016A -Umacroncyrillic;04EE -Umacrondieresis;1E7A -Umonospace;FF35 -Uogonek;0172 -Upsilon;03A5 -Upsilon1;03D2 -Upsilonacutehooksymbolgreek;03D3 -Upsilonafrican;01B1 -Upsilondieresis;03AB -Upsilondieresishooksymbolgreek;03D4 -Upsilonhooksymbol;03D2 -Upsilontonos;038E -Uring;016E -Ushortcyrillic;040E -Usmall;F775 -Ustraightcyrillic;04AE -Ustraightstrokecyrillic;04B0 -Utilde;0168 -Utildeacute;1E78 -Utildebelow;1E74 -V;0056 -Vcircle;24CB -Vdotbelow;1E7E -Vecyrillic;0412 -Vewarmenian;054E -Vhook;01B2 -Vmonospace;FF36 -Voarmenian;0548 -Vsmall;F776 -Vtilde;1E7C -W;0057 -Wacute;1E82 -Wcircle;24CC -Wcircumflex;0174 -Wdieresis;1E84 -Wdotaccent;1E86 -Wdotbelow;1E88 -Wgrave;1E80 -Wmonospace;FF37 -Wsmall;F777 -X;0058 -Xcircle;24CD -Xdieresis;1E8C -Xdotaccent;1E8A -Xeharmenian;053D -Xi;039E -Xmonospace;FF38 -Xsmall;F778 -Y;0059 -Yacute;00DD -Yacutesmall;F7FD -Yatcyrillic;0462 -Ycircle;24CE -Ycircumflex;0176 -Ydieresis;0178 -Ydieresissmall;F7FF -Ydotaccent;1E8E -Ydotbelow;1EF4 -Yericyrillic;042B -Yerudieresiscyrillic;04F8 -Ygrave;1EF2 -Yhook;01B3 -Yhookabove;1EF6 -Yiarmenian;0545 -Yicyrillic;0407 -Yiwnarmenian;0552 -Ymonospace;FF39 -Ysmall;F779 -Ytilde;1EF8 -Yusbigcyrillic;046A -Yusbigiotifiedcyrillic;046C -Yuslittlecyrillic;0466 -Yuslittleiotifiedcyrillic;0468 -Z;005A -Zaarmenian;0536 -Zacute;0179 -Zcaron;017D -Zcaronsmall;F6FF -Zcircle;24CF -Zcircumflex;1E90 -Zdot;017B -Zdotaccent;017B -Zdotbelow;1E92 -Zecyrillic;0417 -Zedescendercyrillic;0498 -Zedieresiscyrillic;04DE -Zeta;0396 -Zhearmenian;053A -Zhebrevecyrillic;04C1 -Zhecyrillic;0416 -Zhedescendercyrillic;0496 -Zhedieresiscyrillic;04DC -Zlinebelow;1E94 -Zmonospace;FF3A -Zsmall;F77A -Zstroke;01B5 -a;0061 -aabengali;0986 -aacute;00E1 -aadeva;0906 -aagujarati;0A86 -aagurmukhi;0A06 -aamatragurmukhi;0A3E -aarusquare;3303 -aavowelsignbengali;09BE -aavowelsigndeva;093E -aavowelsigngujarati;0ABE -abbreviationmarkarmenian;055F -abbreviationsigndeva;0970 -abengali;0985 -abopomofo;311A -abreve;0103 -abreveacute;1EAF -abrevecyrillic;04D1 -abrevedotbelow;1EB7 -abrevegrave;1EB1 -abrevehookabove;1EB3 -abrevetilde;1EB5 -acaron;01CE -acircle;24D0 -acircumflex;00E2 -acircumflexacute;1EA5 -acircumflexdotbelow;1EAD -acircumflexgrave;1EA7 -acircumflexhookabove;1EA9 -acircumflextilde;1EAB -acute;00B4 -acutebelowcmb;0317 -acutecmb;0301 -acutecomb;0301 -acutedeva;0954 -acutelowmod;02CF -acutetonecmb;0341 -acyrillic;0430 -adblgrave;0201 -addakgurmukhi;0A71 -adeva;0905 -adieresis;00E4 -adieresiscyrillic;04D3 -adieresismacron;01DF -adotbelow;1EA1 -adotmacron;01E1 -ae;00E6 -aeacute;01FD -aekorean;3150 -aemacron;01E3 -afii00208;2015 -afii08941;20A4 -afii10017;0410 -afii10018;0411 -afii10019;0412 -afii10020;0413 -afii10021;0414 -afii10022;0415 -afii10023;0401 -afii10024;0416 -afii10025;0417 -afii10026;0418 -afii10027;0419 -afii10028;041A -afii10029;041B -afii10030;041C -afii10031;041D -afii10032;041E -afii10033;041F -afii10034;0420 -afii10035;0421 -afii10036;0422 -afii10037;0423 -afii10038;0424 -afii10039;0425 -afii10040;0426 -afii10041;0427 -afii10042;0428 -afii10043;0429 -afii10044;042A -afii10045;042B -afii10046;042C -afii10047;042D -afii10048;042E -afii10049;042F -afii10050;0490 -afii10051;0402 -afii10052;0403 -afii10053;0404 -afii10054;0405 -afii10055;0406 -afii10056;0407 -afii10057;0408 -afii10058;0409 -afii10059;040A -afii10060;040B -afii10061;040C -afii10062;040E -afii10063;F6C4 -afii10064;F6C5 -afii10065;0430 -afii10066;0431 -afii10067;0432 -afii10068;0433 -afii10069;0434 -afii10070;0435 -afii10071;0451 -afii10072;0436 -afii10073;0437 -afii10074;0438 -afii10075;0439 -afii10076;043A -afii10077;043B -afii10078;043C -afii10079;043D -afii10080;043E -afii10081;043F -afii10082;0440 -afii10083;0441 -afii10084;0442 -afii10085;0443 -afii10086;0444 -afii10087;0445 -afii10088;0446 -afii10089;0447 -afii10090;0448 -afii10091;0449 -afii10092;044A -afii10093;044B -afii10094;044C -afii10095;044D -afii10096;044E -afii10097;044F -afii10098;0491 -afii10099;0452 -afii10100;0453 -afii10101;0454 -afii10102;0455 -afii10103;0456 -afii10104;0457 -afii10105;0458 -afii10106;0459 -afii10107;045A -afii10108;045B -afii10109;045C -afii10110;045E -afii10145;040F -afii10146;0462 -afii10147;0472 -afii10148;0474 -afii10192;F6C6 -afii10193;045F -afii10194;0463 -afii10195;0473 -afii10196;0475 -afii10831;F6C7 -afii10832;F6C8 -afii10846;04D9 -afii299;200E -afii300;200F -afii301;200D -afii57381;066A -afii57388;060C -afii57392;0660 -afii57393;0661 -afii57394;0662 -afii57395;0663 -afii57396;0664 -afii57397;0665 -afii57398;0666 -afii57399;0667 -afii57400;0668 -afii57401;0669 -afii57403;061B -afii57407;061F -afii57409;0621 -afii57410;0622 -afii57411;0623 -afii57412;0624 -afii57413;0625 -afii57414;0626 -afii57415;0627 -afii57416;0628 -afii57417;0629 -afii57418;062A -afii57419;062B -afii57420;062C -afii57421;062D -afii57422;062E -afii57423;062F -afii57424;0630 -afii57425;0631 -afii57426;0632 -afii57427;0633 -afii57428;0634 -afii57429;0635 -afii57430;0636 -afii57431;0637 -afii57432;0638 -afii57433;0639 -afii57434;063A -afii57440;0640 -afii57441;0641 -afii57442;0642 -afii57443;0643 -afii57444;0644 -afii57445;0645 -afii57446;0646 -afii57448;0648 -afii57449;0649 -afii57450;064A -afii57451;064B -afii57452;064C -afii57453;064D -afii57454;064E -afii57455;064F -afii57456;0650 -afii57457;0651 -afii57458;0652 -afii57470;0647 -afii57505;06A4 -afii57506;067E -afii57507;0686 -afii57508;0698 -afii57509;06AF -afii57511;0679 -afii57512;0688 -afii57513;0691 -afii57514;06BA -afii57519;06D2 -afii57534;06D5 -afii57636;20AA -afii57645;05BE -afii57658;05C3 -afii57664;05D0 -afii57665;05D1 -afii57666;05D2 -afii57667;05D3 -afii57668;05D4 -afii57669;05D5 -afii57670;05D6 -afii57671;05D7 -afii57672;05D8 -afii57673;05D9 -afii57674;05DA -afii57675;05DB -afii57676;05DC -afii57677;05DD -afii57678;05DE -afii57679;05DF -afii57680;05E0 -afii57681;05E1 -afii57682;05E2 -afii57683;05E3 -afii57684;05E4 -afii57685;05E5 -afii57686;05E6 -afii57687;05E7 -afii57688;05E8 -afii57689;05E9 -afii57690;05EA -afii57694;FB2A -afii57695;FB2B -afii57700;FB4B -afii57705;FB1F -afii57716;05F0 -afii57717;05F1 -afii57718;05F2 -afii57723;FB35 -afii57793;05B4 -afii57794;05B5 -afii57795;05B6 -afii57796;05BB -afii57797;05B8 -afii57798;05B7 -afii57799;05B0 -afii57800;05B2 -afii57801;05B1 -afii57802;05B3 -afii57803;05C2 -afii57804;05C1 -afii57806;05B9 -afii57807;05BC -afii57839;05BD -afii57841;05BF -afii57842;05C0 -afii57929;02BC -afii61248;2105 -afii61289;2113 -afii61352;2116 -afii61573;202C -afii61574;202D -afii61575;202E -afii61664;200C -afii63167;066D -afii64937;02BD -agrave;00E0 -agujarati;0A85 -agurmukhi;0A05 -ahiragana;3042 -ahookabove;1EA3 -aibengali;0990 -aibopomofo;311E -aideva;0910 -aiecyrillic;04D5 -aigujarati;0A90 -aigurmukhi;0A10 -aimatragurmukhi;0A48 -ainarabic;0639 -ainfinalarabic;FECA -aininitialarabic;FECB -ainmedialarabic;FECC -ainvertedbreve;0203 -aivowelsignbengali;09C8 -aivowelsigndeva;0948 -aivowelsigngujarati;0AC8 -akatakana;30A2 -akatakanahalfwidth;FF71 -akorean;314F -alef;05D0 -alefarabic;0627 -alefdageshhebrew;FB30 -aleffinalarabic;FE8E -alefhamzaabovearabic;0623 -alefhamzaabovefinalarabic;FE84 -alefhamzabelowarabic;0625 -alefhamzabelowfinalarabic;FE88 -alefhebrew;05D0 -aleflamedhebrew;FB4F -alefmaddaabovearabic;0622 -alefmaddaabovefinalarabic;FE82 -alefmaksuraarabic;0649 -alefmaksurafinalarabic;FEF0 -alefmaksurainitialarabic;FEF3 -alefmaksuramedialarabic;FEF4 -alefpatahhebrew;FB2E -alefqamatshebrew;FB2F -aleph;2135 -allequal;224C -alpha;03B1 -alphatonos;03AC -amacron;0101 -amonospace;FF41 -ampersand;0026 -ampersandmonospace;FF06 -ampersandsmall;F726 -amsquare;33C2 -anbopomofo;3122 -angbopomofo;3124 -angkhankhuthai;0E5A -angle;2220 -anglebracketleft;3008 -anglebracketleftvertical;FE3F -anglebracketright;3009 -anglebracketrightvertical;FE40 -angleleft;2329 -angleright;232A -angstrom;212B -anoteleia;0387 -anudattadeva;0952 -anusvarabengali;0982 -anusvaradeva;0902 -anusvaragujarati;0A82 -aogonek;0105 -apaatosquare;3300 -aparen;249C -apostrophearmenian;055A -apostrophemod;02BC -apple;F8FF -approaches;2250 -approxequal;2248 -approxequalorimage;2252 -approximatelyequal;2245 -araeaekorean;318E -araeakorean;318D -arc;2312 -arighthalfring;1E9A -aring;00E5 -aringacute;01FB -aringbelow;1E01 -arrowboth;2194 -arrowdashdown;21E3 -arrowdashleft;21E0 -arrowdashright;21E2 -arrowdashup;21E1 -arrowdblboth;21D4 -arrowdbldown;21D3 -arrowdblleft;21D0 -arrowdblright;21D2 -arrowdblup;21D1 -arrowdown;2193 -arrowdownleft;2199 -arrowdownright;2198 -arrowdownwhite;21E9 -arrowheaddownmod;02C5 -arrowheadleftmod;02C2 -arrowheadrightmod;02C3 -arrowheadupmod;02C4 -arrowhorizex;F8E7 -arrowleft;2190 -arrowleftdbl;21D0 -arrowleftdblstroke;21CD -arrowleftoverright;21C6 -arrowleftwhite;21E6 -arrowright;2192 -arrowrightdblstroke;21CF -arrowrightheavy;279E -arrowrightoverleft;21C4 -arrowrightwhite;21E8 -arrowtableft;21E4 -arrowtabright;21E5 -arrowup;2191 -arrowupdn;2195 -arrowupdnbse;21A8 -arrowupdownbase;21A8 -arrowupleft;2196 -arrowupleftofdown;21C5 -arrowupright;2197 -arrowupwhite;21E7 -arrowvertex;F8E6 -asciicircum;005E -asciicircummonospace;FF3E -asciitilde;007E -asciitildemonospace;FF5E -ascript;0251 -ascriptturned;0252 -asmallhiragana;3041 -asmallkatakana;30A1 -asmallkatakanahalfwidth;FF67 -asterisk;002A -asteriskaltonearabic;066D -asteriskarabic;066D -asteriskmath;2217 -asteriskmonospace;FF0A -asterisksmall;FE61 -asterism;2042 -asuperior;F6E9 -asymptoticallyequal;2243 -at;0040 -atilde;00E3 -atmonospace;FF20 -atsmall;FE6B -aturned;0250 -aubengali;0994 -aubopomofo;3120 -audeva;0914 -augujarati;0A94 -augurmukhi;0A14 -aulengthmarkbengali;09D7 -aumatragurmukhi;0A4C -auvowelsignbengali;09CC -auvowelsigndeva;094C -auvowelsigngujarati;0ACC -avagrahadeva;093D -aybarmenian;0561 -ayin;05E2 -ayinaltonehebrew;FB20 -ayinhebrew;05E2 -b;0062 -babengali;09AC -backslash;005C -backslashmonospace;FF3C -badeva;092C -bagujarati;0AAC -bagurmukhi;0A2C -bahiragana;3070 -bahtthai;0E3F -bakatakana;30D0 -bar;007C -barmonospace;FF5C -bbopomofo;3105 -bcircle;24D1 -bdotaccent;1E03 -bdotbelow;1E05 -beamedsixteenthnotes;266C -because;2235 -becyrillic;0431 -beharabic;0628 -behfinalarabic;FE90 -behinitialarabic;FE91 -behiragana;3079 -behmedialarabic;FE92 -behmeeminitialarabic;FC9F -behmeemisolatedarabic;FC08 -behnoonfinalarabic;FC6D -bekatakana;30D9 -benarmenian;0562 -bet;05D1 -beta;03B2 -betasymbolgreek;03D0 -betdagesh;FB31 -betdageshhebrew;FB31 -bethebrew;05D1 -betrafehebrew;FB4C -bhabengali;09AD -bhadeva;092D -bhagujarati;0AAD -bhagurmukhi;0A2D -bhook;0253 -bihiragana;3073 -bikatakana;30D3 -bilabialclick;0298 -bindigurmukhi;0A02 -birusquare;3331 -blackcircle;25CF -blackdiamond;25C6 -blackdownpointingtriangle;25BC -blackleftpointingpointer;25C4 -blackleftpointingtriangle;25C0 -blacklenticularbracketleft;3010 -blacklenticularbracketleftvertical;FE3B -blacklenticularbracketright;3011 -blacklenticularbracketrightvertical;FE3C -blacklowerlefttriangle;25E3 -blacklowerrighttriangle;25E2 -blackrectangle;25AC -blackrightpointingpointer;25BA -blackrightpointingtriangle;25B6 -blacksmallsquare;25AA -blacksmilingface;263B -blacksquare;25A0 -blackstar;2605 -blackupperlefttriangle;25E4 -blackupperrighttriangle;25E5 -blackuppointingsmalltriangle;25B4 -blackuppointingtriangle;25B2 -blank;2423 -blinebelow;1E07 -block;2588 -bmonospace;FF42 -bobaimaithai;0E1A -bohiragana;307C -bokatakana;30DC -bparen;249D -bqsquare;33C3 -braceex;F8F4 -braceleft;007B -braceleftbt;F8F3 -braceleftmid;F8F2 -braceleftmonospace;FF5B -braceleftsmall;FE5B -bracelefttp;F8F1 -braceleftvertical;FE37 -braceright;007D -bracerightbt;F8FE -bracerightmid;F8FD -bracerightmonospace;FF5D -bracerightsmall;FE5C -bracerighttp;F8FC -bracerightvertical;FE38 -bracketleft;005B -bracketleftbt;F8F0 -bracketleftex;F8EF -bracketleftmonospace;FF3B -bracketlefttp;F8EE -bracketright;005D -bracketrightbt;F8FB -bracketrightex;F8FA -bracketrightmonospace;FF3D -bracketrighttp;F8F9 -breve;02D8 -brevebelowcmb;032E -brevecmb;0306 -breveinvertedbelowcmb;032F -breveinvertedcmb;0311 -breveinverteddoublecmb;0361 -bridgebelowcmb;032A -bridgeinvertedbelowcmb;033A -brokenbar;00A6 -bstroke;0180 -bsuperior;F6EA -btopbar;0183 -buhiragana;3076 -bukatakana;30D6 -bullet;2022 -bulletinverse;25D8 -bulletoperator;2219 -bullseye;25CE -c;0063 -caarmenian;056E -cabengali;099A -cacute;0107 -cadeva;091A -cagujarati;0A9A -cagurmukhi;0A1A -calsquare;3388 -candrabindubengali;0981 -candrabinducmb;0310 -candrabindudeva;0901 -candrabindugujarati;0A81 -capslock;21EA -careof;2105 -caron;02C7 -caronbelowcmb;032C -caroncmb;030C -carriagereturn;21B5 -cbopomofo;3118 -ccaron;010D -ccedilla;00E7 -ccedillaacute;1E09 -ccircle;24D2 -ccircumflex;0109 -ccurl;0255 -cdot;010B -cdotaccent;010B -cdsquare;33C5 -cedilla;00B8 -cedillacmb;0327 -cent;00A2 -centigrade;2103 -centinferior;F6DF -centmonospace;FFE0 -centoldstyle;F7A2 -centsuperior;F6E0 -chaarmenian;0579 -chabengali;099B -chadeva;091B -chagujarati;0A9B -chagurmukhi;0A1B -chbopomofo;3114 -cheabkhasiancyrillic;04BD -checkmark;2713 -checyrillic;0447 -chedescenderabkhasiancyrillic;04BF -chedescendercyrillic;04B7 -chedieresiscyrillic;04F5 -cheharmenian;0573 -chekhakassiancyrillic;04CC -cheverticalstrokecyrillic;04B9 -chi;03C7 -chieuchacirclekorean;3277 -chieuchaparenkorean;3217 -chieuchcirclekorean;3269 -chieuchkorean;314A -chieuchparenkorean;3209 -chochangthai;0E0A -chochanthai;0E08 -chochingthai;0E09 -chochoethai;0E0C -chook;0188 -cieucacirclekorean;3276 -cieucaparenkorean;3216 -cieuccirclekorean;3268 -cieuckorean;3148 -cieucparenkorean;3208 -cieucuparenkorean;321C -circle;25CB -circlemultiply;2297 -circleot;2299 -circleplus;2295 -circlepostalmark;3036 -circlewithlefthalfblack;25D0 -circlewithrighthalfblack;25D1 -circumflex;02C6 -circumflexbelowcmb;032D -circumflexcmb;0302 -clear;2327 -clickalveolar;01C2 -clickdental;01C0 -clicklateral;01C1 -clickretroflex;01C3 -club;2663 -clubsuitblack;2663 -clubsuitwhite;2667 -cmcubedsquare;33A4 -cmonospace;FF43 -cmsquaredsquare;33A0 -coarmenian;0581 -colon;003A -colonmonetary;20A1 -colonmonospace;FF1A -colonsign;20A1 -colonsmall;FE55 -colontriangularhalfmod;02D1 -colontriangularmod;02D0 -comma;002C -commaabovecmb;0313 -commaaboverightcmb;0315 -commaaccent;F6C3 -commaarabic;060C -commaarmenian;055D -commainferior;F6E1 -commamonospace;FF0C -commareversedabovecmb;0314 -commareversedmod;02BD -commasmall;FE50 -commasuperior;F6E2 -commaturnedabovecmb;0312 -commaturnedmod;02BB -compass;263C -congruent;2245 -contourintegral;222E -control;2303 -controlACK;0006 -controlBEL;0007 -controlBS;0008 -controlCAN;0018 -controlCR;000D -controlDC1;0011 -controlDC2;0012 -controlDC3;0013 -controlDC4;0014 -controlDEL;007F -controlDLE;0010 -controlEM;0019 -controlENQ;0005 -controlEOT;0004 -controlESC;001B -controlETB;0017 -controlETX;0003 -controlFF;000C -controlFS;001C -controlGS;001D -controlHT;0009 -controlLF;000A -controlNAK;0015 -controlRS;001E -controlSI;000F -controlSO;000E -controlSOT;0002 -controlSTX;0001 -controlSUB;001A -controlSYN;0016 -controlUS;001F -controlVT;000B -copyright;00A9 -copyrightsans;F8E9 -copyrightserif;F6D9 -cornerbracketleft;300C -cornerbracketlefthalfwidth;FF62 -cornerbracketleftvertical;FE41 -cornerbracketright;300D -cornerbracketrighthalfwidth;FF63 -cornerbracketrightvertical;FE42 -corporationsquare;337F -cosquare;33C7 -coverkgsquare;33C6 -cparen;249E -cruzeiro;20A2 -cstretched;0297 -curlyand;22CF -curlyor;22CE -currency;00A4 -cyrBreve;F6D1 -cyrFlex;F6D2 -cyrbreve;F6D4 -cyrflex;F6D5 -d;0064 -daarmenian;0564 -dabengali;09A6 -dadarabic;0636 -dadeva;0926 -dadfinalarabic;FEBE -dadinitialarabic;FEBF -dadmedialarabic;FEC0 -dagesh;05BC -dageshhebrew;05BC -dagger;2020 -daggerdbl;2021 -dagujarati;0AA6 -dagurmukhi;0A26 -dahiragana;3060 -dakatakana;30C0 -dalarabic;062F -dalet;05D3 -daletdagesh;FB33 -daletdageshhebrew;FB33 -dalethatafpatah;05D3 05B2 -dalethatafpatahhebrew;05D3 05B2 -dalethatafsegol;05D3 05B1 -dalethatafsegolhebrew;05D3 05B1 -dalethebrew;05D3 -dalethiriq;05D3 05B4 -dalethiriqhebrew;05D3 05B4 -daletholam;05D3 05B9 -daletholamhebrew;05D3 05B9 -daletpatah;05D3 05B7 -daletpatahhebrew;05D3 05B7 -daletqamats;05D3 05B8 -daletqamatshebrew;05D3 05B8 -daletqubuts;05D3 05BB -daletqubutshebrew;05D3 05BB -daletsegol;05D3 05B6 -daletsegolhebrew;05D3 05B6 -daletsheva;05D3 05B0 -daletshevahebrew;05D3 05B0 -dalettsere;05D3 05B5 -dalettserehebrew;05D3 05B5 -dalfinalarabic;FEAA -dammaarabic;064F -dammalowarabic;064F -dammatanaltonearabic;064C -dammatanarabic;064C -danda;0964 -dargahebrew;05A7 -dargalefthebrew;05A7 -dasiapneumatacyrilliccmb;0485 -dblGrave;F6D3 -dblanglebracketleft;300A -dblanglebracketleftvertical;FE3D -dblanglebracketright;300B -dblanglebracketrightvertical;FE3E -dblarchinvertedbelowcmb;032B -dblarrowleft;21D4 -dblarrowright;21D2 -dbldanda;0965 -dblgrave;F6D6 -dblgravecmb;030F -dblintegral;222C -dbllowline;2017 -dbllowlinecmb;0333 -dbloverlinecmb;033F -dblprimemod;02BA -dblverticalbar;2016 -dblverticallineabovecmb;030E -dbopomofo;3109 -dbsquare;33C8 -dcaron;010F -dcedilla;1E11 -dcircle;24D3 -dcircumflexbelow;1E13 -dcroat;0111 -ddabengali;09A1 -ddadeva;0921 -ddagujarati;0AA1 -ddagurmukhi;0A21 -ddalarabic;0688 -ddalfinalarabic;FB89 -dddhadeva;095C -ddhabengali;09A2 -ddhadeva;0922 -ddhagujarati;0AA2 -ddhagurmukhi;0A22 -ddotaccent;1E0B -ddotbelow;1E0D -decimalseparatorarabic;066B -decimalseparatorpersian;066B -decyrillic;0434 -degree;00B0 -dehihebrew;05AD -dehiragana;3067 -deicoptic;03EF -dekatakana;30C7 -deleteleft;232B -deleteright;2326 -delta;03B4 -deltaturned;018D -denominatorminusonenumeratorbengali;09F8 -dezh;02A4 -dhabengali;09A7 -dhadeva;0927 -dhagujarati;0AA7 -dhagurmukhi;0A27 -dhook;0257 -dialytikatonos;0385 -dialytikatonoscmb;0344 -diamond;2666 -diamondsuitwhite;2662 -dieresis;00A8 -dieresisacute;F6D7 -dieresisbelowcmb;0324 -dieresiscmb;0308 -dieresisgrave;F6D8 -dieresistonos;0385 -dihiragana;3062 -dikatakana;30C2 -dittomark;3003 -divide;00F7 -divides;2223 -divisionslash;2215 -djecyrillic;0452 -dkshade;2593 -dlinebelow;1E0F -dlsquare;3397 -dmacron;0111 -dmonospace;FF44 -dnblock;2584 -dochadathai;0E0E -dodekthai;0E14 -dohiragana;3069 -dokatakana;30C9 -dollar;0024 -dollarinferior;F6E3 -dollarmonospace;FF04 -dollaroldstyle;F724 -dollarsmall;FE69 -dollarsuperior;F6E4 -dong;20AB -dorusquare;3326 -dotaccent;02D9 -dotaccentcmb;0307 -dotbelowcmb;0323 -dotbelowcomb;0323 -dotkatakana;30FB -dotlessi;0131 -dotlessj;F6BE -dotlessjstrokehook;0284 -dotmath;22C5 -dottedcircle;25CC -doubleyodpatah;FB1F -doubleyodpatahhebrew;FB1F -downtackbelowcmb;031E -downtackmod;02D5 -dparen;249F -dsuperior;F6EB -dtail;0256 -dtopbar;018C -duhiragana;3065 -dukatakana;30C5 -dz;01F3 -dzaltone;02A3 -dzcaron;01C6 -dzcurl;02A5 -dzeabkhasiancyrillic;04E1 -dzecyrillic;0455 -dzhecyrillic;045F -e;0065 -eacute;00E9 -earth;2641 -ebengali;098F -ebopomofo;311C -ebreve;0115 -ecandradeva;090D -ecandragujarati;0A8D -ecandravowelsigndeva;0945 -ecandravowelsigngujarati;0AC5 -ecaron;011B -ecedillabreve;1E1D -echarmenian;0565 -echyiwnarmenian;0587 -ecircle;24D4 -ecircumflex;00EA -ecircumflexacute;1EBF -ecircumflexbelow;1E19 -ecircumflexdotbelow;1EC7 -ecircumflexgrave;1EC1 -ecircumflexhookabove;1EC3 -ecircumflextilde;1EC5 -ecyrillic;0454 -edblgrave;0205 -edeva;090F -edieresis;00EB -edot;0117 -edotaccent;0117 -edotbelow;1EB9 -eegurmukhi;0A0F -eematragurmukhi;0A47 -efcyrillic;0444 -egrave;00E8 -egujarati;0A8F -eharmenian;0567 -ehbopomofo;311D -ehiragana;3048 -ehookabove;1EBB -eibopomofo;311F -eight;0038 -eightarabic;0668 -eightbengali;09EE -eightcircle;2467 -eightcircleinversesansserif;2791 -eightdeva;096E -eighteencircle;2471 -eighteenparen;2485 -eighteenperiod;2499 -eightgujarati;0AEE -eightgurmukhi;0A6E -eighthackarabic;0668 -eighthangzhou;3028 -eighthnotebeamed;266B -eightideographicparen;3227 -eightinferior;2088 -eightmonospace;FF18 -eightoldstyle;F738 -eightparen;247B -eightperiod;248F -eightpersian;06F8 -eightroman;2177 -eightsuperior;2078 -eightthai;0E58 -einvertedbreve;0207 -eiotifiedcyrillic;0465 -ekatakana;30A8 -ekatakanahalfwidth;FF74 -ekonkargurmukhi;0A74 -ekorean;3154 -elcyrillic;043B -element;2208 -elevencircle;246A -elevenparen;247E -elevenperiod;2492 -elevenroman;217A -ellipsis;2026 -ellipsisvertical;22EE -emacron;0113 -emacronacute;1E17 -emacrongrave;1E15 -emcyrillic;043C -emdash;2014 -emdashvertical;FE31 -emonospace;FF45 -emphasismarkarmenian;055B -emptyset;2205 -enbopomofo;3123 -encyrillic;043D -endash;2013 -endashvertical;FE32 -endescendercyrillic;04A3 -eng;014B -engbopomofo;3125 -enghecyrillic;04A5 -enhookcyrillic;04C8 -enspace;2002 -eogonek;0119 -eokorean;3153 -eopen;025B -eopenclosed;029A -eopenreversed;025C -eopenreversedclosed;025E -eopenreversedhook;025D -eparen;24A0 -epsilon;03B5 -epsilontonos;03AD -equal;003D -equalmonospace;FF1D -equalsmall;FE66 -equalsuperior;207C -equivalence;2261 -erbopomofo;3126 -ercyrillic;0440 -ereversed;0258 -ereversedcyrillic;044D -escyrillic;0441 -esdescendercyrillic;04AB -esh;0283 -eshcurl;0286 -eshortdeva;090E -eshortvowelsigndeva;0946 -eshreversedloop;01AA -eshsquatreversed;0285 -esmallhiragana;3047 -esmallkatakana;30A7 -esmallkatakanahalfwidth;FF6A -estimated;212E -esuperior;F6EC -eta;03B7 -etarmenian;0568 -etatonos;03AE -eth;00F0 -etilde;1EBD -etildebelow;1E1B -etnahtafoukhhebrew;0591 -etnahtafoukhlefthebrew;0591 -etnahtahebrew;0591 -etnahtalefthebrew;0591 -eturned;01DD -eukorean;3161 -euro;20AC -evowelsignbengali;09C7 -evowelsigndeva;0947 -evowelsigngujarati;0AC7 -exclam;0021 -exclamarmenian;055C -exclamdbl;203C -exclamdown;00A1 -exclamdownsmall;F7A1 -exclammonospace;FF01 -exclamsmall;F721 -existential;2203 -ezh;0292 -ezhcaron;01EF -ezhcurl;0293 -ezhreversed;01B9 -ezhtail;01BA -f;0066 -fadeva;095E -fagurmukhi;0A5E -fahrenheit;2109 -fathaarabic;064E -fathalowarabic;064E -fathatanarabic;064B -fbopomofo;3108 -fcircle;24D5 -fdotaccent;1E1F -feharabic;0641 -feharmenian;0586 -fehfinalarabic;FED2 -fehinitialarabic;FED3 -fehmedialarabic;FED4 -feicoptic;03E5 -female;2640 -ff;FB00 -ffi;FB03 -ffl;FB04 -fi;FB01 -fifteencircle;246E -fifteenparen;2482 -fifteenperiod;2496 -figuredash;2012 -filledbox;25A0 -filledrect;25AC -finalkaf;05DA -finalkafdagesh;FB3A -finalkafdageshhebrew;FB3A -finalkafhebrew;05DA -finalkafqamats;05DA 05B8 -finalkafqamatshebrew;05DA 05B8 -finalkafsheva;05DA 05B0 -finalkafshevahebrew;05DA 05B0 -finalmem;05DD -finalmemhebrew;05DD -finalnun;05DF -finalnunhebrew;05DF -finalpe;05E3 -finalpehebrew;05E3 -finaltsadi;05E5 -finaltsadihebrew;05E5 -firsttonechinese;02C9 -fisheye;25C9 -fitacyrillic;0473 -five;0035 -fivearabic;0665 -fivebengali;09EB -fivecircle;2464 -fivecircleinversesansserif;278E -fivedeva;096B -fiveeighths;215D -fivegujarati;0AEB -fivegurmukhi;0A6B -fivehackarabic;0665 -fivehangzhou;3025 -fiveideographicparen;3224 -fiveinferior;2085 -fivemonospace;FF15 -fiveoldstyle;F735 -fiveparen;2478 -fiveperiod;248C -fivepersian;06F5 -fiveroman;2174 -fivesuperior;2075 -fivethai;0E55 -fl;FB02 -florin;0192 -fmonospace;FF46 -fmsquare;3399 -fofanthai;0E1F -fofathai;0E1D -fongmanthai;0E4F -forall;2200 -four;0034 -fourarabic;0664 -fourbengali;09EA -fourcircle;2463 -fourcircleinversesansserif;278D -fourdeva;096A -fourgujarati;0AEA -fourgurmukhi;0A6A -fourhackarabic;0664 -fourhangzhou;3024 -fourideographicparen;3223 -fourinferior;2084 -fourmonospace;FF14 -fournumeratorbengali;09F7 -fouroldstyle;F734 -fourparen;2477 -fourperiod;248B -fourpersian;06F4 -fourroman;2173 -foursuperior;2074 -fourteencircle;246D -fourteenparen;2481 -fourteenperiod;2495 -fourthai;0E54 -fourthtonechinese;02CB -fparen;24A1 -fraction;2044 -franc;20A3 -g;0067 -gabengali;0997 -gacute;01F5 -gadeva;0917 -gafarabic;06AF -gaffinalarabic;FB93 -gafinitialarabic;FB94 -gafmedialarabic;FB95 -gagujarati;0A97 -gagurmukhi;0A17 -gahiragana;304C -gakatakana;30AC -gamma;03B3 -gammalatinsmall;0263 -gammasuperior;02E0 -gangiacoptic;03EB -gbopomofo;310D -gbreve;011F -gcaron;01E7 -gcedilla;0123 -gcircle;24D6 -gcircumflex;011D -gcommaaccent;0123 -gdot;0121 -gdotaccent;0121 -gecyrillic;0433 -gehiragana;3052 -gekatakana;30B2 -geometricallyequal;2251 -gereshaccenthebrew;059C -gereshhebrew;05F3 -gereshmuqdamhebrew;059D -germandbls;00DF -gershayimaccenthebrew;059E -gershayimhebrew;05F4 -getamark;3013 -ghabengali;0998 -ghadarmenian;0572 -ghadeva;0918 -ghagujarati;0A98 -ghagurmukhi;0A18 -ghainarabic;063A -ghainfinalarabic;FECE -ghaininitialarabic;FECF -ghainmedialarabic;FED0 -ghemiddlehookcyrillic;0495 -ghestrokecyrillic;0493 -gheupturncyrillic;0491 -ghhadeva;095A -ghhagurmukhi;0A5A -ghook;0260 -ghzsquare;3393 -gihiragana;304E -gikatakana;30AE -gimarmenian;0563 -gimel;05D2 -gimeldagesh;FB32 -gimeldageshhebrew;FB32 -gimelhebrew;05D2 -gjecyrillic;0453 -glottalinvertedstroke;01BE -glottalstop;0294 -glottalstopinverted;0296 -glottalstopmod;02C0 -glottalstopreversed;0295 -glottalstopreversedmod;02C1 -glottalstopreversedsuperior;02E4 -glottalstopstroke;02A1 -glottalstopstrokereversed;02A2 -gmacron;1E21 -gmonospace;FF47 -gohiragana;3054 -gokatakana;30B4 -gparen;24A2 -gpasquare;33AC -gradient;2207 -grave;0060 -gravebelowcmb;0316 -gravecmb;0300 -gravecomb;0300 -gravedeva;0953 -gravelowmod;02CE -gravemonospace;FF40 -gravetonecmb;0340 -greater;003E -greaterequal;2265 -greaterequalorless;22DB -greatermonospace;FF1E -greaterorequivalent;2273 -greaterorless;2277 -greateroverequal;2267 -greatersmall;FE65 -gscript;0261 -gstroke;01E5 -guhiragana;3050 -guillemotleft;00AB -guillemotright;00BB -guilsinglleft;2039 -guilsinglright;203A -gukatakana;30B0 -guramusquare;3318 -gysquare;33C9 -h;0068 -haabkhasiancyrillic;04A9 -haaltonearabic;06C1 -habengali;09B9 -hadescendercyrillic;04B3 -hadeva;0939 -hagujarati;0AB9 -hagurmukhi;0A39 -haharabic;062D -hahfinalarabic;FEA2 -hahinitialarabic;FEA3 -hahiragana;306F -hahmedialarabic;FEA4 -haitusquare;332A -hakatakana;30CF -hakatakanahalfwidth;FF8A -halantgurmukhi;0A4D -hamzaarabic;0621 -hamzadammaarabic;0621 064F -hamzadammatanarabic;0621 064C -hamzafathaarabic;0621 064E -hamzafathatanarabic;0621 064B -hamzalowarabic;0621 -hamzalowkasraarabic;0621 0650 -hamzalowkasratanarabic;0621 064D -hamzasukunarabic;0621 0652 -hangulfiller;3164 -hardsigncyrillic;044A -harpoonleftbarbup;21BC -harpoonrightbarbup;21C0 -hasquare;33CA -hatafpatah;05B2 -hatafpatah16;05B2 -hatafpatah23;05B2 -hatafpatah2f;05B2 -hatafpatahhebrew;05B2 -hatafpatahnarrowhebrew;05B2 -hatafpatahquarterhebrew;05B2 -hatafpatahwidehebrew;05B2 -hatafqamats;05B3 -hatafqamats1b;05B3 -hatafqamats28;05B3 -hatafqamats34;05B3 -hatafqamatshebrew;05B3 -hatafqamatsnarrowhebrew;05B3 -hatafqamatsquarterhebrew;05B3 -hatafqamatswidehebrew;05B3 -hatafsegol;05B1 -hatafsegol17;05B1 -hatafsegol24;05B1 -hatafsegol30;05B1 -hatafsegolhebrew;05B1 -hatafsegolnarrowhebrew;05B1 -hatafsegolquarterhebrew;05B1 -hatafsegolwidehebrew;05B1 -hbar;0127 -hbopomofo;310F -hbrevebelow;1E2B -hcedilla;1E29 -hcircle;24D7 -hcircumflex;0125 -hdieresis;1E27 -hdotaccent;1E23 -hdotbelow;1E25 -he;05D4 -heart;2665 -heartsuitblack;2665 -heartsuitwhite;2661 -hedagesh;FB34 -hedageshhebrew;FB34 -hehaltonearabic;06C1 -heharabic;0647 -hehebrew;05D4 -hehfinalaltonearabic;FBA7 -hehfinalalttwoarabic;FEEA -hehfinalarabic;FEEA -hehhamzaabovefinalarabic;FBA5 -hehhamzaaboveisolatedarabic;FBA4 -hehinitialaltonearabic;FBA8 -hehinitialarabic;FEEB -hehiragana;3078 -hehmedialaltonearabic;FBA9 -hehmedialarabic;FEEC -heiseierasquare;337B -hekatakana;30D8 -hekatakanahalfwidth;FF8D -hekutaarusquare;3336 -henghook;0267 -herutusquare;3339 -het;05D7 -hethebrew;05D7 -hhook;0266 -hhooksuperior;02B1 -hieuhacirclekorean;327B -hieuhaparenkorean;321B -hieuhcirclekorean;326D -hieuhkorean;314E -hieuhparenkorean;320D -hihiragana;3072 -hikatakana;30D2 -hikatakanahalfwidth;FF8B -hiriq;05B4 -hiriq14;05B4 -hiriq21;05B4 -hiriq2d;05B4 -hiriqhebrew;05B4 -hiriqnarrowhebrew;05B4 -hiriqquarterhebrew;05B4 -hiriqwidehebrew;05B4 -hlinebelow;1E96 -hmonospace;FF48 -hoarmenian;0570 -hohipthai;0E2B -hohiragana;307B -hokatakana;30DB -hokatakanahalfwidth;FF8E -holam;05B9 -holam19;05B9 -holam26;05B9 -holam32;05B9 -holamhebrew;05B9 -holamnarrowhebrew;05B9 -holamquarterhebrew;05B9 -holamwidehebrew;05B9 -honokhukthai;0E2E -hookabovecomb;0309 -hookcmb;0309 -hookpalatalizedbelowcmb;0321 -hookretroflexbelowcmb;0322 -hoonsquare;3342 -horicoptic;03E9 -horizontalbar;2015 -horncmb;031B -hotsprings;2668 -house;2302 -hparen;24A3 -hsuperior;02B0 -hturned;0265 -huhiragana;3075 -huiitosquare;3333 -hukatakana;30D5 -hukatakanahalfwidth;FF8C -hungarumlaut;02DD -hungarumlautcmb;030B -hv;0195 -hyphen;002D -hypheninferior;F6E5 -hyphenmonospace;FF0D -hyphensmall;FE63 -hyphensuperior;F6E6 -hyphentwo;2010 -i;0069 -iacute;00ED -iacyrillic;044F -ibengali;0987 -ibopomofo;3127 -ibreve;012D -icaron;01D0 -icircle;24D8 -icircumflex;00EE -icyrillic;0456 -idblgrave;0209 -ideographearthcircle;328F -ideographfirecircle;328B -ideographicallianceparen;323F -ideographiccallparen;323A -ideographiccentrecircle;32A5 -ideographicclose;3006 -ideographiccomma;3001 -ideographiccommaleft;FF64 -ideographiccongratulationparen;3237 -ideographiccorrectcircle;32A3 -ideographicearthparen;322F -ideographicenterpriseparen;323D -ideographicexcellentcircle;329D -ideographicfestivalparen;3240 -ideographicfinancialcircle;3296 -ideographicfinancialparen;3236 -ideographicfireparen;322B -ideographichaveparen;3232 -ideographichighcircle;32A4 -ideographiciterationmark;3005 -ideographiclaborcircle;3298 -ideographiclaborparen;3238 -ideographicleftcircle;32A7 -ideographiclowcircle;32A6 -ideographicmedicinecircle;32A9 -ideographicmetalparen;322E -ideographicmoonparen;322A -ideographicnameparen;3234 -ideographicperiod;3002 -ideographicprintcircle;329E -ideographicreachparen;3243 -ideographicrepresentparen;3239 -ideographicresourceparen;323E -ideographicrightcircle;32A8 -ideographicsecretcircle;3299 -ideographicselfparen;3242 -ideographicsocietyparen;3233 -ideographicspace;3000 -ideographicspecialparen;3235 -ideographicstockparen;3231 -ideographicstudyparen;323B -ideographicsunparen;3230 -ideographicsuperviseparen;323C -ideographicwaterparen;322C -ideographicwoodparen;322D -ideographiczero;3007 -ideographmetalcircle;328E -ideographmooncircle;328A -ideographnamecircle;3294 -ideographsuncircle;3290 -ideographwatercircle;328C -ideographwoodcircle;328D -ideva;0907 -idieresis;00EF -idieresisacute;1E2F -idieresiscyrillic;04E5 -idotbelow;1ECB -iebrevecyrillic;04D7 -iecyrillic;0435 -ieungacirclekorean;3275 -ieungaparenkorean;3215 -ieungcirclekorean;3267 -ieungkorean;3147 -ieungparenkorean;3207 -igrave;00EC -igujarati;0A87 -igurmukhi;0A07 -ihiragana;3044 -ihookabove;1EC9 -iibengali;0988 -iicyrillic;0438 -iideva;0908 -iigujarati;0A88 -iigurmukhi;0A08 -iimatragurmukhi;0A40 -iinvertedbreve;020B -iishortcyrillic;0439 -iivowelsignbengali;09C0 -iivowelsigndeva;0940 -iivowelsigngujarati;0AC0 -ij;0133 -ikatakana;30A4 -ikatakanahalfwidth;FF72 -ikorean;3163 -ilde;02DC -iluyhebrew;05AC -imacron;012B -imacroncyrillic;04E3 -imageorapproximatelyequal;2253 -imatragurmukhi;0A3F -imonospace;FF49 -increment;2206 -infinity;221E -iniarmenian;056B -integral;222B -integralbottom;2321 -integralbt;2321 -integralex;F8F5 -integraltop;2320 -integraltp;2320 -intersection;2229 -intisquare;3305 -invbullet;25D8 -invcircle;25D9 -invsmileface;263B -iocyrillic;0451 -iogonek;012F -iota;03B9 -iotadieresis;03CA -iotadieresistonos;0390 -iotalatin;0269 -iotatonos;03AF -iparen;24A4 -irigurmukhi;0A72 -ismallhiragana;3043 -ismallkatakana;30A3 -ismallkatakanahalfwidth;FF68 -issharbengali;09FA -istroke;0268 -isuperior;F6ED -iterationhiragana;309D -iterationkatakana;30FD -itilde;0129 -itildebelow;1E2D -iubopomofo;3129 -iucyrillic;044E -ivowelsignbengali;09BF -ivowelsigndeva;093F -ivowelsigngujarati;0ABF -izhitsacyrillic;0475 -izhitsadblgravecyrillic;0477 -j;006A -jaarmenian;0571 -jabengali;099C -jadeva;091C -jagujarati;0A9C -jagurmukhi;0A1C -jbopomofo;3110 -jcaron;01F0 -jcircle;24D9 -jcircumflex;0135 -jcrossedtail;029D -jdotlessstroke;025F -jecyrillic;0458 -jeemarabic;062C -jeemfinalarabic;FE9E -jeeminitialarabic;FE9F -jeemmedialarabic;FEA0 -jeharabic;0698 -jehfinalarabic;FB8B -jhabengali;099D -jhadeva;091D -jhagujarati;0A9D -jhagurmukhi;0A1D -jheharmenian;057B -jis;3004 -jmonospace;FF4A -jparen;24A5 -jsuperior;02B2 -k;006B -kabashkircyrillic;04A1 -kabengali;0995 -kacute;1E31 -kacyrillic;043A -kadescendercyrillic;049B -kadeva;0915 -kaf;05DB -kafarabic;0643 -kafdagesh;FB3B -kafdageshhebrew;FB3B -kaffinalarabic;FEDA -kafhebrew;05DB -kafinitialarabic;FEDB -kafmedialarabic;FEDC -kafrafehebrew;FB4D -kagujarati;0A95 -kagurmukhi;0A15 -kahiragana;304B -kahookcyrillic;04C4 -kakatakana;30AB -kakatakanahalfwidth;FF76 -kappa;03BA -kappasymbolgreek;03F0 -kapyeounmieumkorean;3171 -kapyeounphieuphkorean;3184 -kapyeounpieupkorean;3178 -kapyeounssangpieupkorean;3179 -karoriisquare;330D -kashidaautoarabic;0640 -kashidaautonosidebearingarabic;0640 -kasmallkatakana;30F5 -kasquare;3384 -kasraarabic;0650 -kasratanarabic;064D -kastrokecyrillic;049F -katahiraprolongmarkhalfwidth;FF70 -kaverticalstrokecyrillic;049D -kbopomofo;310E -kcalsquare;3389 -kcaron;01E9 -kcedilla;0137 -kcircle;24DA -kcommaaccent;0137 -kdotbelow;1E33 -keharmenian;0584 -kehiragana;3051 -kekatakana;30B1 -kekatakanahalfwidth;FF79 -kenarmenian;056F -kesmallkatakana;30F6 -kgreenlandic;0138 -khabengali;0996 -khacyrillic;0445 -khadeva;0916 -khagujarati;0A96 -khagurmukhi;0A16 -khaharabic;062E -khahfinalarabic;FEA6 -khahinitialarabic;FEA7 -khahmedialarabic;FEA8 -kheicoptic;03E7 -khhadeva;0959 -khhagurmukhi;0A59 -khieukhacirclekorean;3278 -khieukhaparenkorean;3218 -khieukhcirclekorean;326A -khieukhkorean;314B -khieukhparenkorean;320A -khokhaithai;0E02 -khokhonthai;0E05 -khokhuatthai;0E03 -khokhwaithai;0E04 -khomutthai;0E5B -khook;0199 -khorakhangthai;0E06 -khzsquare;3391 -kihiragana;304D -kikatakana;30AD -kikatakanahalfwidth;FF77 -kiroguramusquare;3315 -kiromeetorusquare;3316 -kirosquare;3314 -kiyeokacirclekorean;326E -kiyeokaparenkorean;320E -kiyeokcirclekorean;3260 -kiyeokkorean;3131 -kiyeokparenkorean;3200 -kiyeoksioskorean;3133 -kjecyrillic;045C -klinebelow;1E35 -klsquare;3398 -kmcubedsquare;33A6 -kmonospace;FF4B -kmsquaredsquare;33A2 -kohiragana;3053 -kohmsquare;33C0 -kokaithai;0E01 -kokatakana;30B3 -kokatakanahalfwidth;FF7A -kooposquare;331E -koppacyrillic;0481 -koreanstandardsymbol;327F -koroniscmb;0343 -kparen;24A6 -kpasquare;33AA -ksicyrillic;046F -ktsquare;33CF -kturned;029E -kuhiragana;304F -kukatakana;30AF -kukatakanahalfwidth;FF78 -kvsquare;33B8 -kwsquare;33BE -l;006C -labengali;09B2 -lacute;013A -ladeva;0932 -lagujarati;0AB2 -lagurmukhi;0A32 -lakkhangyaothai;0E45 -lamaleffinalarabic;FEFC -lamalefhamzaabovefinalarabic;FEF8 -lamalefhamzaaboveisolatedarabic;FEF7 -lamalefhamzabelowfinalarabic;FEFA -lamalefhamzabelowisolatedarabic;FEF9 -lamalefisolatedarabic;FEFB -lamalefmaddaabovefinalarabic;FEF6 -lamalefmaddaaboveisolatedarabic;FEF5 -lamarabic;0644 -lambda;03BB -lambdastroke;019B -lamed;05DC -lameddagesh;FB3C -lameddageshhebrew;FB3C -lamedhebrew;05DC -lamedholam;05DC 05B9 -lamedholamdagesh;05DC 05B9 05BC -lamedholamdageshhebrew;05DC 05B9 05BC -lamedholamhebrew;05DC 05B9 -lamfinalarabic;FEDE -lamhahinitialarabic;FCCA -laminitialarabic;FEDF -lamjeeminitialarabic;FCC9 -lamkhahinitialarabic;FCCB -lamlamhehisolatedarabic;FDF2 -lammedialarabic;FEE0 -lammeemhahinitialarabic;FD88 -lammeeminitialarabic;FCCC -lammeemjeeminitialarabic;FEDF FEE4 FEA0 -lammeemkhahinitialarabic;FEDF FEE4 FEA8 -largecircle;25EF -lbar;019A -lbelt;026C -lbopomofo;310C -lcaron;013E -lcedilla;013C -lcircle;24DB -lcircumflexbelow;1E3D -lcommaaccent;013C -ldot;0140 -ldotaccent;0140 -ldotbelow;1E37 -ldotbelowmacron;1E39 -leftangleabovecmb;031A -lefttackbelowcmb;0318 -less;003C -lessequal;2264 -lessequalorgreater;22DA -lessmonospace;FF1C -lessorequivalent;2272 -lessorgreater;2276 -lessoverequal;2266 -lesssmall;FE64 -lezh;026E -lfblock;258C -lhookretroflex;026D -lira;20A4 -liwnarmenian;056C -lj;01C9 -ljecyrillic;0459 -ll;F6C0 -lladeva;0933 -llagujarati;0AB3 -llinebelow;1E3B -llladeva;0934 -llvocalicbengali;09E1 -llvocalicdeva;0961 -llvocalicvowelsignbengali;09E3 -llvocalicvowelsigndeva;0963 -lmiddletilde;026B -lmonospace;FF4C -lmsquare;33D0 -lochulathai;0E2C -logicaland;2227 -logicalnot;00AC -logicalnotreversed;2310 -logicalor;2228 -lolingthai;0E25 -longs;017F -lowlinecenterline;FE4E -lowlinecmb;0332 -lowlinedashed;FE4D -lozenge;25CA -lparen;24A7 -lslash;0142 -lsquare;2113 -lsuperior;F6EE -ltshade;2591 -luthai;0E26 -lvocalicbengali;098C -lvocalicdeva;090C -lvocalicvowelsignbengali;09E2 -lvocalicvowelsigndeva;0962 -lxsquare;33D3 -m;006D -mabengali;09AE -macron;00AF -macronbelowcmb;0331 -macroncmb;0304 -macronlowmod;02CD -macronmonospace;FFE3 -macute;1E3F -madeva;092E -magujarati;0AAE -magurmukhi;0A2E -mahapakhhebrew;05A4 -mahapakhlefthebrew;05A4 -mahiragana;307E -maichattawalowleftthai;F895 -maichattawalowrightthai;F894 -maichattawathai;0E4B -maichattawaupperleftthai;F893 -maieklowleftthai;F88C -maieklowrightthai;F88B -maiekthai;0E48 -maiekupperleftthai;F88A -maihanakatleftthai;F884 -maihanakatthai;0E31 -maitaikhuleftthai;F889 -maitaikhuthai;0E47 -maitholowleftthai;F88F -maitholowrightthai;F88E -maithothai;0E49 -maithoupperleftthai;F88D -maitrilowleftthai;F892 -maitrilowrightthai;F891 -maitrithai;0E4A -maitriupperleftthai;F890 -maiyamokthai;0E46 -makatakana;30DE -makatakanahalfwidth;FF8F -male;2642 -mansyonsquare;3347 -maqafhebrew;05BE -mars;2642 -masoracirclehebrew;05AF -masquare;3383 -mbopomofo;3107 -mbsquare;33D4 -mcircle;24DC -mcubedsquare;33A5 -mdotaccent;1E41 -mdotbelow;1E43 -meemarabic;0645 -meemfinalarabic;FEE2 -meeminitialarabic;FEE3 -meemmedialarabic;FEE4 -meemmeeminitialarabic;FCD1 -meemmeemisolatedarabic;FC48 -meetorusquare;334D -mehiragana;3081 -meizierasquare;337E -mekatakana;30E1 -mekatakanahalfwidth;FF92 -mem;05DE -memdagesh;FB3E -memdageshhebrew;FB3E -memhebrew;05DE -menarmenian;0574 -merkhahebrew;05A5 -merkhakefulahebrew;05A6 -merkhakefulalefthebrew;05A6 -merkhalefthebrew;05A5 -mhook;0271 -mhzsquare;3392 -middledotkatakanahalfwidth;FF65 -middot;00B7 -mieumacirclekorean;3272 -mieumaparenkorean;3212 -mieumcirclekorean;3264 -mieumkorean;3141 -mieumpansioskorean;3170 -mieumparenkorean;3204 -mieumpieupkorean;316E -mieumsioskorean;316F -mihiragana;307F -mikatakana;30DF -mikatakanahalfwidth;FF90 -minus;2212 -minusbelowcmb;0320 -minuscircle;2296 -minusmod;02D7 -minusplus;2213 -minute;2032 -miribaarusquare;334A -mirisquare;3349 -mlonglegturned;0270 -mlsquare;3396 -mmcubedsquare;33A3 -mmonospace;FF4D -mmsquaredsquare;339F -mohiragana;3082 -mohmsquare;33C1 -mokatakana;30E2 -mokatakanahalfwidth;FF93 -molsquare;33D6 -momathai;0E21 -moverssquare;33A7 -moverssquaredsquare;33A8 -mparen;24A8 -mpasquare;33AB -mssquare;33B3 -msuperior;F6EF -mturned;026F -mu;00B5 -mu1;00B5 -muasquare;3382 -muchgreater;226B -muchless;226A -mufsquare;338C -mugreek;03BC -mugsquare;338D -muhiragana;3080 -mukatakana;30E0 -mukatakanahalfwidth;FF91 -mulsquare;3395 -multiply;00D7 -mumsquare;339B -munahhebrew;05A3 -munahlefthebrew;05A3 -musicalnote;266A -musicalnotedbl;266B -musicflatsign;266D -musicsharpsign;266F -mussquare;33B2 -muvsquare;33B6 -muwsquare;33BC -mvmegasquare;33B9 -mvsquare;33B7 -mwmegasquare;33BF -mwsquare;33BD -n;006E -nabengali;09A8 -nabla;2207 -nacute;0144 -nadeva;0928 -nagujarati;0AA8 -nagurmukhi;0A28 -nahiragana;306A -nakatakana;30CA -nakatakanahalfwidth;FF85 -napostrophe;0149 -nasquare;3381 -nbopomofo;310B -nbspace;00A0 -ncaron;0148 -ncedilla;0146 -ncircle;24DD -ncircumflexbelow;1E4B -ncommaaccent;0146 -ndotaccent;1E45 -ndotbelow;1E47 -nehiragana;306D -nekatakana;30CD -nekatakanahalfwidth;FF88 -newsheqelsign;20AA -nfsquare;338B -ngabengali;0999 -ngadeva;0919 -ngagujarati;0A99 -ngagurmukhi;0A19 -ngonguthai;0E07 -nhiragana;3093 -nhookleft;0272 -nhookretroflex;0273 -nieunacirclekorean;326F -nieunaparenkorean;320F -nieuncieuckorean;3135 -nieuncirclekorean;3261 -nieunhieuhkorean;3136 -nieunkorean;3134 -nieunpansioskorean;3168 -nieunparenkorean;3201 -nieunsioskorean;3167 -nieuntikeutkorean;3166 -nihiragana;306B -nikatakana;30CB -nikatakanahalfwidth;FF86 -nikhahitleftthai;F899 -nikhahitthai;0E4D -nine;0039 -ninearabic;0669 -ninebengali;09EF -ninecircle;2468 -ninecircleinversesansserif;2792 -ninedeva;096F -ninegujarati;0AEF -ninegurmukhi;0A6F -ninehackarabic;0669 -ninehangzhou;3029 -nineideographicparen;3228 -nineinferior;2089 -ninemonospace;FF19 -nineoldstyle;F739 -nineparen;247C -nineperiod;2490 -ninepersian;06F9 -nineroman;2178 -ninesuperior;2079 -nineteencircle;2472 -nineteenparen;2486 -nineteenperiod;249A -ninethai;0E59 -nj;01CC -njecyrillic;045A -nkatakana;30F3 -nkatakanahalfwidth;FF9D -nlegrightlong;019E -nlinebelow;1E49 -nmonospace;FF4E -nmsquare;339A -nnabengali;09A3 -nnadeva;0923 -nnagujarati;0AA3 -nnagurmukhi;0A23 -nnnadeva;0929 -nohiragana;306E -nokatakana;30CE -nokatakanahalfwidth;FF89 -nonbreakingspace;00A0 -nonenthai;0E13 -nonuthai;0E19 -noonarabic;0646 -noonfinalarabic;FEE6 -noonghunnaarabic;06BA -noonghunnafinalarabic;FB9F -noonhehinitialarabic;FEE7 FEEC -nooninitialarabic;FEE7 -noonjeeminitialarabic;FCD2 -noonjeemisolatedarabic;FC4B -noonmedialarabic;FEE8 -noonmeeminitialarabic;FCD5 -noonmeemisolatedarabic;FC4E -noonnoonfinalarabic;FC8D -notcontains;220C -notelement;2209 -notelementof;2209 -notequal;2260 -notgreater;226F -notgreaternorequal;2271 -notgreaternorless;2279 -notidentical;2262 -notless;226E -notlessnorequal;2270 -notparallel;2226 -notprecedes;2280 -notsubset;2284 -notsucceeds;2281 -notsuperset;2285 -nowarmenian;0576 -nparen;24A9 -nssquare;33B1 -nsuperior;207F -ntilde;00F1 -nu;03BD -nuhiragana;306C -nukatakana;30CC -nukatakanahalfwidth;FF87 -nuktabengali;09BC -nuktadeva;093C -nuktagujarati;0ABC -nuktagurmukhi;0A3C -numbersign;0023 -numbersignmonospace;FF03 -numbersignsmall;FE5F -numeralsigngreek;0374 -numeralsignlowergreek;0375 -numero;2116 -nun;05E0 -nundagesh;FB40 -nundageshhebrew;FB40 -nunhebrew;05E0 -nvsquare;33B5 -nwsquare;33BB -nyabengali;099E -nyadeva;091E -nyagujarati;0A9E -nyagurmukhi;0A1E -o;006F -oacute;00F3 -oangthai;0E2D -obarred;0275 -obarredcyrillic;04E9 -obarreddieresiscyrillic;04EB -obengali;0993 -obopomofo;311B -obreve;014F -ocandradeva;0911 -ocandragujarati;0A91 -ocandravowelsigndeva;0949 -ocandravowelsigngujarati;0AC9 -ocaron;01D2 -ocircle;24DE -ocircumflex;00F4 -ocircumflexacute;1ED1 -ocircumflexdotbelow;1ED9 -ocircumflexgrave;1ED3 -ocircumflexhookabove;1ED5 -ocircumflextilde;1ED7 -ocyrillic;043E -odblacute;0151 -odblgrave;020D -odeva;0913 -odieresis;00F6 -odieresiscyrillic;04E7 -odotbelow;1ECD -oe;0153 -oekorean;315A -ogonek;02DB -ogonekcmb;0328 -ograve;00F2 -ogujarati;0A93 -oharmenian;0585 -ohiragana;304A -ohookabove;1ECF -ohorn;01A1 -ohornacute;1EDB -ohorndotbelow;1EE3 -ohorngrave;1EDD -ohornhookabove;1EDF -ohorntilde;1EE1 -ohungarumlaut;0151 -oi;01A3 -oinvertedbreve;020F -okatakana;30AA -okatakanahalfwidth;FF75 -okorean;3157 -olehebrew;05AB -omacron;014D -omacronacute;1E53 -omacrongrave;1E51 -omdeva;0950 -omega;03C9 -omega1;03D6 -omegacyrillic;0461 -omegalatinclosed;0277 -omegaroundcyrillic;047B -omegatitlocyrillic;047D -omegatonos;03CE -omgujarati;0AD0 -omicron;03BF -omicrontonos;03CC -omonospace;FF4F -one;0031 -onearabic;0661 -onebengali;09E7 -onecircle;2460 -onecircleinversesansserif;278A -onedeva;0967 -onedotenleader;2024 -oneeighth;215B -onefitted;F6DC -onegujarati;0AE7 -onegurmukhi;0A67 -onehackarabic;0661 -onehalf;00BD -onehangzhou;3021 -oneideographicparen;3220 -oneinferior;2081 -onemonospace;FF11 -onenumeratorbengali;09F4 -oneoldstyle;F731 -oneparen;2474 -oneperiod;2488 -onepersian;06F1 -onequarter;00BC -oneroman;2170 -onesuperior;00B9 -onethai;0E51 -onethird;2153 -oogonek;01EB -oogonekmacron;01ED -oogurmukhi;0A13 -oomatragurmukhi;0A4B -oopen;0254 -oparen;24AA -openbullet;25E6 -option;2325 -ordfeminine;00AA -ordmasculine;00BA -orthogonal;221F -oshortdeva;0912 -oshortvowelsigndeva;094A -oslash;00F8 -oslashacute;01FF -osmallhiragana;3049 -osmallkatakana;30A9 -osmallkatakanahalfwidth;FF6B -ostrokeacute;01FF -osuperior;F6F0 -otcyrillic;047F -otilde;00F5 -otildeacute;1E4D -otildedieresis;1E4F -oubopomofo;3121 -overline;203E -overlinecenterline;FE4A -overlinecmb;0305 -overlinedashed;FE49 -overlinedblwavy;FE4C -overlinewavy;FE4B -overscore;00AF -ovowelsignbengali;09CB -ovowelsigndeva;094B -ovowelsigngujarati;0ACB -p;0070 -paampssquare;3380 -paasentosquare;332B -pabengali;09AA -pacute;1E55 -padeva;092A -pagedown;21DF -pageup;21DE -pagujarati;0AAA -pagurmukhi;0A2A -pahiragana;3071 -paiyannoithai;0E2F -pakatakana;30D1 -palatalizationcyrilliccmb;0484 -palochkacyrillic;04C0 -pansioskorean;317F -paragraph;00B6 -parallel;2225 -parenleft;0028 -parenleftaltonearabic;FD3E -parenleftbt;F8ED -parenleftex;F8EC -parenleftinferior;208D -parenleftmonospace;FF08 -parenleftsmall;FE59 -parenleftsuperior;207D -parenlefttp;F8EB -parenleftvertical;FE35 -parenright;0029 -parenrightaltonearabic;FD3F -parenrightbt;F8F8 -parenrightex;F8F7 -parenrightinferior;208E -parenrightmonospace;FF09 -parenrightsmall;FE5A -parenrightsuperior;207E -parenrighttp;F8F6 -parenrightvertical;FE36 -partialdiff;2202 -paseqhebrew;05C0 -pashtahebrew;0599 -pasquare;33A9 -patah;05B7 -patah11;05B7 -patah1d;05B7 -patah2a;05B7 -patahhebrew;05B7 -patahnarrowhebrew;05B7 -patahquarterhebrew;05B7 -patahwidehebrew;05B7 -pazerhebrew;05A1 -pbopomofo;3106 -pcircle;24DF -pdotaccent;1E57 -pe;05E4 -pecyrillic;043F -pedagesh;FB44 -pedageshhebrew;FB44 -peezisquare;333B -pefinaldageshhebrew;FB43 -peharabic;067E -peharmenian;057A -pehebrew;05E4 -pehfinalarabic;FB57 -pehinitialarabic;FB58 -pehiragana;307A -pehmedialarabic;FB59 -pekatakana;30DA -pemiddlehookcyrillic;04A7 -perafehebrew;FB4E -percent;0025 -percentarabic;066A -percentmonospace;FF05 -percentsmall;FE6A -period;002E -periodarmenian;0589 -periodcentered;00B7 -periodhalfwidth;FF61 -periodinferior;F6E7 -periodmonospace;FF0E -periodsmall;FE52 -periodsuperior;F6E8 -perispomenigreekcmb;0342 -perpendicular;22A5 -perthousand;2030 -peseta;20A7 -pfsquare;338A -phabengali;09AB -phadeva;092B -phagujarati;0AAB -phagurmukhi;0A2B -phi;03C6 -phi1;03D5 -phieuphacirclekorean;327A -phieuphaparenkorean;321A -phieuphcirclekorean;326C -phieuphkorean;314D -phieuphparenkorean;320C -philatin;0278 -phinthuthai;0E3A -phisymbolgreek;03D5 -phook;01A5 -phophanthai;0E1E -phophungthai;0E1C -phosamphaothai;0E20 -pi;03C0 -pieupacirclekorean;3273 -pieupaparenkorean;3213 -pieupcieuckorean;3176 -pieupcirclekorean;3265 -pieupkiyeokkorean;3172 -pieupkorean;3142 -pieupparenkorean;3205 -pieupsioskiyeokkorean;3174 -pieupsioskorean;3144 -pieupsiostikeutkorean;3175 -pieupthieuthkorean;3177 -pieuptikeutkorean;3173 -pihiragana;3074 -pikatakana;30D4 -pisymbolgreek;03D6 -piwrarmenian;0583 -plus;002B -plusbelowcmb;031F -pluscircle;2295 -plusminus;00B1 -plusmod;02D6 -plusmonospace;FF0B -plussmall;FE62 -plussuperior;207A -pmonospace;FF50 -pmsquare;33D8 -pohiragana;307D -pointingindexdownwhite;261F -pointingindexleftwhite;261C -pointingindexrightwhite;261E -pointingindexupwhite;261D -pokatakana;30DD -poplathai;0E1B -postalmark;3012 -postalmarkface;3020 -pparen;24AB -precedes;227A -prescription;211E -primemod;02B9 -primereversed;2035 -product;220F -projective;2305 -prolongedkana;30FC -propellor;2318 -propersubset;2282 -propersuperset;2283 -proportion;2237 -proportional;221D -psi;03C8 -psicyrillic;0471 -psilipneumatacyrilliccmb;0486 -pssquare;33B0 -puhiragana;3077 -pukatakana;30D7 -pvsquare;33B4 -pwsquare;33BA -q;0071 -qadeva;0958 -qadmahebrew;05A8 -qafarabic;0642 -qaffinalarabic;FED6 -qafinitialarabic;FED7 -qafmedialarabic;FED8 -qamats;05B8 -qamats10;05B8 -qamats1a;05B8 -qamats1c;05B8 -qamats27;05B8 -qamats29;05B8 -qamats33;05B8 -qamatsde;05B8 -qamatshebrew;05B8 -qamatsnarrowhebrew;05B8 -qamatsqatanhebrew;05B8 -qamatsqatannarrowhebrew;05B8 -qamatsqatanquarterhebrew;05B8 -qamatsqatanwidehebrew;05B8 -qamatsquarterhebrew;05B8 -qamatswidehebrew;05B8 -qarneyparahebrew;059F -qbopomofo;3111 -qcircle;24E0 -qhook;02A0 -qmonospace;FF51 -qof;05E7 -qofdagesh;FB47 -qofdageshhebrew;FB47 -qofhatafpatah;05E7 05B2 -qofhatafpatahhebrew;05E7 05B2 -qofhatafsegol;05E7 05B1 -qofhatafsegolhebrew;05E7 05B1 -qofhebrew;05E7 -qofhiriq;05E7 05B4 -qofhiriqhebrew;05E7 05B4 -qofholam;05E7 05B9 -qofholamhebrew;05E7 05B9 -qofpatah;05E7 05B7 -qofpatahhebrew;05E7 05B7 -qofqamats;05E7 05B8 -qofqamatshebrew;05E7 05B8 -qofqubuts;05E7 05BB -qofqubutshebrew;05E7 05BB -qofsegol;05E7 05B6 -qofsegolhebrew;05E7 05B6 -qofsheva;05E7 05B0 -qofshevahebrew;05E7 05B0 -qoftsere;05E7 05B5 -qoftserehebrew;05E7 05B5 -qparen;24AC -quarternote;2669 -qubuts;05BB -qubuts18;05BB -qubuts25;05BB -qubuts31;05BB -qubutshebrew;05BB -qubutsnarrowhebrew;05BB -qubutsquarterhebrew;05BB -qubutswidehebrew;05BB -question;003F -questionarabic;061F -questionarmenian;055E -questiondown;00BF -questiondownsmall;F7BF -questiongreek;037E -questionmonospace;FF1F -questionsmall;F73F -quotedbl;0022 -quotedblbase;201E -quotedblleft;201C -quotedblmonospace;FF02 -quotedblprime;301E -quotedblprimereversed;301D -quotedblright;201D -quoteleft;2018 -quoteleftreversed;201B -quotereversed;201B -quoteright;2019 -quoterightn;0149 -quotesinglbase;201A -quotesingle;0027 -quotesinglemonospace;FF07 -r;0072 -raarmenian;057C -rabengali;09B0 -racute;0155 -radeva;0930 -radical;221A -radicalex;F8E5 -radoverssquare;33AE -radoverssquaredsquare;33AF -radsquare;33AD -rafe;05BF -rafehebrew;05BF -ragujarati;0AB0 -ragurmukhi;0A30 -rahiragana;3089 -rakatakana;30E9 -rakatakanahalfwidth;FF97 -ralowerdiagonalbengali;09F1 -ramiddlediagonalbengali;09F0 -ramshorn;0264 -ratio;2236 -rbopomofo;3116 -rcaron;0159 -rcedilla;0157 -rcircle;24E1 -rcommaaccent;0157 -rdblgrave;0211 -rdotaccent;1E59 -rdotbelow;1E5B -rdotbelowmacron;1E5D -referencemark;203B -reflexsubset;2286 -reflexsuperset;2287 -registered;00AE -registersans;F8E8 -registerserif;F6DA -reharabic;0631 -reharmenian;0580 -rehfinalarabic;FEAE -rehiragana;308C -rehyehaleflamarabic;0631 FEF3 FE8E 0644 -rekatakana;30EC -rekatakanahalfwidth;FF9A -resh;05E8 -reshdageshhebrew;FB48 -reshhatafpatah;05E8 05B2 -reshhatafpatahhebrew;05E8 05B2 -reshhatafsegol;05E8 05B1 -reshhatafsegolhebrew;05E8 05B1 -reshhebrew;05E8 -reshhiriq;05E8 05B4 -reshhiriqhebrew;05E8 05B4 -reshholam;05E8 05B9 -reshholamhebrew;05E8 05B9 -reshpatah;05E8 05B7 -reshpatahhebrew;05E8 05B7 -reshqamats;05E8 05B8 -reshqamatshebrew;05E8 05B8 -reshqubuts;05E8 05BB -reshqubutshebrew;05E8 05BB -reshsegol;05E8 05B6 -reshsegolhebrew;05E8 05B6 -reshsheva;05E8 05B0 -reshshevahebrew;05E8 05B0 -reshtsere;05E8 05B5 -reshtserehebrew;05E8 05B5 -reversedtilde;223D -reviahebrew;0597 -reviamugrashhebrew;0597 -revlogicalnot;2310 -rfishhook;027E -rfishhookreversed;027F -rhabengali;09DD -rhadeva;095D -rho;03C1 -rhook;027D -rhookturned;027B -rhookturnedsuperior;02B5 -rhosymbolgreek;03F1 -rhotichookmod;02DE -rieulacirclekorean;3271 -rieulaparenkorean;3211 -rieulcirclekorean;3263 -rieulhieuhkorean;3140 -rieulkiyeokkorean;313A -rieulkiyeoksioskorean;3169 -rieulkorean;3139 -rieulmieumkorean;313B -rieulpansioskorean;316C -rieulparenkorean;3203 -rieulphieuphkorean;313F -rieulpieupkorean;313C -rieulpieupsioskorean;316B -rieulsioskorean;313D -rieulthieuthkorean;313E -rieultikeutkorean;316A -rieulyeorinhieuhkorean;316D -rightangle;221F -righttackbelowcmb;0319 -righttriangle;22BF -rihiragana;308A -rikatakana;30EA -rikatakanahalfwidth;FF98 -ring;02DA -ringbelowcmb;0325 -ringcmb;030A -ringhalfleft;02BF -ringhalfleftarmenian;0559 -ringhalfleftbelowcmb;031C -ringhalfleftcentered;02D3 -ringhalfright;02BE -ringhalfrightbelowcmb;0339 -ringhalfrightcentered;02D2 -rinvertedbreve;0213 -rittorusquare;3351 -rlinebelow;1E5F -rlongleg;027C -rlonglegturned;027A -rmonospace;FF52 -rohiragana;308D -rokatakana;30ED -rokatakanahalfwidth;FF9B -roruathai;0E23 -rparen;24AD -rrabengali;09DC -rradeva;0931 -rragurmukhi;0A5C -rreharabic;0691 -rrehfinalarabic;FB8D -rrvocalicbengali;09E0 -rrvocalicdeva;0960 -rrvocalicgujarati;0AE0 -rrvocalicvowelsignbengali;09C4 -rrvocalicvowelsigndeva;0944 -rrvocalicvowelsigngujarati;0AC4 -rsuperior;F6F1 -rtblock;2590 -rturned;0279 -rturnedsuperior;02B4 -ruhiragana;308B -rukatakana;30EB -rukatakanahalfwidth;FF99 -rupeemarkbengali;09F2 -rupeesignbengali;09F3 -rupiah;F6DD -ruthai;0E24 -rvocalicbengali;098B -rvocalicdeva;090B -rvocalicgujarati;0A8B -rvocalicvowelsignbengali;09C3 -rvocalicvowelsigndeva;0943 -rvocalicvowelsigngujarati;0AC3 -s;0073 -sabengali;09B8 -sacute;015B -sacutedotaccent;1E65 -sadarabic;0635 -sadeva;0938 -sadfinalarabic;FEBA -sadinitialarabic;FEBB -sadmedialarabic;FEBC -sagujarati;0AB8 -sagurmukhi;0A38 -sahiragana;3055 -sakatakana;30B5 -sakatakanahalfwidth;FF7B -sallallahoualayhewasallamarabic;FDFA -samekh;05E1 -samekhdagesh;FB41 -samekhdageshhebrew;FB41 -samekhhebrew;05E1 -saraaathai;0E32 -saraaethai;0E41 -saraaimaimalaithai;0E44 -saraaimaimuanthai;0E43 -saraamthai;0E33 -saraathai;0E30 -saraethai;0E40 -saraiileftthai;F886 -saraiithai;0E35 -saraileftthai;F885 -saraithai;0E34 -saraothai;0E42 -saraueeleftthai;F888 -saraueethai;0E37 -saraueleftthai;F887 -sarauethai;0E36 -sarauthai;0E38 -sarauuthai;0E39 -sbopomofo;3119 -scaron;0161 -scarondotaccent;1E67 -scedilla;015F -schwa;0259 -schwacyrillic;04D9 -schwadieresiscyrillic;04DB -schwahook;025A -scircle;24E2 -scircumflex;015D -scommaaccent;0219 -sdotaccent;1E61 -sdotbelow;1E63 -sdotbelowdotaccent;1E69 -seagullbelowcmb;033C -second;2033 -secondtonechinese;02CA -section;00A7 -seenarabic;0633 -seenfinalarabic;FEB2 -seeninitialarabic;FEB3 -seenmedialarabic;FEB4 -segol;05B6 -segol13;05B6 -segol1f;05B6 -segol2c;05B6 -segolhebrew;05B6 -segolnarrowhebrew;05B6 -segolquarterhebrew;05B6 -segoltahebrew;0592 -segolwidehebrew;05B6 -seharmenian;057D -sehiragana;305B -sekatakana;30BB -sekatakanahalfwidth;FF7E -semicolon;003B -semicolonarabic;061B -semicolonmonospace;FF1B -semicolonsmall;FE54 -semivoicedmarkkana;309C -semivoicedmarkkanahalfwidth;FF9F -sentisquare;3322 -sentosquare;3323 -seven;0037 -sevenarabic;0667 -sevenbengali;09ED -sevencircle;2466 -sevencircleinversesansserif;2790 -sevendeva;096D -seveneighths;215E -sevengujarati;0AED -sevengurmukhi;0A6D -sevenhackarabic;0667 -sevenhangzhou;3027 -sevenideographicparen;3226 -seveninferior;2087 -sevenmonospace;FF17 -sevenoldstyle;F737 -sevenparen;247A -sevenperiod;248E -sevenpersian;06F7 -sevenroman;2176 -sevensuperior;2077 -seventeencircle;2470 -seventeenparen;2484 -seventeenperiod;2498 -seventhai;0E57 -sfthyphen;00AD -shaarmenian;0577 -shabengali;09B6 -shacyrillic;0448 -shaddaarabic;0651 -shaddadammaarabic;FC61 -shaddadammatanarabic;FC5E -shaddafathaarabic;FC60 -shaddafathatanarabic;0651 064B -shaddakasraarabic;FC62 -shaddakasratanarabic;FC5F -shade;2592 -shadedark;2593 -shadelight;2591 -shademedium;2592 -shadeva;0936 -shagujarati;0AB6 -shagurmukhi;0A36 -shalshelethebrew;0593 -shbopomofo;3115 -shchacyrillic;0449 -sheenarabic;0634 -sheenfinalarabic;FEB6 -sheeninitialarabic;FEB7 -sheenmedialarabic;FEB8 -sheicoptic;03E3 -sheqel;20AA -sheqelhebrew;20AA -sheva;05B0 -sheva115;05B0 -sheva15;05B0 -sheva22;05B0 -sheva2e;05B0 -shevahebrew;05B0 -shevanarrowhebrew;05B0 -shevaquarterhebrew;05B0 -shevawidehebrew;05B0 -shhacyrillic;04BB -shimacoptic;03ED -shin;05E9 -shindagesh;FB49 -shindageshhebrew;FB49 -shindageshshindot;FB2C -shindageshshindothebrew;FB2C -shindageshsindot;FB2D -shindageshsindothebrew;FB2D -shindothebrew;05C1 -shinhebrew;05E9 -shinshindot;FB2A -shinshindothebrew;FB2A -shinsindot;FB2B -shinsindothebrew;FB2B -shook;0282 -sigma;03C3 -sigma1;03C2 -sigmafinal;03C2 -sigmalunatesymbolgreek;03F2 -sihiragana;3057 -sikatakana;30B7 -sikatakanahalfwidth;FF7C -siluqhebrew;05BD -siluqlefthebrew;05BD -similar;223C -sindothebrew;05C2 -siosacirclekorean;3274 -siosaparenkorean;3214 -sioscieuckorean;317E -sioscirclekorean;3266 -sioskiyeokkorean;317A -sioskorean;3145 -siosnieunkorean;317B -siosparenkorean;3206 -siospieupkorean;317D -siostikeutkorean;317C -six;0036 -sixarabic;0666 -sixbengali;09EC -sixcircle;2465 -sixcircleinversesansserif;278F -sixdeva;096C -sixgujarati;0AEC -sixgurmukhi;0A6C -sixhackarabic;0666 -sixhangzhou;3026 -sixideographicparen;3225 -sixinferior;2086 -sixmonospace;FF16 -sixoldstyle;F736 -sixparen;2479 -sixperiod;248D -sixpersian;06F6 -sixroman;2175 -sixsuperior;2076 -sixteencircle;246F -sixteencurrencydenominatorbengali;09F9 -sixteenparen;2483 -sixteenperiod;2497 -sixthai;0E56 -slash;002F -slashmonospace;FF0F -slong;017F -slongdotaccent;1E9B -smileface;263A -smonospace;FF53 -sofpasuqhebrew;05C3 -softhyphen;00AD -softsigncyrillic;044C -sohiragana;305D -sokatakana;30BD -sokatakanahalfwidth;FF7F -soliduslongoverlaycmb;0338 -solidusshortoverlaycmb;0337 -sorusithai;0E29 -sosalathai;0E28 -sosothai;0E0B -sosuathai;0E2A -space;0020 -spacehackarabic;0020 -spade;2660 -spadesuitblack;2660 -spadesuitwhite;2664 -sparen;24AE -squarebelowcmb;033B -squarecc;33C4 -squarecm;339D -squarediagonalcrosshatchfill;25A9 -squarehorizontalfill;25A4 -squarekg;338F -squarekm;339E -squarekmcapital;33CE -squareln;33D1 -squarelog;33D2 -squaremg;338E -squaremil;33D5 -squaremm;339C -squaremsquared;33A1 -squareorthogonalcrosshatchfill;25A6 -squareupperlefttolowerrightfill;25A7 -squareupperrighttolowerleftfill;25A8 -squareverticalfill;25A5 -squarewhitewithsmallblack;25A3 -srsquare;33DB -ssabengali;09B7 -ssadeva;0937 -ssagujarati;0AB7 -ssangcieuckorean;3149 -ssanghieuhkorean;3185 -ssangieungkorean;3180 -ssangkiyeokkorean;3132 -ssangnieunkorean;3165 -ssangpieupkorean;3143 -ssangsioskorean;3146 -ssangtikeutkorean;3138 -ssuperior;F6F2 -sterling;00A3 -sterlingmonospace;FFE1 -strokelongoverlaycmb;0336 -strokeshortoverlaycmb;0335 -subset;2282 -subsetnotequal;228A -subsetorequal;2286 -succeeds;227B -suchthat;220B -suhiragana;3059 -sukatakana;30B9 -sukatakanahalfwidth;FF7D -sukunarabic;0652 -summation;2211 -sun;263C -superset;2283 -supersetnotequal;228B -supersetorequal;2287 -svsquare;33DC -syouwaerasquare;337C -t;0074 -tabengali;09A4 -tackdown;22A4 -tackleft;22A3 -tadeva;0924 -tagujarati;0AA4 -tagurmukhi;0A24 -taharabic;0637 -tahfinalarabic;FEC2 -tahinitialarabic;FEC3 -tahiragana;305F -tahmedialarabic;FEC4 -taisyouerasquare;337D -takatakana;30BF -takatakanahalfwidth;FF80 -tatweelarabic;0640 -tau;03C4 -tav;05EA -tavdages;FB4A -tavdagesh;FB4A -tavdageshhebrew;FB4A -tavhebrew;05EA -tbar;0167 -tbopomofo;310A -tcaron;0165 -tccurl;02A8 -tcedilla;0163 -tcheharabic;0686 -tchehfinalarabic;FB7B -tchehinitialarabic;FB7C -tchehmedialarabic;FB7D -tchehmeeminitialarabic;FB7C FEE4 -tcircle;24E3 -tcircumflexbelow;1E71 -tcommaaccent;0163 -tdieresis;1E97 -tdotaccent;1E6B -tdotbelow;1E6D -tecyrillic;0442 -tedescendercyrillic;04AD -teharabic;062A -tehfinalarabic;FE96 -tehhahinitialarabic;FCA2 -tehhahisolatedarabic;FC0C -tehinitialarabic;FE97 -tehiragana;3066 -tehjeeminitialarabic;FCA1 -tehjeemisolatedarabic;FC0B -tehmarbutaarabic;0629 -tehmarbutafinalarabic;FE94 -tehmedialarabic;FE98 -tehmeeminitialarabic;FCA4 -tehmeemisolatedarabic;FC0E -tehnoonfinalarabic;FC73 -tekatakana;30C6 -tekatakanahalfwidth;FF83 -telephone;2121 -telephoneblack;260E -telishagedolahebrew;05A0 -telishaqetanahebrew;05A9 -tencircle;2469 -tenideographicparen;3229 -tenparen;247D -tenperiod;2491 -tenroman;2179 -tesh;02A7 -tet;05D8 -tetdagesh;FB38 -tetdageshhebrew;FB38 -tethebrew;05D8 -tetsecyrillic;04B5 -tevirhebrew;059B -tevirlefthebrew;059B -thabengali;09A5 -thadeva;0925 -thagujarati;0AA5 -thagurmukhi;0A25 -thalarabic;0630 -thalfinalarabic;FEAC -thanthakhatlowleftthai;F898 -thanthakhatlowrightthai;F897 -thanthakhatthai;0E4C -thanthakhatupperleftthai;F896 -theharabic;062B -thehfinalarabic;FE9A -thehinitialarabic;FE9B -thehmedialarabic;FE9C -thereexists;2203 -therefore;2234 -theta;03B8 -theta1;03D1 -thetasymbolgreek;03D1 -thieuthacirclekorean;3279 -thieuthaparenkorean;3219 -thieuthcirclekorean;326B -thieuthkorean;314C -thieuthparenkorean;320B -thirteencircle;246C -thirteenparen;2480 -thirteenperiod;2494 -thonangmonthothai;0E11 -thook;01AD -thophuthaothai;0E12 -thorn;00FE -thothahanthai;0E17 -thothanthai;0E10 -thothongthai;0E18 -thothungthai;0E16 -thousandcyrillic;0482 -thousandsseparatorarabic;066C -thousandsseparatorpersian;066C -three;0033 -threearabic;0663 -threebengali;09E9 -threecircle;2462 -threecircleinversesansserif;278C -threedeva;0969 -threeeighths;215C -threegujarati;0AE9 -threegurmukhi;0A69 -threehackarabic;0663 -threehangzhou;3023 -threeideographicparen;3222 -threeinferior;2083 -threemonospace;FF13 -threenumeratorbengali;09F6 -threeoldstyle;F733 -threeparen;2476 -threeperiod;248A -threepersian;06F3 -threequarters;00BE -threequartersemdash;F6DE -threeroman;2172 -threesuperior;00B3 -threethai;0E53 -thzsquare;3394 -tihiragana;3061 -tikatakana;30C1 -tikatakanahalfwidth;FF81 -tikeutacirclekorean;3270 -tikeutaparenkorean;3210 -tikeutcirclekorean;3262 -tikeutkorean;3137 -tikeutparenkorean;3202 -tilde;02DC -tildebelowcmb;0330 -tildecmb;0303 -tildecomb;0303 -tildedoublecmb;0360 -tildeoperator;223C -tildeoverlaycmb;0334 -tildeverticalcmb;033E -timescircle;2297 -tipehahebrew;0596 -tipehalefthebrew;0596 -tippigurmukhi;0A70 -titlocyrilliccmb;0483 -tiwnarmenian;057F -tlinebelow;1E6F -tmonospace;FF54 -toarmenian;0569 -tohiragana;3068 -tokatakana;30C8 -tokatakanahalfwidth;FF84 -tonebarextrahighmod;02E5 -tonebarextralowmod;02E9 -tonebarhighmod;02E6 -tonebarlowmod;02E8 -tonebarmidmod;02E7 -tonefive;01BD -tonesix;0185 -tonetwo;01A8 -tonos;0384 -tonsquare;3327 -topatakthai;0E0F -tortoiseshellbracketleft;3014 -tortoiseshellbracketleftsmall;FE5D -tortoiseshellbracketleftvertical;FE39 -tortoiseshellbracketright;3015 -tortoiseshellbracketrightsmall;FE5E -tortoiseshellbracketrightvertical;FE3A -totaothai;0E15 -tpalatalhook;01AB -tparen;24AF -trademark;2122 -trademarksans;F8EA -trademarkserif;F6DB -tretroflexhook;0288 -triagdn;25BC -triaglf;25C4 -triagrt;25BA -triagup;25B2 -ts;02A6 -tsadi;05E6 -tsadidagesh;FB46 -tsadidageshhebrew;FB46 -tsadihebrew;05E6 -tsecyrillic;0446 -tsere;05B5 -tsere12;05B5 -tsere1e;05B5 -tsere2b;05B5 -tserehebrew;05B5 -tserenarrowhebrew;05B5 -tserequarterhebrew;05B5 -tserewidehebrew;05B5 -tshecyrillic;045B -tsuperior;F6F3 -ttabengali;099F -ttadeva;091F -ttagujarati;0A9F -ttagurmukhi;0A1F -tteharabic;0679 -ttehfinalarabic;FB67 -ttehinitialarabic;FB68 -ttehmedialarabic;FB69 -tthabengali;09A0 -tthadeva;0920 -tthagujarati;0AA0 -tthagurmukhi;0A20 -tturned;0287 -tuhiragana;3064 -tukatakana;30C4 -tukatakanahalfwidth;FF82 -tusmallhiragana;3063 -tusmallkatakana;30C3 -tusmallkatakanahalfwidth;FF6F -twelvecircle;246B -twelveparen;247F -twelveperiod;2493 -twelveroman;217B -twentycircle;2473 -twentyhangzhou;5344 -twentyparen;2487 -twentyperiod;249B -two;0032 -twoarabic;0662 -twobengali;09E8 -twocircle;2461 -twocircleinversesansserif;278B -twodeva;0968 -twodotenleader;2025 -twodotleader;2025 -twodotleadervertical;FE30 -twogujarati;0AE8 -twogurmukhi;0A68 -twohackarabic;0662 -twohangzhou;3022 -twoideographicparen;3221 -twoinferior;2082 -twomonospace;FF12 -twonumeratorbengali;09F5 -twooldstyle;F732 -twoparen;2475 -twoperiod;2489 -twopersian;06F2 -tworoman;2171 -twostroke;01BB -twosuperior;00B2 -twothai;0E52 -twothirds;2154 -u;0075 -uacute;00FA -ubar;0289 -ubengali;0989 -ubopomofo;3128 -ubreve;016D -ucaron;01D4 -ucircle;24E4 -ucircumflex;00FB -ucircumflexbelow;1E77 -ucyrillic;0443 -udattadeva;0951 -udblacute;0171 -udblgrave;0215 -udeva;0909 -udieresis;00FC -udieresisacute;01D8 -udieresisbelow;1E73 -udieresiscaron;01DA -udieresiscyrillic;04F1 -udieresisgrave;01DC -udieresismacron;01D6 -udotbelow;1EE5 -ugrave;00F9 -ugujarati;0A89 -ugurmukhi;0A09 -uhiragana;3046 -uhookabove;1EE7 -uhorn;01B0 -uhornacute;1EE9 -uhorndotbelow;1EF1 -uhorngrave;1EEB -uhornhookabove;1EED -uhorntilde;1EEF -uhungarumlaut;0171 -uhungarumlautcyrillic;04F3 -uinvertedbreve;0217 -ukatakana;30A6 -ukatakanahalfwidth;FF73 -ukcyrillic;0479 -ukorean;315C -umacron;016B -umacroncyrillic;04EF -umacrondieresis;1E7B -umatragurmukhi;0A41 -umonospace;FF55 -underscore;005F -underscoredbl;2017 -underscoremonospace;FF3F -underscorevertical;FE33 -underscorewavy;FE4F -union;222A -universal;2200 -uogonek;0173 -uparen;24B0 -upblock;2580 -upperdothebrew;05C4 -upsilon;03C5 -upsilondieresis;03CB -upsilondieresistonos;03B0 -upsilonlatin;028A -upsilontonos;03CD -uptackbelowcmb;031D -uptackmod;02D4 -uragurmukhi;0A73 -uring;016F -ushortcyrillic;045E -usmallhiragana;3045 -usmallkatakana;30A5 -usmallkatakanahalfwidth;FF69 -ustraightcyrillic;04AF -ustraightstrokecyrillic;04B1 -utilde;0169 -utildeacute;1E79 -utildebelow;1E75 -uubengali;098A -uudeva;090A -uugujarati;0A8A -uugurmukhi;0A0A -uumatragurmukhi;0A42 -uuvowelsignbengali;09C2 -uuvowelsigndeva;0942 -uuvowelsigngujarati;0AC2 -uvowelsignbengali;09C1 -uvowelsigndeva;0941 -uvowelsigngujarati;0AC1 -v;0076 -vadeva;0935 -vagujarati;0AB5 -vagurmukhi;0A35 -vakatakana;30F7 -vav;05D5 -vavdagesh;FB35 -vavdagesh65;FB35 -vavdageshhebrew;FB35 -vavhebrew;05D5 -vavholam;FB4B -vavholamhebrew;FB4B -vavvavhebrew;05F0 -vavyodhebrew;05F1 -vcircle;24E5 -vdotbelow;1E7F -vecyrillic;0432 -veharabic;06A4 -vehfinalarabic;FB6B -vehinitialarabic;FB6C -vehmedialarabic;FB6D -vekatakana;30F9 -venus;2640 -verticalbar;007C -verticallineabovecmb;030D -verticallinebelowcmb;0329 -verticallinelowmod;02CC -verticallinemod;02C8 -vewarmenian;057E -vhook;028B -vikatakana;30F8 -viramabengali;09CD -viramadeva;094D -viramagujarati;0ACD -visargabengali;0983 -visargadeva;0903 -visargagujarati;0A83 -vmonospace;FF56 -voarmenian;0578 -voicediterationhiragana;309E -voicediterationkatakana;30FE -voicedmarkkana;309B -voicedmarkkanahalfwidth;FF9E -vokatakana;30FA -vparen;24B1 -vtilde;1E7D -vturned;028C -vuhiragana;3094 -vukatakana;30F4 -w;0077 -wacute;1E83 -waekorean;3159 -wahiragana;308F -wakatakana;30EF -wakatakanahalfwidth;FF9C -wakorean;3158 -wasmallhiragana;308E -wasmallkatakana;30EE -wattosquare;3357 -wavedash;301C -wavyunderscorevertical;FE34 -wawarabic;0648 -wawfinalarabic;FEEE -wawhamzaabovearabic;0624 -wawhamzaabovefinalarabic;FE86 -wbsquare;33DD -wcircle;24E6 -wcircumflex;0175 -wdieresis;1E85 -wdotaccent;1E87 -wdotbelow;1E89 -wehiragana;3091 -weierstrass;2118 -wekatakana;30F1 -wekorean;315E -weokorean;315D -wgrave;1E81 -whitebullet;25E6 -whitecircle;25CB -whitecircleinverse;25D9 -whitecornerbracketleft;300E -whitecornerbracketleftvertical;FE43 -whitecornerbracketright;300F -whitecornerbracketrightvertical;FE44 -whitediamond;25C7 -whitediamondcontainingblacksmalldiamond;25C8 -whitedownpointingsmalltriangle;25BF -whitedownpointingtriangle;25BD -whiteleftpointingsmalltriangle;25C3 -whiteleftpointingtriangle;25C1 -whitelenticularbracketleft;3016 -whitelenticularbracketright;3017 -whiterightpointingsmalltriangle;25B9 -whiterightpointingtriangle;25B7 -whitesmallsquare;25AB -whitesmilingface;263A -whitesquare;25A1 -whitestar;2606 -whitetelephone;260F -whitetortoiseshellbracketleft;3018 -whitetortoiseshellbracketright;3019 -whiteuppointingsmalltriangle;25B5 -whiteuppointingtriangle;25B3 -wihiragana;3090 -wikatakana;30F0 -wikorean;315F -wmonospace;FF57 -wohiragana;3092 -wokatakana;30F2 -wokatakanahalfwidth;FF66 -won;20A9 -wonmonospace;FFE6 -wowaenthai;0E27 -wparen;24B2 -wring;1E98 -wsuperior;02B7 -wturned;028D -wynn;01BF -x;0078 -xabovecmb;033D -xbopomofo;3112 -xcircle;24E7 -xdieresis;1E8D -xdotaccent;1E8B -xeharmenian;056D -xi;03BE -xmonospace;FF58 -xparen;24B3 -xsuperior;02E3 -y;0079 -yaadosquare;334E -yabengali;09AF -yacute;00FD -yadeva;092F -yaekorean;3152 -yagujarati;0AAF -yagurmukhi;0A2F -yahiragana;3084 -yakatakana;30E4 -yakatakanahalfwidth;FF94 -yakorean;3151 -yamakkanthai;0E4E -yasmallhiragana;3083 -yasmallkatakana;30E3 -yasmallkatakanahalfwidth;FF6C -yatcyrillic;0463 -ycircle;24E8 -ycircumflex;0177 -ydieresis;00FF -ydotaccent;1E8F -ydotbelow;1EF5 -yeharabic;064A -yehbarreearabic;06D2 -yehbarreefinalarabic;FBAF -yehfinalarabic;FEF2 -yehhamzaabovearabic;0626 -yehhamzaabovefinalarabic;FE8A -yehhamzaaboveinitialarabic;FE8B -yehhamzaabovemedialarabic;FE8C -yehinitialarabic;FEF3 -yehmedialarabic;FEF4 -yehmeeminitialarabic;FCDD -yehmeemisolatedarabic;FC58 -yehnoonfinalarabic;FC94 -yehthreedotsbelowarabic;06D1 -yekorean;3156 -yen;00A5 -yenmonospace;FFE5 -yeokorean;3155 -yeorinhieuhkorean;3186 -yerahbenyomohebrew;05AA -yerahbenyomolefthebrew;05AA -yericyrillic;044B -yerudieresiscyrillic;04F9 -yesieungkorean;3181 -yesieungpansioskorean;3183 -yesieungsioskorean;3182 -yetivhebrew;059A -ygrave;1EF3 -yhook;01B4 -yhookabove;1EF7 -yiarmenian;0575 -yicyrillic;0457 -yikorean;3162 -yinyang;262F -yiwnarmenian;0582 -ymonospace;FF59 -yod;05D9 -yoddagesh;FB39 -yoddageshhebrew;FB39 -yodhebrew;05D9 -yodyodhebrew;05F2 -yodyodpatahhebrew;FB1F -yohiragana;3088 -yoikorean;3189 -yokatakana;30E8 -yokatakanahalfwidth;FF96 -yokorean;315B -yosmallhiragana;3087 -yosmallkatakana;30E7 -yosmallkatakanahalfwidth;FF6E -yotgreek;03F3 -yoyaekorean;3188 -yoyakorean;3187 -yoyakthai;0E22 -yoyingthai;0E0D -yparen;24B4 -ypogegrammeni;037A -ypogegrammenigreekcmb;0345 -yr;01A6 -yring;1E99 -ysuperior;02B8 -ytilde;1EF9 -yturned;028E -yuhiragana;3086 -yuikorean;318C -yukatakana;30E6 -yukatakanahalfwidth;FF95 -yukorean;3160 -yusbigcyrillic;046B -yusbigiotifiedcyrillic;046D -yuslittlecyrillic;0467 -yuslittleiotifiedcyrillic;0469 -yusmallhiragana;3085 -yusmallkatakana;30E5 -yusmallkatakanahalfwidth;FF6D -yuyekorean;318B -yuyeokorean;318A -yyabengali;09DF -yyadeva;095F -z;007A -zaarmenian;0566 -zacute;017A -zadeva;095B -zagurmukhi;0A5B -zaharabic;0638 -zahfinalarabic;FEC6 -zahinitialarabic;FEC7 -zahiragana;3056 -zahmedialarabic;FEC8 -zainarabic;0632 -zainfinalarabic;FEB0 -zakatakana;30B6 -zaqefgadolhebrew;0595 -zaqefqatanhebrew;0594 -zarqahebrew;0598 -zayin;05D6 -zayindagesh;FB36 -zayindageshhebrew;FB36 -zayinhebrew;05D6 -zbopomofo;3117 -zcaron;017E -zcircle;24E9 -zcircumflex;1E91 -zcurl;0291 -zdot;017C -zdotaccent;017C -zdotbelow;1E93 -zecyrillic;0437 -zedescendercyrillic;0499 -zedieresiscyrillic;04DF -zehiragana;305C -zekatakana;30BC -zero;0030 -zeroarabic;0660 -zerobengali;09E6 -zerodeva;0966 -zerogujarati;0AE6 -zerogurmukhi;0A66 -zerohackarabic;0660 -zeroinferior;2080 -zeromonospace;FF10 -zerooldstyle;F730 -zeropersian;06F0 -zerosuperior;2070 -zerothai;0E50 -zerowidthjoiner;FEFF -zerowidthnonjoiner;200C -zerowidthspace;200B -zeta;03B6 -zhbopomofo;3113 -zhearmenian;056A -zhebrevecyrillic;04C2 -zhecyrillic;0436 -zhedescendercyrillic;0497 -zhedieresiscyrillic;04DD -zihiragana;3058 -zikatakana;30B8 -zinorhebrew;05AE -zlinebelow;1E95 -zmonospace;FF5A -zohiragana;305E -zokatakana;30BE -zparen;24B5 -zretroflexhook;0290 -zstroke;01B6 -zuhiragana;305A -zukatakana;30BA -#--end -############################################################################### -# TeX extensions -Delta;2206;0394 -Ifractur;2111 -# FFsmall, FFIsmall, FFLsmall, FIsmall, FLsmall: invalid Unicode -FFsmall;D804 -FFIsmall;D807 -FFLsmall;D808 -FIsmall;D805 -FLsmall;D806 -# Germandbls: invalid Unicode, used for secondary replacement from EC.enc -Germandbls;D800 -# Germandblssmall: invalid Unicode -Germandblssmall;D803 -Ng;014A -Omega;2126;03A9 -Rfractur;211C -# SS: invalid Unicode, used for secondary replacement from EC.enc -SS;D800 -# SSsmall: invalid Unicode -SSsmall;D803 -# altselector: invalid Unicode -altselector;D802 -angbracketleft;27E8;2329 -angbracketright;27E9;232A -arrowbothv;2195 -arrowdblbothv;21D5 -arrowleftbothalf;21BD -arrowlefttophalf;21BC -arrownortheast;2197 -arrownorthwest;2196 -arrowrightbothalf;21C1 -arrowrighttophalf;21C0 -arrowsoutheast;2198 -arrowsouthwest;2199 -# ascendercompwordmark: taller cwm, invalid Unicode -ascendercompwordmark;D80A -bardbl;2225 -# capitalcompwordmark: taller cwm, invalid Unicode -capitalcompwordmark;D809 -ceilingleft;2308 -ceilingright;2309 -circlecopyrt;20DD;25CB -circledivide;2298 -circledot;2299 -circleminus;2296 -coproduct;2A3F -# cwm: Unicode for ZWNJ, used for secondary replacement from EC.enc -cwm;200C -dblbracketleft;27E6 -dblbracketright;27E7 -diamond;2662;2666 -diamondmath;22C4 -# 0237 is the proposed allocation for dotless j as of Unicode 4.0 -dotlessj;0237;F6BE -emptyset;2205;F638 -# emptyslot: invalid Unicode; the user explicitly wants this slot empty -emptyslot;D801 -epsilon1;03F5 -equivasymptotic;224D -flat;266D -floorleft;230A -floorright;230B -follows;227B -followsequal;227D -greatermuch;226B -heart;2661;2665 -intersectionsq;2293 -latticetop;22A4 -lessmuch;226A -lscript;2113 -natural;266E -negationslash;0338 -ng;014B -owner;220B -# XXX phi? -phi;03D5;03C6 -phi1;03C6 -pi1;03D6 -precedesequal;227C -prime;2032;02B9 -rho1;03F1 -sharp;266F -similarequal;2243 -slurabove;2322 -slurbelow;2323 -star;22C6 -subsetsqequal;2291 -supersetsqequal;2292 -triangle;25B3 -triangleinv;25BD -triangleleft;25B9 -triangleright;25C3 -turnstileleft;22A2 -turnstileright;22A3 -unionmulti;228E -unionsq;2294 -vector;20D7 -# visualspace: Unicode for OPEN BOX, used for secondary replacement from EC.enc -visualspace;2423 -wreathproduct;2240 -# -- Marco Kuhlmann reported annoying glyph neologisms in fontinst encodings -# Dbar = Dcroat -Dbar;0110 -# compwordmark = cwm -compwordmark;200C -# dbar = dcroat -dbar;0111 -# rangedash = endash -endash;2013 -# hyphenchar = hyphen -hyphenchar;002D -# punctdash = emdash -punctdash;2014 -# visiblespace = visualspace -visiblespace;2423 -# -- end TeX extensions diff --git a/Build/source/texk/texlive/linked_scripts/fontools/font2afm b/Build/source/texk/texlive/linked_scripts/fontools/font2afm deleted file mode 100755 index b0a60420d23..00000000000 --- a/Build/source/texk/texlive/linked_scripts/fontools/font2afm +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/perl - -=pod - -=head1 NAME - -font2afm - create font metrics (in F<afm> format) for (almost) any font file - -=head1 SYNOPSIS - -font2afm [options] I<font> ... - -font2afm [options] @I<filelist> - -=head1 DESCRIPTION - -B<font2afm> generates font metrics (in Adobe's F<afm> format) for Type1, -TrueType and OpenType fonts. - -B<font2afm> is just a wrapper script around several utilities (B<cfftot1>, -B<pf2afm>, B<ttf2afm>, B<pfm2kpx> and B<ot2kpx>) that do the real work. -All these utilities need to be available on your system. - -=head1 OPTIONS - -=over 4 - -=item B<-f> - -Force overwriting of existing F<afm> files. - -=back - -=head1 FILES - -=over 4 - -=item I<font> - -This can be any Type1 (in either F<pfa> or F<pfb> format), TrueType or -OpenType (both PostScript- and TrueType-flavored) font. - -=item I<filelist> - -This should contain a newline-separated list of font filenames. - -=back - -=head1 SEE ALSO - -F<pf2afm> (part of I<GhostScript>), F<ttf2afm> (part of I<pdfTeX>), -F<afm2afm>, F<autoinst>, F<cmap2enc>, F<ot2kpx>, F<pfm2kpx>, F<cfftot1> -(part of Eddie Kohler's I<LCDF TypeTools>). - -=head1 AUTHOR - -Marc Penninga <marc@penninga.info> - -=head1 HISTORY - -=over 12 - -=item I<2005-04-15> - -First version - -=item I<2005-04-29> - -Improved the documentation - -=item I<2005-05-23> - -Bugfix. - -=item I<2005-07-29> - -Added support for PostScript-flavored (F<otf>) OpenType fonts. - -=item I<2005-08-08> - -Bugfix. - -=item I<2010-07-19> - -Another small bugfix. - -=back - -=cut - -############################################################################## - -use Getopt::Std; -use integer; -use warnings; no warnings qw(uninitialized); - -getopts "f", \%options; - -$0 =~ s!.*/!!; -die "Usage: $0 fontfile ...\n or: $0 \@fontlist\n" if @ARGV < 1; - -if ($ARGV[0] =~ m!^@(.+)!) { - open LIST, "<$1" or die "Error: can't open `$1' - $!\n"; - chop(@ARGV = <LIST>); - map {m!\S+! and $_ = $&} @ARGV; -} - -for (@ARGV) { - if (m!(.+)\.(pfb|pfa|ttf|otf)!) { - ($base, $ext) = ($1, $2); - } - else { - warn "Warning: unrecognised font file `$_' skipped\n"; - next; - } - - next if -e "${base}.afm" and !$options{f}; - - if ($ext =~ m!pf(?:a|b)!) { - if (-e "${base}.pfm") { - system "pfm2kpx '${base}.pfm'"; - } - else { - system "pf2afm '$_'"; - } - if (-e "${base}.otf") { - system "ot2kpx '${base}.otf' >'${base}.kpx'"; - open AFM, "<${base}.afm" or - die "Error: can't open `${base}.afm' - $!\n"; - open KPX, "<${base}.kpx" or - warn("Warning: can't open `${base}.kpx' - $!\n"), next; - { - local $/; - $afm = <AFM>; - $kpx = <KPX>; - } - close AFM; - open AFM, ">${base}.afm" or - die "Error: can't create `${base}.afm' - $!\n"; - - if ($afm =~ m!^(.+?)(?:StartKernData.+EndKernData\n)? - EndFontMetrics!sx) - { - print AFM "$1${kpx}EndFontMetrics\n"; - } - else { - warn "Warning: `${base}.afm' seems rotten - please check\n"; - print AFM $afm; - } - unlink "${base}.kpx"; - } - } - elsif ($ext =~ m!ttf!) { - system "ttf2afm -o '${base}.afm' '$_'"; - system "ot2kpx '${base}.ttf' >'${base}.kpx'"; - open AFM, "<${base}.afm" or - die "Error: can't open `${base}.afm' - $!\n"; - open KPX, "<${base}.kpx" or - warn("Warning: can't open `${base}.kpx' - $!\n"), next; - { - local $/; - $afm = <AFM>; - $kpx = <KPX>; - } - close AFM; - open AFM, ">${base}.afm" or - die "Error: can't create `${base}.afm' - $!\n"; - - if ($afm =~ m!^(.+?)(?:StartKernData.+EndKernData\n)? - EndFontMetrics!sx) - { - print AFM "$1${kpx}EndFontMetrics\n"; - } - else { - warn "Warning: `${base}.afm' seems rotten - please check\n"; - print AFM $afm; - } - unlink "${base}.kpx"; - } - elsif ($ext =~ m!otf!) { - system "cfftot1 -b -o ${base}.pfb $_"; - $_ = $base . ".pfb"; - redo; - } - else { - die "Error: you've just found a bug in `$0' - congratulations!\n"; - } -} - -__END__ diff --git a/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx b/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx index b1fce6e72e0..60c2a99b418 100755 --- a/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx +++ b/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx @@ -1,103 +1,134 @@ -#!/usr/bin/perl +#! /usr/bin/env perl -=pod - -=head1 NAME - -ot2kpx - extract kerning information from an OpenType font - -=head1 SYNOPSIS - -ot2kpx I<font> - -=head1 DESCRIPTION - -In many OpenType fonts, most kerning data is stored in the `GPOS' table rather -than in the `kern' table. B<ot2kpx> extracts the kerning data from both tables -and prints it (in F<afm> format) to C<stdout>. +=begin COPYRIGHT -=head1 RESTRICTIONS +---------------------------------------------------------------------------- -=over 2 + Copyright (C) 2005-2012 Marc Penninga. -=item B<-> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 2 + of the License, or (at your option) any later version. -B<ot2kpx> prints data from all features named `kern', regardless of script -and language. Maybe it would be better to let the user choose a script -and language (defaulting to `latn' and `DFLT') and print only the kerning -data from features associated with these values. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -=item B<-> + You should have received a copy of the GNU General Public License + along with this program; if not, write to + Free Software Foundation, Inc., + 59 Temple Place, + Suite 330, + Boston, MA 02111-1307, + USA -B<ot2kpx> uses only the XAdvance data associated with the first glyph in any -kerning pair; all other data in the ValueRecords is ignored. I'm not sure -whether this is The Right Thing to Do; however, almost always there is -no other data, so this approach gives correct results (in fact, the only -font I know of that does contain data other than XAdvance is Linotype -Palatino; this also contains XAdvDevice data, which is used (according to -the OpenType specification) to I<`define subtle, device-dependent adjustments -at specific font sizes or device resolutions'>. Since there is no way to -express such adjustments in F<afm> format, ignoring them seems to be the -only option.) +---------------------------------------------------------------------------- -=back +=end COPYRIGHT -=head1 SEE ALSO +=cut -F<afm2afm>, F<autoinst>, F<cmap2enc>, F<font2afm>, F<pfm2kpx>. +use strict; +use warnings; -=head1 AUTHOR +use integer; +use List::Util @List::Util::EXPORT_OK; +use Pod::Usage; -Marc Penninga <marc@penninga.info> +use v5.10; -=head1 HISTORY +our ($NUM_GLYPHS, $UNITS_PER_EM, %KPX); -=over 12 +sub main { + pod2usage(-verbose => 0) if @ARGV != 1; -=item I<2005-01-10> + my %font = OTF::get_tables($ARGV[0]); -First version + $NUM_GLYPHS = unpack '@4n', $font{maxp}; + $UNITS_PER_EM = unpack '@18n', $font{head}; -=item I<2005-02-18> + my @glyph_name = map { sprintf "index%d", $_ } 0 .. $NUM_GLYPHS - 1; + if (defined $font{CFF}) { + OTF::CFF::get_glyph_names($font{CFF}, \@glyph_name); + } -Rewrote some of the code + if (defined $font{kern}) { + OTF::Kern::parse_kerntable($font{kern}); + } -=item I<2005-03-08> + if (defined $font{GPOS}) { + my @lookup_list_indices + = OTF::GPOS::get_lookup_list_indices($font{GPOS}); + my @all_lookups = OTF::GPOS::get_lookups($font{GPOS}); + my @lookups = @all_lookups[@lookup_list_indices]; + my @subtables = map { OTF::GPOS::get_subtables($_) } @lookups; + + for my $subtable (@subtables) { + my $pos_format = unpack 'n', $subtable; + given ($pos_format) { + when (1) { OTF::GPOS::parse_pos_format_1($subtable) } + when (2) { OTF::GPOS::parse_pos_format_2($subtable) } + default { + warn "[ERROR] invalid PosFormat $pos_format ignored"; + } + } + } + } -Input files searched via B<kpsewhich> (where available) + my $num_kernpairs = sum map { scalar keys %{$KPX{$_}} } keys %KPX; + print "StartKernData\nStartKernPairs $num_kernpairs\n"; + for my $first (sort { $a <=> $b } keys %KPX) { + my $first_glyph = $glyph_name[$first]; + for my $second (sort { $a <=> $b } keys %{$KPX{$first}}) { + print "KPX $first_glyph $glyph_name[$second] ", + "$KPX{$first}{$second}\n"; + } + } + print "EndKernPairs\nEndKernData\n"; -=item I<2005-03-15> + return; +} -Input files searched using B<kpsewhich> or B<findtexmf> -=item I<2005-03-21> +######################################################################## -Test if GPOS table is present before trying to read it -=item I<2005-04-29> +package OTF; -Improved the documentation +#----------------------------------------------------------------------- +# Return a hash with all tables (as strings) from the font +#----------------------------------------------------------------------- +sub get_tables { + my $filename = shift; -=item I<2005-05-25> + open my $fontfile, '<:raw', $filename + or die "[ERROR] can't open $filename: $!"; + my $fontdata = do { local $/; <$fontfile> }; + close $fontfile; -Changed warning that's given when the font contains no GPOS table, to an -informational message. + my ($sfnt_version, @tables) = unpack 'a4nx6/(a16)', $fontdata; -=item I<2005-07-29> + die "[ERROR] $filename: unknown font type" + unless $sfnt_version eq "\x00\x01\x00\x00" + || $sfnt_version eq 'OTTO'; -A few updates to the documentation + my %table = map { my ($tag, $offset, $length) = unpack 'A4@8N@12N', $_; + ($tag => substr $fontdata, $offset, $length); + } + @tables; -=back + return %table; +} -=cut -############################################################################## +######################################################################## -use integer; -use warnings; no warnings qw(uninitialized); -@StandardStrings = qw( +package OTF::CFF; +my @STANDARD_STRINGS = qw( .notdef space exclam quotedbl numbersign dollar percent ampersand quoteright parenleft parenright asterisk @@ -222,437 +253,602 @@ use warnings; no warnings qw(uninitialized); Regular Roman Semibold ); -sub getu($) { - my $arg = shift; - my $n = length $arg; - my $r = 0; - - for my $i (0 .. $n - 1) { - $r = ($r << 8) + unpack("C", substr($arg, $i, 1)); - } - - return $r; -} +#----------------------------------------------------------------------- +# +#----------------------------------------------------------------------- +sub get_glyph_names { + my ($CFF, $glyph_name) = @_; -sub gets16($) { - my $v = getu $_[0]; - if ($v > 0x7FFF) { - $v -= 0x10000; - } + # skip header; parse (and ignore) NAME index + my ($rest) = _parse_index(substr $CFF, unpack '@2C', $CFF); - return $v; -} + # parse TopDict index + ($rest, my @top_dict) = _parse_index($rest); + if (@top_dict > 1) { + warn "[WARNING] multiple fonts in single file not supported"; + } + my %top_dict = _parse_dict($top_dict[0]); + if ($NUM_GLYPHS != unpack 'n', substr($CFF, $top_dict{17}, 2)) { + die "[ERROR] NumGlyphs different in 'maxp' and 'CFF' tables"; + } -sub getnum($) { - my $i; - my $r = 0; + # parse String index + ($rest, my @strings) = _parse_index($rest); + @strings = (@STANDARD_STRINGS, @strings); - if (${$_[0]}[0] == 28) { - shift(@{$_[0]}); - for $i (0, 1) { - $r = ($r << 8) | shift(@{$_[0]}); + my $charset = substr $CFF, $top_dict{15}; + my $format = unpack 'C', $charset; + given ($format) { + when (0) { + my @codes = unpack "\@1n@{[ $NUM_GLYPHS - 1 ]}", $charset; + @$glyph_name = @strings[0, @codes]; + } + when (1) { + my $i = 0; + $glyph_name->[$i++] = $strings[0]; + for (my $j = 0; $i < $NUM_GLYPHS; $j++) { + my ($first, $n_left) + = unpack "\@@{[ 1 + 3*$j ]}nC", $charset; + $glyph_name->[$i + $_] = $strings[$first + $_] + for 0 .. $n_left; + $i += 1 + $n_left; + } } - } - elsif (${$_[0]}[0] == 29) { - shift(@{$_[0]}); - for $i (0 .. 3) { - $r = ($r << 8) | shift(@{$_[0]}); + when (2) { + my $i = 0; + $glyph_name->[$i++] = $strings[0]; + for (my $j = 0; $i < $NUM_GLYPHS; $j++) { + my ($first, $n_left) + = unpack "\@@{[ 1 + 4*$j ]}nn", $charset; + $glyph_name->[$i + $_] = $strings[$first + $_] + for 0 .. $n_left; + $i += 1 + $n_left; + } + } + default { + warn "[ERROR] invalid CharsetFormat '$format' ignored"; } - } - elsif (${$_[0]}[0] == 30) { - shift @{$_[0]}; - $nibbles = ""; - $nibbles .= sprintf("%02x", shift @{$_[0]}) until $nibbles =~ /f/; - $nibbles =~ tr/abef/.E-/d; - $nibbles =~ s/c/E-/g; - $r = eval $nibbles; - } - elsif (${$_[0]}[0] >= 251) { - $r = -256 * (shift(@{$_[0]}) - 251) - shift(@{$_[0]}) - 108; - } - elsif (${$_[0]}[0] >= 247) { - $r = 256 * (shift(@{$_[0]}) - 247) + shift(@{$_[0]}) + 108; - } - else { - $r = shift(@{$_[0]}) - 139; } - return $r; + return; } -sub getidx($) { - my $n = getu(substr $_[0], 0, 2); - my $sz = getu(substr $_[0], 2, 1); - my(@r, @off, @d, $i); - for $i (0 .. $n) { - $off[$i] = getu(substr $_[0], 3 + $i * $sz, $sz); +#----------------------------------------------------------------------- +# Parse Adobe's INDEX format (see CFF spec); return "rest" plus data array +#----------------------------------------------------------------------- +sub _parse_index { + my $index = shift; + + my ($count, $off_size) = unpack 'nC', $index; + my @offsets = unpack "\@3(a$off_size)@{[ $count + 1 ]}", $index; + given ($off_size) { + when (1) { $_ = unpack 'C', $_ for @offsets } + when (2) { $_ = unpack 'n', $_ for @offsets } + when (4) { $_ = unpack 'N', $_ for @offsets } + when (3) { + for my $offset (@offsets) { + my @bytes = map 'C3', $offset; + $offset = ($bytes[0] << 16) + ($bytes[1] << 8) + $bytes[2]; + } + } + default { + warn "[ERROR] invalid OffSize $off_size ignored"; + } } - for $i (0 .. $n - 1) { - $d[$i] = substr $_[0], 2 + ($n + 1) * $sz + $off[$i], - $off[$i + 1] - $off[$i]; + $_ += 2 + $off_size * ($count + 1) for @offsets; + + my @data; + for my $i (0 .. $count - 1) { + $data[$i] + = substr $index, $offsets[$i], $offsets[$i + 1] - $offsets[$i]; } - return substr($_[0], 2 + ($n + 1) * $sz + $off[$n]), @d; + return substr($index, $offsets[$count]), @data; } -sub getcov($) { - my $Coverage = shift; - my $CoverageFormat = getu(substr $Coverage, 0, 2); - my @r = (); - if ($CoverageFormat == 1) { - my $GlyphCount = getu(substr $Coverage, 2, 2); - for my $i (0 .. $GlyphCount - 1) { - push @r, getu(substr $Coverage, 4 + 2 * $i, 2); - } - } - elsif ($CoverageFormat == 2) { - my $RangeCount = getu(substr $Coverage, 2, 2); - for my $i (0 .. $RangeCount - 1) { - my $RangeRecord = substr $Coverage, 4 + 6 * $i, 6; - my $Start = getu(substr $RangeRecord, 0, 2); - my $End = getu(substr $RangeRecord, 2, 2); - for my $j ($Start .. $End) { - push @r, $j; - } - } - } - else { - warn "Warning: unknown CoverageFormat `$CoverageFormat'\n"; +#----------------------------------------------------------------------- +# Parse Adobe's DICT format (see CFF spec); return data hash +#----------------------------------------------------------------------- +sub _parse_dict { + my $dict = shift; + + my @bytes = unpack 'C*', $dict; + my (@operands, %dict); + while (@bytes) { + given ($bytes[0]) { + when ([0 .. 11, 13 .. 22]) { + my $operator = shift @bytes; + ($dict{$operator} = join q{ }, @operands) =~ s/^\s+//xms; + @operands = (); + } + when (12) { + my $operator = join q{ }, splice @bytes, 0, 2; + ($dict{$operator} = join q{ }, @operands) =~ s/^\s+//xms; + @operands = (); + } + when ([28, 29, 30, 32 .. 254]) { + push @operands, _get_number(\@bytes); + } + default { + warn "[ERROR] invalid byte $bytes[0] in DICT ignored"; + shift @bytes; + } + } } - return @r; + + return %dict; } -sub getclass($) { - my @c = (0) * $NumGlyphs; - my $ClassFormat = getu(substr $_[0], 0, 2); - my($i, $j); - - if ($ClassFormat == 1) { - my $StartGlyph = getu(substr $_[0], 2, 2); - my $GlyphCount = getu(substr $_[0], 4, 2); - - for $i (0 .. $GlyphCount - 1) { - $c[$i + $StartGlyph] = getu(substr $_[0], 6 + 2 * $i, 2); - } - } - elsif ($ClassFormat == 2) { - my $ClassRangeCount = getu(substr $_[0], 2, 2); - - for $i (0 .. $ClassRangeCount - 1) { - my $ClassRangeRecord = substr $_[0], 4 + 6 * $i, 6; - my $Start = getu(substr $ClassRangeRecord, 0, 2); - my $End = getu(substr $ClassRangeRecord, 2, 2); - my $Class = getu(substr $ClassRangeRecord, 4, 2); - - for $j ($Start .. $End) { - $c[$j] = $Class; - } - } - } - else { - warn "Warning: unknown ClassFormat `$ClassFormat'\n"; - } +#----------------------------------------------------------------------- +# Parse Adobe's variable-length numbers (see CFF spec); shorten arg array +#----------------------------------------------------------------------- +sub _get_number { + my $bytes = shift; - return @c; + given (my $b0 = shift @$bytes) { + when (28) { + my ($b1, $b2) = splice @$bytes, 0, 2; + return ($b1 << 8) | $b2; + } + when (29) { + my ($b1, $b2, $b3, $b4) = splice @$bytes, 0, 4; + return ((((($b1 << 8) + $b2) << 8) + $b3) << 8) + $b4; + } + when (30) { + # Reals not implemented; just dump appropriate number of bytes + until (($b0 & 0xf0) == 0xf0 || ($b0 & 0xf) == 0xf) { + $b0 = shift @$bytes; + } + } + when ([ 32 .. 246]) { + return $b0 - 139; + } + when ([247 .. 250]) { + my $b1 = shift @$bytes; + return 256 * ($b0 - 247) + $b1 + 108; + } + when ([251 .. 254]) { + my $b1 = shift @$bytes; + return -256 * ($b0 - 251) - $b1 - 108; + } + } } -############################################################################## -use integer; -use warnings; no warnings qw(uninitialized); - -$0 =~ s!.*/!!; -die "Usage: $0 fontfile\n" if @ARGV != 1; - -if ((chop($fn = `kpsewhich $ARGV[0] 2>&1`) and -e $fn) or - (chop($fn = `findtexmf $ARGV[0] 2>&1`) and -e $fn)) -{ - open FONT, "<$fn" or die "Error: can't open `$fn' - $!\n"; -} -else { - open FONT, "<$ARGV[0]" or - die "Error: can't open `$ARGV[0]' - $!\n"; -} -binmode FONT; -{ - local $/; - $FONT = <FONT>; +######################################################################## + + +package OTF::GPOS; + +#----------------------------------------------------------------------- +# Return list of all Lookups from the GPOS table +#----------------------------------------------------------------------- +sub get_lookups { + my $GPOS = shift; + + my $lookup_list = substr $GPOS, unpack '@8n', $GPOS; + my @lookup_offsets = unpack 'n/n', $lookup_list; + + return map { substr $lookup_list, $_ } @lookup_offsets; } -$NumTables = getu(substr $FONT, 4, 2); -for ($i = 0; $i < $NumTables; $i++) { -$Record = substr $FONT, 12 + 16 * $i, 16; - ($Name = substr $Record, 0, 4) =~ s/\s//g; - $Offset = getu(substr $Record, 8, 4); - $Length = getu(substr $Record, 12, 4); - $Table{$Name} = substr $FONT, $Offset, $Length; +#----------------------------------------------------------------------- +# Return list of all LookupListIndices pointed to by 'kern' feature +#----------------------------------------------------------------------- +sub get_lookup_list_indices { + my $GPOS = shift; + + my $feature_list = substr $GPOS, unpack '@6n', $GPOS; + my %lookup_list_index; + for my $feature_record (unpack 'n/(a6)', $feature_list) { + my ($tag, $offset) = unpack 'a4n', $feature_record; + next if $tag ne 'kern'; + + my $feature = substr $feature_list, $offset; + my @lookup_list_indices = unpack '@2n/n', $feature; + $lookup_list_index{$_} = 1 for @lookup_list_indices; + } + + return keys %lookup_list_index; } -$UnitsPerEM = getu(substr $Table{head}, 18, 2); -$NumGlyphs = getu(substr $Table{maxp}, 4, 2); - -if (exists $Table{GPOS}) { - $FeatureList = substr $Table{GPOS}, getu(substr $Table{GPOS}, 6, 2); - $FeatureCount = getu(substr $FeatureList, 0, 2); - for $i (0 .. $FeatureCount - 1) { - $FeatureTag = substr $FeatureList, 2 + 6 * $i, 4; - $Feature = getu(substr $FeatureList, 6 + 6 * $i, 2); - $LookupCount = getu(substr $FeatureList, $Feature + 2, 2); - for $j (0 .. $LookupCount - 1) { - push @{$LookupListIndex{$FeatureTag}}, - getu(substr $FeatureList, $Feature + 4 + 2 * $j, 2); - } +#----------------------------------------------------------------------- +# Return list of all subtables in Lookup table +#----------------------------------------------------------------------- +sub get_subtables { + my $lookup = shift; + + my ($lookup_type, @subtable_offsets) = unpack 'n@4n/n', $lookup; + if ($lookup_type != 2) { + warn "[WARNING] LookupType $lookup_type not implemented"; + return; } - $LookupList = substr $Table{GPOS}, getu(substr $Table{GPOS}, 8, 2); - $LookupCount = getu(substr $LookupList, 0, 2); - for $i (0 .. $LookupCount - 1) { - $Lookup[$i] = substr $LookupList, - getu(substr $LookupList, 2 + 2 * $i, 2); + + return map { substr $lookup, $_ } @subtable_offsets; +} + +#----------------------------------------------------------------------- +# Parse subtable in PairPosFormat 1, store kern pairs in global %KPX +#----------------------------------------------------------------------- +sub parse_pos_format_1 { + my $subtable = shift; + + my ($coverage_offset, $value_format_1, $value_format_2, @pair_set_offsets) + = unpack '@2nnnn/n', $subtable; + + my @coverage = _get_coverage(substr $subtable, $coverage_offset); + my @pair_sets = map { substr $subtable, $_ } @pair_set_offsets; + if (@coverage != @pair_sets) { + warn "[ERROR] Coverage table doesn't match PairSet table"; + return; } - for $j (@{$LookupListIndex{kern}}) { - $LookupTable = $Lookup[$j]; - $LookupType = getu(substr $LookupTable, 0, 2); - $SubTableCount = getu(substr $LookupTable, 4, 2); - if ($LookupType != 2) { - warn "Warning: wrong LookupType `$LookupType', table skipped\n"; - next; - } - for $k (0 .. $SubTableCount - 1) { - $SubTable = substr $LookupTable, - getu(substr $LookupTable, 6 + 2 * $k, 2); - $PosFormat = getu(substr $SubTable, 0, 2); - if ($PosFormat == 1) { - $Coverage = substr $SubTable, getu(substr $SubTable, 2, 2); - @Coverage = getcov($Coverage); - $ValueFormat1 = getu(substr $SubTable, 4, 2); - $ValueFormat2 = getu(substr $SubTable, 6, 2); - - if (!($ValueFormat1 & 0x04) || $ValueFormat2 != 0) { - warn "Warning: ValueFormat `($ValueFormat1, " . - "$ValueFormat2)' not implemented\n"; - next; - } - $PairValueRecordSize = 4; - $ValueOffset = 2; - if ($ValueFormat1 & 0x01) { - $PairValueRecordSize += 2; - $ValueOffset += 2; - } - if ($ValueFormat1 & 0x02) { - $PairValueRecordSize += 2; - $ValueOffset += 2; - } - if ($ValueFormat1 & 0x08) {$PairValueRecordSize += 2} - if ($ValueFormat1 & 0x10) {$PairValueRecordSize += 2} - if ($ValueFormat1 & 0x20) {$PairValueRecordSize += 2} - if ($ValueFormat1 & 0x40) {$PairValueRecordSize += 2} - if ($ValueFormat1 & 0x80) {$PairValueRecordSize += 2} - - $GlyphCount = @Coverage; - $PairSetCount = getu(substr $SubTable, 8, 2); - if ($GlyphCount != $PairSetCount) { - warn "ERROR: GlyphCount not equal to PairSetCount\n"; - next; - } - for $l (0 .. $#Coverage) { - $left = $Coverage[$l]; - $PairSet = substr $SubTable, - getu(substr $SubTable, 10 + 2 * $l, 2); - $PairValueCount = getu(substr $PairSet, 0, 2); - - for $r (0 .. $PairValueCount - 1) { - $PairValueRecord = substr $PairSet, - 2 + $r * $PairValueRecordSize, - $PairValueRecordSize; - $right = getu(substr $PairValueRecord, 0, 2); - $Value = getu(substr $PairValueRecord, $ValueOffset, 2); - $KPX{$left}{$right} ||= $Value * 1000 / $UnitsPerEM; - } - } - } - elsif ($PosFormat == 2) { - $Coverage = substr $SubTable, getu(substr $SubTable, 2, 2); - @Coverage = getcov($Coverage); - - $ValueFormat1 = getu(substr $SubTable, 4, 2); - $ValueFormat2 = getu(substr $SubTable, 6, 2); - - if (!($ValueFormat1 & 0x04) || $ValueFormat2 != 0) { - warn "Warning: ValueFormat `($ValueFormat1, " . - "$ValueFormat2)' not implemented\n"; - next; - } - $Class2RecordSize = 2; - $ValueOffset = 0; - if ($ValueFormat1 & 0x01) { - $Class2RecordSize += 2; - $ValueOffset += 2; - } - if ($ValueFormat1 & 0x02) { - $Class2RecordSize += 2; - $ValueOffset += 2; - } - if ($ValueFormat1 & 0x08) {$Class2RecordSize += 2} - if ($ValueFormat1 & 0x10) {$Class2RecordSize += 2} - if ($ValueFormat1 & 0x20) {$Class2RecordSize += 2} - if ($ValueFormat1 & 0x40) {$Class2RecordSize += 2} - if ($ValueFormat1 & 0x80) {$Class2RecordSize += 2} - - $ClassDef1 = getu(substr $SubTable, 8, 2); - $ClassDef2 = getu(substr $SubTable, 10, 2); - $Class1Count = getu(substr $SubTable, 12, 2); - $Class2Count = getu(substr $SubTable, 14, 2); - @Class1 = getclass(substr $SubTable, $ClassDef1); - @Class2 = getclass(substr $SubTable, $ClassDef2); - - for $l (0 .. $Class1Count - 1) { - $Class1RecordSize = $Class2Count * $Class2RecordSize; - $Class1Record = substr $SubTable, - 16 + $Class1RecordSize * $l, - $Class1RecordSize; - - for $m (0 .. $Class2Count - 1) { - $ValueRecord = substr $Class1Record, - $Class2RecordSize * $m, $Class2RecordSize; - $Value[$l][$m] = - gets16(substr $ValueRecord, $ValueOffset, 2); - } - } - - for $m (@Coverage) { - for $n (0 .. $NumGlyphs - 1) { - if ($Value = $Value[$Class1[$m]][$Class2[$n]]) { - $KPX{$m}{$n} ||= $Value * 1000 / $UnitsPerEM; - } - } - } - } - else { - warn "Warning: unknown PosFormat `$PosFormat'\n"; - next; - } - } + + my ($record_size, $value_offset) + = _parse_value_formats($value_format_1, $value_format_2, 2, 2); + + while (1) { + my $pair_set = shift @pair_sets or last; + my $first = shift @coverage; + + my @pair_value_records = unpack "n/(a$record_size)", $pair_set; + + for my $pair_value_record (@pair_value_records) { + my ($second, $value) + = unpack "n\@${value_offset}s>", $pair_value_record; + next if $value == 0; + $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; + } } -} - - -if (exists $Table{kern}) { - $nTables = getu(substr $Table{kern}, 2, 2); - $startSubTable = 4; - for $i (0 .. $nTables - 1) { - $length = getu(substr $Table{kern}, $startSubTable + 2, 2); - $coverage = getu(substr $Table{kern}, $startSubTable + 4, 2); - if ($coverage != 0x01) { - warn "Warning: format of `kern' table not supported\n"; - $startSubTable += $length; - next; - } - $nPairs = getu(substr $Table{kern}, $startSubTable + 6, 2); - for $j (0 .. $nPairs - 1) { - $kernRecord = substr $Table{kern}, $startSubTable + 14 + 6 * $j, 6; - $left = getu(substr $kernRecord, 0, 2); - $right = getu(substr $kernRecord, 2, 2); - $value = gets16(substr $kernRecord, 4, 2); - $KPX{$left}{$right} ||= $value * 1000 / $UnitsPerEM; - } - $startSubTable += $length; + + return; +} + +#----------------------------------------------------------------------- +# Parse subtable in PairPosFormat 2, store kern pairs in global %KPX +#----------------------------------------------------------------------- +sub parse_pos_format_2 { + my $subtable = shift; + + my ($coverage_offset, $value_format_1, $value_format_2, + $class_def_1, $class_def_2, $class_1_count, $class_2_count) + = unpack '@2nnnnnnn', $subtable; + + my @coverage = _get_coverage(substr $subtable, $coverage_offset); + + my ($class_2_record_size, $value_offset) + = _parse_value_formats($value_format_1, $value_format_2, 0, 0); + + my @class_1 = _get_class(substr $subtable, $class_def_1); + my @class_2 = _get_class(substr $subtable, $class_def_2); + + my $class_1_record_size = $class_2_count * $class_2_record_size; + my @class_1_records + = unpack "\@16(a$class_1_record_size)$class_1_count", $subtable; + + for my $class_1 (0 .. $class_1_count - 1) { + my $class_1_record = $class_1_records[$class_1]; + my @class_2_records + = unpack "(a$class_2_record_size)$class_2_count", $class_1_record; + + for my $class_2 (0 .. $class_2_count - 1) { + my $class_2_record = $class_2_records[$class_2]; + my $value = unpack "\@${value_offset}s>", $class_2_record; + next if $value == 0; + $value = 1000 * $value / $UNITS_PER_EM; + + my @first = grep { $class_1[$_] == $class_1 } @coverage; + my @second = grep { $class_2[$_] == $class_2 } 0 .. $#class_2; + + for my $first (@first) { + for my $second (@second) { + $KPX{$first}{$second} ||= $value; + } + } + } } + + return; } +#----------------------------------------------------------------------- +# Get class number for all glyphs +#----------------------------------------------------------------------- +sub _get_class { + my $class = shift; -if (exists $Table{CFF}) { - $HdrSize = getu(substr $Table{CFF}, 2, 1); - ($CFF, undef) = getidx substr($Table{CFF}, $HdrSize); - ($CFF, @TopDict) = getidx $CFF; - @TopDict = map ord, split(//, $TopDict[0]); - while (@TopDict) { - if ($TopDict[0] > 21) { - push @Operands, getnum(\@TopDict); - } - elsif ($TopDict[0] == 12) { - $Operator = shift(@TopDict) . " " . shift(@TopDict); - ($TopDict{$Operator} = join " ", @Operands) =~ s/^\s*//; - @Operands = undef; - } - else { - $Operator = shift(@TopDict); - ($TopDict{$Operator} = join " ", @Operands) =~ s/^\s*//; - @Operands = undef; - } + my @class = (0) x $NUM_GLYPHS; + + my $class_format = unpack 'n', $class; + given ($class_format) { + when (1) { + my ($start_glyph, @class_value) = unpack '@2nn/n', $class; + @class[$start_glyph .. $start_glyph + $#class_value] + = @class_value; + } + when (2) { + my @class_ranges = unpack '@2n/(a6)', $class; + for my $class_range (@class_ranges) { + my ($start, $end, $class) = unpack 'nnn', $class_range; + @class[$start .. $end] = ($class) x ($end - $start + 1); + } + } + default { + warn "[ERROR] invalid ClassFormat '$class_format' ignored"; + return; + } } - ($CFF, @Strings) = getidx $CFF; - unshift @Strings, @StandardStrings; - if ($NumGlyphs != getu(substr $Table{CFF}, $TopDict{17}, 2)) { - die "Error: NumGlyphs in `maxp' different from `CFF'\n"; + + return @class; +} + + +#----------------------------------------------------------------------- +# Determine size of ValueRecord and offset of XAdvance value in it +#----------------------------------------------------------------------- +sub _parse_value_formats { + my ($value_format_1, $value_format_2, $record_size, $value_offset) = @_; + + unless ($value_format_1 & 0x4 && $value_format_2 == 0) { + warn "[WARNING] ValueFormat ($value_format_1, ", + "$value_format_2) not implemented"; + return; } - if ($TopDict{15} == 0) { - for $i (0 .. 228) {$glyphName[$i] = $Strings[$i]} - } - elsif ($TopDict{15} == 1) { - warn "Warning: predefined CharSet `Expert' not implemented\n"; - } - elsif ($TopDict{15} == 2) { - warn "Warning: predefined CharSet `ExpertSubset' not implemented\n"; - } - else { - $Charset = substr $Table{CFF}, $TopDict{15}; - $Format = getu(substr $Charset, 0, 1); - if ($Format == 0) { - $glyphName[0] = $Strings[0]; - for $j (1 .. $NumGlyphs - 1) { - $glyphName[$j] = $Strings[getu(substr $Charset, 1 + 2 * $j,2)]; - } - } - elsif ($Format == 1) { - $i = 0; - $glyphName[$i++] = $Strings[0]; - for ($j = 0; $i < $NumGlyphs; $j++) { - $first = getu(substr $Charset, 1 + 3 * $j, 2); - $nLeft = getu(substr $Charset, 3 + 3 * $j, 1); - for $k (0 .. $nLeft) { - $glyphName[$i++] = $Strings[$first + $k]; - } - } - } - elsif ($Format == 2) { - $i = 0; - $glyphName[$i++] = $Strings[0]; - for ($j = 0; $i < $NumGlyphs; $j++) { - $first = getu(substr $Charset, 1 + 4 * $j, 2); - $nLeft = getu(substr $Charset, 3 + 4 * $j, 2); - for $k (0 .. $nLeft) { - $glyphName[$i++] = $Strings[$first + $k]; - } - } - } - else {die "Error: unknown CharsetFormat `$Format'\n"} + + for my $bit ((0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80)) { + $record_size += 2 if $value_format_1 & $bit; } -} -else { - for $i (0 .. 0xFF) { - $glyphName[$i] = sprintf "index0x%02X", $i; + for my $bit ((0x1, 0x2)) { + $value_offset += 2 if $value_format_1 & $bit; } - for $i (0x100 .. $NumGlyphs - 1) { - $glyphName[$i] = sprintf "index0x%04X", $i; + + return ($record_size, $value_offset); +} + +#----------------------------------------------------------------------- +# Return a list of GlyphIDs in a Coverage table +#----------------------------------------------------------------------- +sub _get_coverage { + my $coverage = shift; + + my $coverage_format = unpack 'n', $coverage; + given ($coverage_format) { + when (1) { + return unpack '@2n/n', $coverage; + } + when (2) { + my @range_records = unpack '@2n/(a6)', $coverage; + + return map { my ($start, $end) = unpack 'nn', $_; + $start .. $end; + } + @range_records; + } + default { + warn "[WARNING] unknown CoverageFormat $coverage_format ignored"; + } } } -for $i (0 .. $NumGlyphs - 1) { - for $j (0 .. $NumGlyphs - 1) { - if ($Value = $KPX{$i}{$j}) { - push @KPX, sprintf("KPX %s %s %d\n", - $glyphName[$i], $glyphName[$j], - $Value > 0x7FFF ? $Value - 0x10000 : $Value); - } + +######################################################################## + + +package OTF::Kern; + +#----------------------------------------------------------------------- +# Parse "kern"table, store kern pairs in global %KPX +#----------------------------------------------------------------------- +sub parse_kerntable { + my $kern = shift; + + my $num_tables = unpack '@2n', $kern; + my $start_subtable = 4; + for my $i (0 .. $num_tables - 1) { + my $subtable = substr $kern, $start_subtable; + my ($length, $coverage) = unpack '@2nn', $subtable; + $start_subtable += $length; + + if ($coverage != 0x1) { + warn "[WARNING] kern table format '$coverage' not implemented"; + next; + } + + my @kern_pairs = unpack '@6nx6/(a6)', $subtable; + for my $kern_pair (@kern_pairs) { + my ($first, $second, $value) = unpack 'nns>', $kern_pair; + next if $value == 0; + + $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; + } } + + return; } -$KPX = @KPX; -print <<EOF; -StartKernData -StartKernPairs $KPX - @{KPX}EndKernPairs -EndKernData -EOF + +######################################################################## + + +package main; + +main(); __END__ + + +######################################################################## + + + To create the documentation: + + pod2man --center="Marc Penninga" --release="fontools" --section=1 \ + ot2kpx - | groff -Tps -man - | ps2pdf - ot2kpx.pdf + +=pod + +=head1 NAME + +ot2kpx - extract kerning information from OpenType fonts + + +=head1 SYNOPSIS + +=over 8 + +=item B<ot2kpx> + +B<fontfile> + +=back + + +=head1 DESCRIPTION + +B<ot2kpx> extract the kerning data from OpenType fonts (both F<otf> +and F<ttf> formats) and prints it (in F<afm> format) to C<stdout>. + + +=head1 OPTIONS AND ARGUMENTS + +=over 4 + +=item B<fontfile> + +The OpenType font (in either F<otf> or F<ttf> format). + +=back + + +=head1 RESTRICTIONS + +=over 4 + +=item B<-> + +B<ot2kpx> doesn't implement all of the OpenType specification. +Things that are missing include: support for font files containing +multiple fonts, LookupTables with LookupTypes other than 2, +"kern" tables with format other than 0 and ValueRecords with +other types of data than just XAdvance data. + +Most of these limitations don't really matter, since the missing features +are rare (the only fonts I know of that use them are the non-western fonts +that come with Adobe Reader). Furthermore, some of these features concern +(according to the OpenType specification) I<"define subtle, device-dependent +adjustments at specific font sizes or device resolutions">. +Since there's no way to express such adjustments in F<afm> format, +ignoring them seems to be the only option anyway. + +=item B<-> + +B<ot2kpx> collects kerning data first from the "kern" table, then from +all LookupTables associated with the "kern" feature; if a kerning pair +occurs multiple times, the first value seen is chosen. +There are (or may be) several issues with this approach: + +=over 4 + +=item - + +The OpenType specification says that fonts in F<otf> format shouldn't +use the "kern" table at all, just the lookups from the "GPOS" table. +Many such fonts do, however, contain a "kern" table, but no "GPOS" table; +so we use the "kern" table anyway. + +=item - + +Instead of reading all LookupTables, it might be better to let the user +specify a script and language and process only the LookupTables for +those values. +However, at least in the fonts I checked, all script/language combinations +eventually point to the I<same> "kern" LookupTables, so this approach +wouldn't make any difference (apart from further complicating the code). + +=back + +=back + + +=head1 AUTHOR + +Marc Penninga <marcpenninga@gmail.com> + + +=head1 COPYRIGHT + +Copyright (C) 2005-2012 Marc Penninga. + + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published +by the Free Software Foundation, either version 2 of the License, +or (at your option) any later version. +A copy of the GNU General Public License is included with B<autoinst>; +see the file F<GPLv2.txt>. + + +=head1 DISCLAIMER + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + + +=head1 RECENT CHANGES + +(See the source code for the rest of the story.) + +=over 12 + +=item I<2012-02-01> + +Refactored the code, and fixed a number of bugs in the process. +Updated the documentation. + +=back + + +=begin Really_old_history + +=over 12 + +=item I<2005-01-10> + +First version + +=item I<2005-02-18> + +Rewrote some of the code + +=item I<2005-03-08> + +Input files searched via B<kpsewhich> (where available) + +=item I<2005-03-15> + +Input files searched using B<kpsewhich> or B<findtexmf> + +=item I<2005-03-21> + +Test if GPOS table is present before trying to read it + +=item I<2005-04-29> + +Improved the documentation + +=item I<2005-05-25> + +Changed warning that's given when the font contains no GPOS table, to an +informational message. + +=item I<2005-07-29> + +A few updates to the documentation + +=back + +=cut + diff --git a/Build/source/texk/texlive/linked_scripts/fontools/pfm2kpx b/Build/source/texk/texlive/linked_scripts/fontools/pfm2kpx deleted file mode 100755 index a2202bcd680..00000000000 --- a/Build/source/texk/texlive/linked_scripts/fontools/pfm2kpx +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/perl - -=pod - -=head1 NAME - -pfm2kpx - extract correct kerning information from F<pfm> -(Printer Font Metrics) files - -=head1 SYNOPSIS - -pfm2kpx [options] I<pfm> - -=head1 DESCRIPTION - -Many PostScript Type1 fonts contain only -F<pfb> and F<pfm> files, but no F<afm> (Adobe Font Metrics) files. These can be -generated with I<pf2afm> (which comes with I<GhostScript>), but -this might not yield all kerning pairs from the F<pfm> file. The reason -for this is that I<pf2afm> interprets C<dfCharSet = 0x00> to mean that -the Adobe StandardEncoding has been used, whereas many fonts (or font -creation tools) instead use the Windows ANSI (aka codepage 1252) encoding. -(You know you've hit this problem when B<pf2afm> complains "C<.notdef -character ocurred among kern pairs -- you'd better check the resulting -AFM file>".) In this case, the resulting F<afm> is incomplete and contains -wrong kerning pairs. - -B<pfm2kpx> extracts the correct kerning pairs from such F<pfm> files and -repairs the F<afm> (if necessary creating it first by running I<pf2afm>). -If for some reason it can't update the F<afm>, it prints the kerning pairs to -C<stdout> instead. - -When I<pf2afm> doesn't complain about the kerning pairs, B<pfm2kpx> -thinks the resulting F<afm> file is fine and quits; this can be -changed by specifying the B<-f> option (see below). - -=head1 OPTIONS - -=over 4 - -=item B<-f> - -Force updating of the F<afm> file, even if I<pf2afm> doesn't complain. - -=back - -=head1 SEE ALSO - -F<pf2afm> (part of GhostScript), F<afm2afm>, F<autoinst>, F<cmap2enc>, -F<font2afm>, F<ot2kpx>. - -=head1 AUTHOR - -Marc Penninga <marc@penninga.info> - -=head1 HISTORY - -=over 12 - -=item I<2005-02-17> - -First version - -=item I<2005-02-18> - -Added C<binmode PFM> to make B<pfm2kpx> work on Windows platforms - -=item I<2005-03-08> - -Input files searched via B<kpsewhich> (where available) - -=item I<2005-03-14> - -Rewrote some of the code to make it more robust, added the B<-f> option - -=item I<2005-03-15> - -Input files searched using B<kpsewhich> or B<findtexmf> - -=item I<2005-04-29> - -Improved the documentation - -=item I<2005-05-24> - -Bugfix. - -=item I<2005-07-29> - -Some updates to the documentation. - -=back - -=cut - -############################################################################## - -@winansi = qw( - - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - .notdef .notdef .notdef .notdef - - 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 .notdef - - Euro .notdef quotesinglbase florin - quotedblbase ellipsis dagger daggerdbl - circumflex perthousand Scaron guilsinglleft - OE .notdef Zcaron .notdef - - .notdef quoteleft quoteright quotedblleft - quotedblright bullet endash emdash - tilde trademark scaron guilsignlright - oe .notdef zcaron Ydieresis - - .notdef exclamdown cent sterling - currency yen brokenbar section - dieresis copyright ordfeminine guillemotleft - logicalnot .notdef registered macron - - degree plusminus twosuperior threesuperior - acute mu paragraph periodcentered - cedilla onesuperior ordmasculine guillemotright - onequarter onehalf threequarters questiondown - - Agrave Aacute Acircumflex Atilde - Adieresis Aring AE Ccedilla - Egrave Eacute Ecircumflex Edieresis - Igrave Iacute Icircumflex Idieresis - - Eth Ntilde Ograve Oacute - Ocircumflex Otilde Odieresis multiply - Oslash Ugrave Uacute Ucircumflex - Udieresis Yacute Thorn germandbls - - agrave aacute acircumflex atilde - adieresis aring ae ccedilla - egrave eacute ecircumflex edieresis - igrave iacute icircumflex idieresis - - eth ntilde ograve oacute - ocircumflex otilde odieresis divide - oslash ugrave uacute ucircumflex - udieresis yacute thorn ydieresis -); - -sub getword($) { - my @bytes = reverse(split(//, substr($_[0], 0, 2))); - my $r = 0; - - for (@bytes) { - $r = ($r << 8) + unpack "C", $_; - } - - return $r >= 32768 ? $r - 65536 : $r; -} - -sub getdword($) { - my @bytes = reverse(split(//, substr($_[0], 0, 4))); - my $r = 0; - - for (@bytes) { - $r = ($r << 8) + unpack "C", $_; - } - - return $r; -} - -############################################################################## - -use Getopt::Std; -use integer; -use warnings; no warnings qw(uninitialized); - -getopts "f", \%options; - -$0 =~ s!.*/!!; -die "Usage: $0 pfmfile\n" if @ARGV != 1; - -($base = $ARGV[0]) =~ s!.*/|\.pfm!!g; -unless (-e "${base}.afm") { - $errmsg = `pf2afm '${base}.pfb'`; - if ($errmsg !~ /\.notdef character ocurred among kern pairs/ and - not exists $options{f}) - { - warn "Warning: output from <pf2afm> seems OK; skipping `$ARGV[0]'.\n", - " If you disagree, rerun $0 with the `-f' option\n"; - exit 0; - } -} - -if ((chop($fn = `kpsewhich '$ARGV[0]' 2>&1`) and -e $fn) or - (chop($fn = `findtexmf '$ARGV[0]' 2>&1`) and -e $fn)) -{ - open PFM, "<$fn" or die "Error: can't open `$fn' - $!\n"; -} -else { - open PFM, "<$ARGV[0]" or - die "Error: can't open `$ARGV[0]' - $!\n"; -} -binmode PFM; -{ - local $/; - $pfm = <PFM>; -} - -$dfCharSet = unpack "C", substr($pfm, 85, 1); -if ($dfCharSet != 0) { - die "Error: `dfCharSet' is $dfCharSet, not 0\n"; -} - -$dfPairKernTable = getdword(substr $pfm, 131, 4); -$etmKernPairs = getword(substr $pfm, 195, 2); -if ($dfPairKernTable == 0 or $etmKernPairs == 0) { - warn "Warning: no kerning pairs found in `$ARGV[0]'\n"; - exit; -} -$pairkern = substr $pfm, $dfPairKernTable; -$n = getword(substr $pairkern, 0, 2); -if ($n != $etmKernPairs) { - warn "Warning: incorrect number of kerning pairs in `$ARGV[0]';\n", - " please check the resulting AFM file!\n"; -} -for $i (0 .. $n - 1) { - $pair = substr $pairkern, 2 + 4 * $i, 4; - $left = unpack "C", substr($pair, 0, 1); - $right = unpack "C", substr($pair, 1, 1); - $kern = getword(substr($pair, 2, 2)); - - push @KPX, "KPX $winansi[$left] $winansi[$right] $kern\n"; -} - -if (open AFM, "<${base}.afm") { - { - local $/; - $afm = <AFM>; - } - $afm =~ s/StartKernData.*//s; - $afm =~ s/\r\n*/\n/gs; - $time = localtime; - $afm =~ s/(?<=Comment ).*?$/Converted at $time by $0 from $ARGV[0]/m; - if (open AFM, ">${base}.afm") {select AFM} - else { - warn "Warning: can't create `${base}.afm' - $!\n" . - " printing to <STDOUT> instead\n"; - } - print <<EOF; -${afm} -StartKernData -StartKernPairs $n - @{KPX}EndKernPairs -EndKernData - -EndFontMetrics -EOF -} -else { - warn "Warning: file `${base}.afm' not found, " . - "printing only kerning pairs\n"; - print "StartKernData\nStartKernPairs $n\n"; - map print, @KPX; - print "EndKernPairs\nEndKernData\n"; -} - -__END__ diff --git a/Build/source/texk/texlive/linked_scripts/fontools/showglyphs b/Build/source/texk/texlive/linked_scripts/fontools/showglyphs deleted file mode 100755 index 1622ebe432f..00000000000 --- a/Build/source/texk/texlive/linked_scripts/fontools/showglyphs +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl - -=pod - -=head1 NAME - -showglyphs - create a F<pdf> file that shows all glyphs in a font - -=head1 SYNOPSIS - -showglyphs I<fontfile> - -=head1 DESCRIPTION - -This program creates a F<pdf> file that shows all glyphs in a given font. - -=head1 FILES - -=over 4 - -=item I<font> - -This can be any Type 1 or TrueType font; OpenType fonts are not (yet?) -supported. - -=back - -=head1 RESTRICTIONS - -=over 4 - -=item B<-> - -B<showglyphs> only works on Unix/Linux systems. - -=item B<-> - -B<showglyphs> needs a working, TDS-compliant Tex installation - -=back - -=head1 SEE ALSO - -F<afm2afm>, F<autoinst>, F<cmap2enc>, F<pfm2kpx>, F<enc2etx>, -F<etx2enc>, F<ot2kpx>. - -=head1 AUTHOR - -Marc Penninga <marc@penninga.info> - -=head1 HISTORY - -=over 12 - -=item I<2005-04-28> - -First version - -=item I<2005-04-29> - -A few bugfixes; B<showglyphs> now works with glyphnames containing underscores - -=item I<2005-05-24> - -Another bugfix - -=item I<2005-07-29> - -A few updates to the documentation - -=back - -=cut - -use integer; -use warnings; no warnings qw(uninitialized); - -$0 =~ s!.*/!!g; -die "Usage: $0 fontfile\n" if @ARGV != 1; - -system "mkdir -p ./showglyphs/"; -system "cp $ARGV[0] ./showglyphs/"; -chdir "./showglyphs"; - -system "font2afm $ARGV[0]"; -$ARGV[0] =~ /([\w-]+)\./ and $fontname = $1; - -open AFM, "<${fontname}.afm" or - die "Error: can't open `${fontname}.afm' - $!\n"; -{ - local $/; - $_ = <AFM>; -} - -(/StartCharMetrics (\d+)/m and $num_glyphs = $1) or $num_glyphs = 255; -@vec = (".notdef") x (($num_glyphs / 256 + 1) * 256); - -for (/(WX.*?$)/gm) {/N\s+([\w.]+)/ and $vec[$i++] = $1} - -system "cp `locate pdftex.map` ."; -open TEX, ">tmp.tex" or die "Error: can't create `tmp.tex' - $!\n"; -print TEX <<EOF; -\\documentclass[a4paper]{article} -\\setlength\\parindent{0pt} -\\setlength\\parskip{0pt} -\\raggedbottom\\frenchspacing - -\\newlength\\tempdima -\\makeatletter -\\setlength\\textheight{\\paperheight} -\\addtolength\\textheight{-2in} -\\setlength\\textwidth{\\paperwidth} -\\addtolength\\textwidth{-2in} - -\\setlength\\oddsidemargin{0pt} -\\setlength\\evensidemargin{0pt} - -\\setlength\\topmargin{0pt} -\\addtolength\\topmargin{-\\headheight} -\\addtolength\\topmargin{-\\headsep} -\\makeatother - -\\newcommand*{\\printglyph}[2]{% - \\frame{% - \\settodepth{\\tempdima}{#1}% - \\makebox[2em][l]{% - \\rule[-18pt]{0pt}{48pt}% - \\makebox[0pt][l]{% - \\raisebox{-14pt}{\\makebox[2em][c]{\\tiny#2}}}% - \\raisebox{-\\tempdima}{% - \\makebox[2em][c]{\\linethickness{0pt}\\frame{#1}}}}}} - -\\begin{document} -EOF - -for ($i = 0; $i < $num_glyphs / 256 + 1; $i++) { - $filename = sprintf "%s%03d", $fontname, $i + 1; - - open ENC, ">$filename.enc" or - die "Error: can't create `$filename.enc' - $!\n"; - - print ENC "%\n% Created ", scalar localtime, - " by $0 from `${fontname}.afm'\n"; - print ENC "%\n/", $filename, " [\n"; - - for ($j = 0; $j < 256; $j += 16) { - printf ENC "%% 0x%04x\n", $j; - for ($k = 0; $k < 16; $k += 4) { - print ENC "\t"; - for ($l = 0; $l < 4; $l++) { - print ENC "/$vec[$i * 256 + $j + $k + $l] "; - } - print ENC "\n"; - } - } - - print ENC "] def\n"; - close ENC; - - system "afm2afm -e '${filename}.enc' -o '${filename}.afm' " . - "'${fontname}.afm' >>./pdftex.map"; - system "afm2tfm '${fontname}.afm' -T '${filename}.enc' '${filename}.tfm'" - . ">/dev/null"; - - for (@vec[256 * $i..256*($i+1)]) {s/(?<!\\)_/\\_/g} - print TEX "\\font\\test=${filename} at 24pt\\test\n"; - for $j (0 .. 31) { - for $k (0 .. 7) { - print TEX "\\printglyph{\\char", 8 * $j + $k, - "}{$vec[$i * 256 + 8 * $j + $k]} "; - } - print TEX "\\par\n"; - last if 256 * $i + 8 * ($j + 1) >= $num_glyphs; - } -} -print TEX "\n\\end{document}\n"; -close TEX; - -system "pdflatex tmp >/dev/null"; -chdir "../"; -system "mv showglyphs/tmp.pdf './${fontname}.pdf'"; -system "/bin/rm -r ./showglyphs/"; - -__END__ |