#!/usr/bin/perl

=begin COPYRIGHT  ------------------------------------------------------------

    autoinst - wrapper script around F<otftotfm>, for installing 
               (PostScript-flavored) OpenType fonts.

    Copyright (c) 2005 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::Long;
use integer;
use strict;
use warnings;


my $EMPTY_STRING = q{};
my $SPACE        = q{ };



$0 =~ s{ .*/ }{ $EMPTY_STRING }xmse;

my $USAGE =<<"END_USAGE";
USAGE: $0 [options] otf_file[s]

Possible options:
    --encoding=enc      Use encoding <enc> for the text fonts
    --sanserif          Install font as sanserif font
    --typewriter        Install font as typewriter font
    --(no)ts1           Turn creation of TS1 fonts on/off
    --(no)superiors     Turn creation of fonts of superior characters on/off
    --(no)inferiors     Turn creation of fonts of inferior characters on/off
    --(no)ornaments     Turn creation of ornament fonts on/off
    --(no)fractions     Turn creation of fonts with 'fraction' digits on/off
    --manual            Manual mode
    --verbose           Verbose mode
    --extra='text'      Add <text> to the options for otftotfm

    otf_file[s]         the OpenType font(s) to install.
    
END_USAGE



my ( $FONTFAMILY, %fd, %fd_entry, $fd_key, $fd_val, %have_seen, @commands );



=begin Comment

    The hash %FD_WEIGHT maps weights (from filenames) to NFSS codes.
    The array @FD_WEIGHT determines the sorting order of the entries 
    in the fd files.
    
=end

=cut

my @FD_WEIGHT = (
    Thin        =>  'ul',
    Light       =>  'l',
    Lt          =>  'l',
    Book        =>  $EMPTY_STRING,
    Regular     =>  $EMPTY_STRING,
    Rg          =>  $EMPTY_STRING,
    Medium      =>  'mb',
    Med         =>  'mb',
    Demibold    =>  'db',
    Semibold    =>  'sb',
    Smbd        =>  'sb',
    Sbd         =>  'sb',
    Sb          =>  'sb',
    Bold        =>  'b',
    Bd          =>  'b',
    ExtraBold   =>  'eb',
    Black       =>  'eb',
    XBlack      =>  'xb',
    Ultrablack  =>  'ub',
    Ultra       =>  'ub',
);
my %FD_WEIGHT = @FD_WEIGHT;



=begin Comment

    The hash %FD_WIDTH maps widths (from filenames) to NFSS codes.
    The array @FD_WIDTH determines the sorting order of the entries 
    in the fd files.

=end

=cut

my @FD_WIDTH = (
    UltraCond   =>  'uc',
    UltraCn     =>  'uc',
    Condensed   =>  'c',
    Cond        =>  'c',
    Cn          =>  'c',
    SemiCond    =>  'sc',
    Scn         =>  'sc',
    Regular     =>  $EMPTY_STRING,
    SemiExt     =>  'sx',
    Extended    =>  'x',
    Ext         =>  'x',
    Ex          =>  'x',
);
my %FD_WIDTH = @FD_WIDTH;



=begin Comment

    The following hash is used for deciding which font families and shapes to 
    generate. Each key names a font family:
        lining      text w/ lining figures
        oldstyle    text w/ oldstyle figures
        textcomp    symbols (TS1-encoded)
        superiors   superior letters and figures (same encoding as text)
        inferiors   inferior letters and figures (same encoding as text)
        ornaments   ornaments (encoded with 'lorn.enc')

    The value corresponding to each key is an anonymous array of shapes;
    each entry in this array is an anonymous hash with a number of 
    key-value pairs:
        fd_n    the name of the shape in LaTeX's NFSS, if the font is
                upright.
        fd_i    the name of the shape in LaTeX's NFSS, if the font is
                italic or oblique (sloped).
        feat    the OpenType features used to create this shape. This is a
                string of the form "required|at_least_one|optional":
                    required        the shape is only built if the font 
                                    supports *all* these features
                    at_least_one    the shape is built if the font supports
                                    at least *one* of these features
                    optional        these features are used if the font
                                    supports them, but they don't prevent
                                    a shape from being generated when 
                                    they're missing.
        extra   extra options passed to otftotfm when creating this font.

    If the fd_n (fd_i) entry for a shape is missing or empty, 
    the upright (italic) version of that shape won't be generated.

    Adding, modifying or deleting shapes shouldn't break the program; 
    please let me know if it does.

=end

=cut

my %FD_SHAPE = (
    lining      =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  '||kern liga lnum tnum',
        },
        {   # Small caps
            fd_n    =>  'sc',
            fd_i    =>  'si',
            feat    =>  'smcp||kern liga lnum tnum',
            extra   =>  '--unicoding "germandbls =: SSsmall"',
        },
        {   # Swash
            fd_n    =>  'nw',
            fd_i    =>  'sw',
            feat    =>  '|dlig swsh|kern liga lnum tnum',
            extra   =>  '--include-alternates "*.swash" -faalt',
        },
        {   # Titling
            fd_n    =>  'tl',
            fd_i    =>  'ti',
            feat    =>  '|case cpsp|kern liga lnum pnum',
        },
    ],
    oldstyle    =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'onum||kern liga pnum',
        },
        {   # Small caps
            fd_n    =>  'sc',
            fd_i    =>  'si',
            feat    =>  'onum smcp||kern liga pnum',
            extra   =>  '--unicoding "germandbls =: SSsmall"',
        },
        {   # Swash
            fd_n    =>  'nw',
            fd_i    =>  'sw',
            feat    =>  'onum|dlig swsh|kern liga pnum',
            extra   =>  '--include-alternates "*.swash" -faalt',
        },
    ],
    textcomp    =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  '||onum pnum',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
    superiors   =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'sups||',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
    inferiors   =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'sinf||',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
    numerators  =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'numr||',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
    denominators  =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'dnom||',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
    ornaments   =>  [
        {   # Regular text
            fd_n    =>  'n',
            fd_i    =>  'it',
            feat    =>  'ornm||',
            extra   =>  '--ligkern "* {KL} *"',
        },
    ],
);



=begin Comment

    These regular expressions are used for parsing the filenames of 
    OpenType fonts. These are based on the naming scheme used by Adobe:
    
        <Family>-<Weight><Width><Shape><Size>.otf
    
    The last four items are all optional (and in some fonts, such as
    'CourierStd.otf', all four are indeed missing; in that case,
    the hyphen is left out as well). 
    
    The regex that does the real filename parsing (RE_FONT) is built up
    from five smaller regexes, each of which matches one element of the
    filename.
    
    The match on <Weight> is non-greedy; this is to accomodate the
    keyword 'Ultra', which can occur in both weights and widths. 
    A filename of 'UniversStd-UltraCn.otf' should be parsed as 
    Weight=Regular and Width=UltraCn, not as Weight=Ultra, Width=Cn. 
    Filenames such as 'Galliard-Ultra.otf', on the other hand, should 
    be parsed as Weight=Ultra, Width=Regular.

=end

=cut

# FontFamily is everything up to the hyphen or '.otf' (whichever comes first)
# The '-Pro' is for some non-Adobe fonts, '-RomanI+' is for Silentium.
my $RE_FAMILY = qr{ [^.-]+ (?: - (?:Pro|RomanI+) )?? }xms;

# FontWeight is anything that matches one of the keys in %FD_WEIGHT
my $RE_WEIGHT = join '|', reverse sort keys %FD_WEIGHT;

# FontWidth is anything that matches one of the keys in %FD_WIDTH
my $RE_WIDTH  = join '|', reverse sort keys %FD_WIDTH;
                
my $RE_SHAPE  = ' Roman | Italic | Ital | It | Oblique | Obl ';

# This will only match fonts that have multiple optical masters
my $RE_SIZE   = ' Capt | Text | Subh | Disp ';

# Match the whole filename
my $RE_FONT   = qr{ \A
                    (
                        ( $RE_FAMILY )
                        (?:
                            -
                            ( $RE_WEIGHT )??
                            ( $RE_WIDTH  )?
                            ( $RE_SHAPE  )?
                            ( $RE_SIZE   )?
                        )?
                    )
                    \.otf \z
                }xms;



=begin Comment
    
    The entries in the generated fd files are sorted by series and shape;
    within each entry, the 'size-info' entries are sorted by size (or 
    rather by the start of that size range).

    This not only results in cleaner looking fd files, but it also allows 
    us to notice errors in the filename parsing (which usually result in
    several fonts being assigned the same combination of NFSS codes) and
    to fix the size ranges for fonts with multiple optical masters.

    The order in which series and shapes are sorted, is determined by the
    two look-up tables %sort_series and %sort_shape. These are generated
    automatically from the @FD_WEIGHT, @FD_WIDTH and %FD_SHAPE tables.

    The actual sorting uses the compare_fd and compare_size subroutines
    to pairwise compare the items to be sorted.

=end

=cut

my (%sort_series, %sort_shape);

for my $i ( 0  ..  (@FD_WIDTH - 2) / 2 ) {
    for my $j ( 0  ..  (@FD_WEIGHT - 2) / 2 ) {
        my $series 
            = ( $FD_WEIGHT[ 2 * $j + 1 ] . $FD_WIDTH[ 2 * $i + 1 ] ) || 'm';
        if ( !exists( $sort_series{$series} ) ) {
            $sort_series{$series} = $i * @FD_WEIGHT + $j;
        }
    }
}

for my $shape ( values %FD_SHAPE ) {
    for my $i ( 0 .. $#{$shape} ) {
        $sort_shape{ $shape->[$i]{fd_n} } ||= 2 * $i;
        $sort_shape{ $shape->[$i]{fd_i} } ||= 2 * $i + 1;
    }
}

# Match fontseries and -shape in a DeclareFontShape line from an fd file
my $RE_FONTSHAPE = qr{
                       \\DeclareFontShape 
                       (?: \{ [^\}]+ \} ){2}    # encoding + family (ignored)
                       \{ ([^\}]+) \}           # fontseries
                       \{ ([^\}]+) \}           # fontshape
                   }xms;

# Sort the DeclareFontShape entries
sub compare_fd {
    my $ERROR_MESSAGE 
        = "ERROR: failure in compare_fd();\n"
        . "probably caused by an error in the filename parsing.\n"
        . "Please send me a bug report and I'll try to fix it.\n"
        ;

    my ($series_a, $shape_a) = $a =~ m{ $RE_FONTSHAPE }xms
        or die $ERROR_MESSAGE;

    my ($series_b, $shape_b) = $b =~ m{ $RE_FONTSHAPE }xms
        or die $ERROR_MESSAGE;

    return( $sort_series{$series_a} <=> $sort_series{$series_b} or 
            $sort_shape{$shape_a}   <=> $sort_shape{$shape_b} 
    );
}

# Match the start of a size range in a 'size-info'
my $RE_SIZEINFO = qr{
                      <             # opening bracket
                      ([\d.]+)      # start of size range
                      -             # literal hyphen
                      [\d.]+        # end of size range
                      >             # closing bracket
                  }xms;

# Sort the 'size-info' entries in a DeclareFontShape entry
sub compare_size {
    my $ERROR_MESSAGE 
        = "ERROR: failure in compare_size();\n"
        . "probably caused by an error in the filename parsing.\n"
        . "Please send me a bug report and I'll try to fix it.\n"
        ;

    my ($start_range_a) = $a =~ m{ $RE_SIZEINFO }xms
        or die $ERROR_MESSAGE;

    my ($start_range_b) = $b =~ m{ $RE_SIZEINFO }xms
        or die $ERROR_MESSAGE;

    return( $start_range_a <=> $start_range_b );
}



##############################################################################
##############################                  ##############################
#############################    MAIN PROGRAM    #############################
##############################                  ##############################
##############################################################################


my @now   = localtime;
my $today = sprintf "%04d/%02d/%02d", $now[5] + 1900, $now[4] + 1, $now[3];

# Default values for the command line options
my %option = (
    encoding    =>  'ly1',
    sanserif    =>  '0',
    typewriter  =>  '0',
    textcomp    =>  '2',    # 0 = no, 1 = yes, 2 = ( enc eq 't1' ? yes : no )
    superiors   =>  '1',    # 0 = no, 1 = yes
    inferiors   =>  '0',    # 0 = no, 1 = yes
    fractions   =>  '0',    # 0 = no, 1 = yes
    ornaments   =>  '1',    # 0 = no, 1 = yes
    manual      =>  '0',    # 0 = no, 1 = yes
    verbose     =>  '0',    # 0 = no, 1 = yes
    extra       =>  $EMPTY_STRING,
);

# Process the command line options
GetOptions(
    'encoding=s'    =>  \$option{encoding}, 
    'sanserif'      =>  \$option{sanserif}, 
    'typewriter'    =>  \$option{typewriter}, 
    'ts1!'          =>  \$option{textcomp},
    'superiors!'    =>  \$option{superiors}, 
    'inferiors!'    =>  \$option{inferiors}, 
    'fractions!'    =>  \$option{fractions}, 
    'ornaments!'    =>  \$option{ornaments}, 
    'manual'        =>  \$option{manual}, 
    'verbose'       =>  \$option{verbose},
    'extra=s'       =>  \$option{extra} 
) 
or die "ERROR: parsing of command line options failed.\n";

if ( $option{sanserif} && $option{typewriter} ) {
    die "ERROR: '--sanserif' and '--typewriter' are mutually exclusive.\n";
}
my $LaTeX_family
    = $option{sanserif}   ? 'sf'
    : $option{typewriter} ? 'tt'
    :                       'rm';

# Remove the font families that weren't selected from the %FD_SHAPE array
for my $family ( qw( textcomp superiors inferiors ornaments ) ) {
    if ( !$option{$family} ) {
        delete $FD_SHAPE{$family};
    }
}
if ( !$option{fractions} ) {
    delete @FD_SHAPE{ qw(numerators denominators) };
}
if ( !( $option{encoding} eq 't1' or $option{textcomp} == 1 ) ) {
    delete $FD_SHAPE{textcomp};
}

# Do we have any file arguments?
if (!@ARGV) {
    die "$USAGE";
}


FONTFILE:
for my $filename (@ARGV) {
    if ( ! -e $filename ) {
        warn "ERROR: file '$filename' not found\n";
        next FONTFILE;
    }
    
    # Local variables for the NFSS-classification of the generated fonts
    my ($fd_encoding, $fd_family, $fd_series, $fd_shape, $fd_size);
    
    # Filename parsing    
    my %fontattr;
    @fontattr{ qw( name family weight width shape size ) }
        = $filename =~ m{ $RE_FONT }xms
        or do {
            warn "WARNING: filename parsing failed for '$filename'\n";
            next FONTFILE;
        };
        
    # Use default values for attributes that were omitted
    $fontattr{weight} ||= 'Regular';
    $fontattr{shape}  ||= 'Roman';
    $fontattr{width}  ||= 'Regular';
    $fontattr{size}   ||= 'Text';

    # Minion is two families (MinionPro, -Std); we use the same name for both
    $FONTFAMILY ||= $fontattr{family};

    # The NFSS 'series' attribute is a combination of weight and width
    $fd_series 
        = $FD_WEIGHT{ $fontattr{weight} } . $FD_WIDTH{ $fontattr{width} } 
        || 'm';
        
    # Remember that we've seen this series
    $have_seen{series}{$fd_series} = 1;

    if ($option{verbose}) {    
        print <<"END_FONT_ATTR";

File '$filename':
    Family  $FONTFAMILY
    Weight  $fontattr{weight}
    Width   $fontattr{width}
    Shape   $fontattr{shape}
END_FONT_ATTR
    }


    # Use otfinfo to get size info for fonts with multiple optical masters.
    my $OTFINFO;
    open $OTFINFO, '-|', "otfinfo -z $filename"
        or do {
            warn "ERROR: 'otfinfo -z $filename' failed - $!\n";
            next FONTFILE;
        };
    if ( <$OTFINFO> =~ m{ \( ([\d.]+) \s+ pt, \s+ ([\d.]+) \s+ pt \] }xms ) {
        $fd_size = "<$1-$2>";
    }
    else {
        if ( $fontattr{size} ne 'Text' ) {
            warn "ERROR: couldn't find size info in '$filename'\n";
            next FONTFILE;
        }
        $fd_size = "<->";
    }
    close $OTFINFO;

    if ($option{verbose}) { 
        print "    Size    $fontattr{size} ($fd_size)\n";
    }

    
    # Use otfinfo to find out which features this font supports
    my %feature;
    open $OTFINFO, '-|', "otfinfo -f $filename"
        or do {
            warn "ERROR: 'otfinfo -f $filename' failed - $!\n";
            next FONTFILE;
        };
    for my $feature (<$OTFINFO>) {
        if ( $feature =~ m{ \A (\w{4}) \s }xms ) {
            $feature{$1} = 1;
        }
    }
    close $OTFINFO;
    
    if ($option{verbose}) {
        my $prefix = '    Feat    ';
        my $count  = 0;
        for my $feature ( sort keys %feature ) {
            print "$prefix$feature";
            $prefix = q{, };
            if ( $count++ > 8 ) {
                $prefix = ",\n" . $SPACE x 12;
                $count  = 0;
            }
        }
        print "\n\n";
    }


    FAMILY:
    for my $family ( keys %FD_SHAPE ) {

        # TS1 and ornaments use their own encoding; others use default
        my $encoding 
            = $family eq 'ornaments' ? 'lorn'
            : $family eq 'textcomp'  ? 'ts1'
            :                          $option{encoding}
            ;
        $fd_encoding 
            = $family eq 'ornaments' ? 'U'
            : $family eq 'textcomp'  ? 'TS1'
            :                          uc $option{encoding}
            ;
            
        my $coding_scheme
            = $fd_encoding eq 'LY1'  ? ' --coding-scheme="TEX TYPEWRITER AND WINDOWS ANSI"'     
            : $fd_encoding eq 'T1'   ? ' --coding-scheme="EXTENDED TEX FONT ENCODING - LATIN"'  
            : $fd_encoding eq 'OT1'  ? ' --coding-scheme="TEX TEXT"'                            
            : $fd_encoding eq 'TS1'  ? ' --coding-scheme="TEX TEXT COMPANION SYMBOLS 1---TS1"'  
            :                          $EMPTY_STRING                                            
            ;

        # Construct NFSS code for this family
        $fd_family 
            = $FONTFAMILY 
            . (
                  $family eq 'lining'       ? 'X'
                : $family eq 'oldstyle'     ? 'J'
                : $family eq 'textcomp'     ? 'X'
                : $family eq 'superiors'    ? '1'
                : $family eq 'inferiors'    ? '0'
                : $family eq 'numerators'   ? '11'
                : $family eq 'denominators' ? '00'
                : $family eq 'ornaments'    ? 'P'
                :                             $EMPTY_STRING 
            )
            ;
        if ( $fd_family eq $FONTFAMILY ) {
            die "ERROR: you've just hit a bug in '$0'!\n",
                "Please send me a bug report and I'll try to fix it.\n";
        }

        
        SHAPE:
        for my $shape ( @{ $FD_SHAPE{$family} } ) {
        
            $fd_shape 
                = $fontattr{shape} eq 'Roman' ? $shape->{fd_n}
                :                               $shape->{fd_i}
                ;
            next SHAPE if !$fd_shape;
            
            # Get the required and optional features for this shape
            my (
                $all_required_features, 
                $one_required_features, 
                $optional_features
            ) = split m{ \| }xms, $shape->{feat}, 4;
            my @all_required_features 
                = split m{ \s+ }xms, $all_required_features;
            my @one_required_features 
                = split m{ \s+ }xms, $one_required_features;
            my @optional_features 
                = split m{ \s+ }xms, $optional_features;
            
            # Does the font support all required features?
            if ( grep { !$feature{$_} } @all_required_features
                or (
                    $one_required_features
                    and !grep { $feature{$_} } @one_required_features
                )
            ) 
            {
                next SHAPE;
            }
            
            # Construct the filename of the virtual font
            my $font 
                = "\U$encoding\E--$fontattr{name}--"
                . join( "-", @all_required_features )
                . '-'
                . ( $one_required_features 
                    ? ( grep { $feature{$_} } @one_required_features )[-1]
                    : $EMPTY_STRING
                )
                ;
            $font =~ s{ [-]{3,} }{--}xms;
            $font =~ s{ [-]+ \z }{ $EMPTY_STRING }xmse;

            # Create the command for otftotfm
            my $command
                = "otftotfm --encoding=$encoding"
                . ( $option{manual} ? ' --pl' : ' --automatic' )
                . " --map-file=$FONTFAMILY.map"
                . $coding_scheme
                . join( $EMPTY_STRING, 
                    map { " -f$_" } 
                        grep { $feature{$_} }
                             @all_required_features,
                             @one_required_features,
                             @optional_features
                  )
                . ( $shape->{extra} ? " $shape->{extra}" : $EMPTY_STRING )
                . ( $option{extra}  ? " $option{extra}"  : $EMPTY_STRING )
                . " $filename"
                . " $font"
                ;
            push @commands, $command;
                
            # Remember we've seen this family and shape
            $have_seen{family}{$family}  = 1;
            $have_seen{shape}{$fd_shape} = 1;



=begin Comment

    The info for the fd files is collected in two hashes:
    
    %fd         This is keyed by filename; it collects the contents of the
                various fd files. At this point in the program, this hash
                contains only the headers of the fd files; the rest is
                added later on.
            
    %fd_entry   This collects the info that will be used to generate the 
                entries in the fd files. Its keys are strings of the form
                '\DeclareFontShape{ENC}{Family}{series}{shape}'; the
                corresponding values are anonymous arrays of strings like
                'size-info fontname'. For fonts without multiple optical
                masters, this array will contain only one entry
                ('<-> fontname'); otherwise it will contain one entry
                for each optical master.

=end

=cut

            $fd{ $fd_encoding . $fd_family } ||=<<"END_FD_HEADER";
%% Generated by $0 on $today
%%
\\ProvidesFile{$fd_encoding$fd_family.fd}
    [$today Font definitions for $FONTFAMILY]

\\DeclareFontFamily{$fd_encoding}{$fd_family}{}

END_FD_HEADER

            $fd_key = "\\DeclareFontShape{$fd_encoding}{$fd_family}" . 
                  "{$fd_series}{$fd_shape}";
            $fd_val = "$fd_size\t$font";
            push @{ $fd_entry{ $fd_encoding . $fd_family }{$fd_key} }, 
                 $fd_val;


            # TS1 for ...J is the same as for ...X, so we just use 'ssub'
            if ( $family eq 'textcomp' ) {
                $fd_family = $FONTFAMILY . 'J';
                
                $fd{ $fd_encoding . $fd_family } ||=<<"END_FD_HEADER";
%% Generated by $0 on $today
%%
\\ProvidesFile{$fd_encoding$fd_family.fd}
    [$today Font definitions for $FONTFAMILY]

\\DeclareFontFamily{$fd_encoding}{$fd_family}{}

END_FD_HEADER

                $fd_key = "\\DeclareFontShape{$fd_encoding}{$fd_family}" . 
                          "{$fd_series}{$fd_shape}";
                $fd_val = "<-> ssub * ${FONTFAMILY}X/$fd_series/$fd_shape";

                @{ $fd_entry{ $fd_encoding . $fd_family }{$fd_key} }
                    = ( $fd_val );
            }

                     
            if ($option{verbose}) {
                printf "    %-40s   %4s/%s/%s/%s\n",
                    $font, $fd_encoding, $fd_family, $fd_series, $fd_shape;
            }
        }
    }
    
    if ($option{verbose}) { 
        print "\n", '-' x 76, "\n";
    }
}


if ( !$FONTFAMILY ) {
    exit;
}


# Generate the LaTeX style file
my $filename = "$FONTFAMILY.sty";
my $STYLE;
open $STYLE, ">", $filename
    or do {
        warn "WARNING: can't create '$filename' - $!\n",
             "Printing to <STDOUT> instead\n";
        $STYLE = *STDOUT;
    };
         
print $STYLE <<"END_STY_HEADER";
%% Generated by $0 on $today
%%
\\NeedsTeXFormat{LaTeX2e}
\\ProvidesPackage{$FONTFAMILY}
    [$today v1.0 Style file for $FONTFAMILY]

END_STY_HEADER

# Load fontenc and textcomp if necessary
if ( $option{encoding} ne "ot1" ) { 
    print $STYLE "\\RequirePackage[\U$option{encoding}\E]{fontenc}\n";
}
if ( $have_seen{family}{textcomp} ) { 
    print $STYLE "\\RequirePackage{textcomp}\n";
}

# Define options for families and series, and choose defaults
my $default_family = 'lining';
my $default_series = $EMPTY_STRING;
if ( $have_seen{family}{lining} ) {
    print $STYLE 
        "\\DeclareOption{lining}",
        "{\\renewcommand*{\\${LaTeX_family}default}{${FONTFAMILY}X}}\n"
        ;
}
if ( $have_seen{family}{oldstyle} ) {
    print $STYLE 
        "\\DeclareOption{oldstyle}",
        "{\\renewcommand*{\\${LaTeX_family}default}{${FONTFAMILY}J}}\n"
        ;
    $default_family = 'oldstyle';
}
print $STYLE "\\renewcommand*{\\familydefault}{\\${LaTeX_family}default}\n\n";

for my $series ( qw(Medium Black Demibold Semibold Bold) ) {
    if ( $have_seen{series}{ $FD_WEIGHT{$series} } ) {
        print $STYLE "\\DeclareOption{\L$series\E}",
                     "{\\renewcommand*{\\bfdefault}{$FD_WEIGHT{$series}}}\n";
        $default_series = ",\L$series\E";
    }
}
print $STYLE <<"END_STY_FOOTNOTE";

\\newif\\ifsups\@for\@footnotes
\\sups\@for\@footnotestrue
\\DeclareOption{normalfootnotes}{\\sups\@for\@footnotesfalse}

\\ExecuteOptions{$default_family$default_series}
\\ProcessOptions\\relax
END_STY_FOOTNOTE

print $STYLE <<"END_STY_LEHMAN";

% Definitions for easy access to various font styles and shapes,
% based on Philipp Lehman's 'nfssext.sty'.
% (We can't use that package directly: it needs the 'fontname' scheme.)

% '\\base\@family' tries to find the base name of the *current* font family,
% i.e. the family name minus the suffix ('J', 'X', etc.). Lehman has a
% macro '\\exfs\@get\@base' that does the same, but that depends on
% 'fontname' (more precisely: it assumes that the font family name consists
% of a three-letter base and a one-letter suffix).

\\ifx\\base\@family\\undefined
    \\let\\old\@base\@family\\familydefault
\\else
    \\let\\old\@base\@family\\base\@family
\\fi

\\def\\${FONTFAMILY}J{${FONTFAMILY}J}
\\def\\${FONTFAMILY}X{${FONTFAMILY}X}
\\def\\base\@family{%
    \\ifx\\f\@family\\${FONTFAMILY}J
        ${FONTFAMILY}%
    \\else
        \\ifx\\f\@family\\${FONTFAMILY}X
            ${FONTFAMILY}%
        \\else
            \\old\@base\@family
        \\fi
    \\fi}

\\def\\sidefault{si}
\\def\\swdefault{sw}
\\def\\tldefault{tl}
\\def\\tidefault{ti}

\\DeclareRobustCommand*{\\t\@mpa}{}
\\DeclareRobustCommand*{\\t\@mpb}{}
\\def\\choose\@shape#1#2#3{%
  \\edef\\t\@mpa{#1}%
  \\edef\\t\@mpb{#2}%
  \\ifx\\f\@shape\\t\@mpb
    \\expandafter
        \\ifx\\csname\\f\@encoding/\\f\@family/\\f\@series/#3\\endcsname\\relax
    \\else
      \\edef\\t\@mpa{#3}%
    \\fi
  \\fi
  \\fontshape{\\t\@mpa}\\selectfont}

\\DeclareRobustCommand{\\lnstyle}{%
    \\not\@math\@alphabet\\lnstyle\\relax
    \\fontfamily{\\base\@family X}\\selectfont}
\\DeclareTextFontCommand{\\textln}{\\lnstyle}

\\DeclareRobustCommand{\\osstyle}{%
    \\not\@math\@alphabet\\osstyle\\relax
    \\fontfamily{\\base\@family J}\\selectfont}
\\DeclareTextFontCommand{\\textos}{\\osstyle}

\\DeclareRobustCommand{\\sustyle}{%
    \\not\@math\@alphabet\\sustyle\\relax
    \\fontfamily{\\base\@family 1}\\selectfont}
\\DeclareTextFontCommand{\\textsu}{\\sustyle}

\\DeclareRobustCommand{\\instyle}{%
    \\not\@math\@alphabet\\instyle\\relax
    \\fontfamily{\\base\@family 0}\\selectfont}
\\DeclareTextFontCommand{\\textin}{\\instyle}

\\DeclareRobustCommand{\\upshape}{%
    \\not\@math\@alphabet\\upshape\\relax
    \\choose\@shape{\\updefault}{\\sidefault}{\\scdefault}}

\\DeclareRobustCommand{\\itshape}{%
    \\not\@math\@alphabet\\itshape\\relax
    \\choose\@shape{\\itdefault}{\\scdefault}{\\sidefault}}

\\DeclareRobustCommand{\\scshape}{%
    \\not\@math\@alphabet\\scshape\\relax
    \\choose\@shape{\\scdefault}{\\itdefault}{\\sidefault}}

\\DeclareRobustCommand{\\sishape}{%
    \\not\@math\@alphabet\\sishape\\relax
    \\fontshape{\\sidefault}\\selectfont}
\\DeclareTextFontCommand{\\textsi}{\\sishape}

\\DeclareRobustCommand{\\swshape}{%
    \\not\@math\@alphabet\\swshape\\relax
    \\fontshape{\\swdefault}\\selectfont}
\\DeclareTextFontCommand{\\textsw}{\\swshape}

\\DeclareRobustCommand{\\tlshape}{%
    \\not\@math\@alphabet\\tlshape\\relax
    \\fontshape{\\tldefault}\\selectfont}
\\DeclareTextFontCommand{\\texttl}{\\tlshape}

\\DeclareRobustCommand{\\tishape}{%
    \\not\@math\@alphabet\\tishape\\relax
    \\fontshape{\\tidefault}\\selectfont}
\\DeclareTextFontCommand{\\textti}{\\tishape}
END_STY_LEHMAN

# Set up footnote marks
if ( $have_seen{family}{superiors} ) {
    print $STYLE <<"END_STY_SUPERIORS";

% Redefine \\\@makefnmark to use real superior figures for footnote marks, 
% instead of scaled-down normal figures.
\\ifsups\@for\@footnotes
    \\renewcommand*{\\\@makefnmark}{{\\sustyle\\hbox{\\\@thefnmark}}}
\\fi
END_STY_SUPERIORS
}

# Set up fractions
if ( $have_seen{family}{numerators} && $have_seen{family}{denominators} ) {
    print $STYLE <<"END_STY_FRACTIONS";

% A simple interface for typesetting fractions.
% Takes two arguments: numerator and denominator.
\\def\\fraction#1#2{%
    {\\fontfamily{\\base\@family 11}\\selectfont #1}%
    \\textfractionsolidus
    {\\fontfamily{\\base\@family 00}\\selectfont #2}}
END_STY_FRACTIONS
}

# Set up ornaments
if ( $have_seen{family}{ornaments} ) {
    print $STYLE <<"END_STY_ORNAMENTS";

% A simple interface for accessing the ornaments. 
% Takes one argument: the number of the ornament to typeset.
\\def\\ornament#1{%
    {\\usefont{U}{\\base\@family P}{\\f\@series}{\\f\@shape}\\char #1}}
END_STY_ORNAMENTS
}

# Footer
print $STYLE <<"END_STY_FOOTER";
\\endinput
%%
%% End of file '$filename'
END_STY_FOOTER



=begin Comment

    Here we generate the fd files. The DeclareFontShape entries and the 
    size-info entries within each DeclareFontShape are sorted, and the
    size-info is fixed.
    
    This is done because in fonts with multiple optical masters, the
    size ranges look like this:

        <6-9>        AJensonPro-ItalicCapt
        <9.1-13.4>   AJensonPro-Italic
        <13.5-21.9>  AJensonPro-ItalicSubh
        <22-72>      AJensonPro-ItalicDisp

    The start of every range is replaced by the end of the previous one,
    and the end of the last range is replaced by an empty string, so
    these size ranges become <-9>, <9-13.4>, <13.4-21.9> and <21.9->.

    Also, if the font has multiple optical masters but some sizes are
    missing (usually because only the Text fonts are present ), the 
    size-infos for the remaining sizes are adjusted so that the font 
    can be used at all sizes.

=end

=cut

my $RE_START_SIZE_RANGE 
    = qr{
          (?<= < )          # The start of a size range is a (decimal)
          [\d.]+            # number, preceded by '<' and followed by a
          (?= - [\d.]* > )  # hyphen, another (decimal) number and '>'.
      }xms;

my $RE_END_SIZE_RANGE 
    = qr{
          (?<= - )          # The end of a size range is a either a (decimal)
          ( [\d.]* )        # number or an empty string, preceded by a hyphen
          (?= > )           # and followed by '>'.
      }xms;

# Don't generate a TS1 fd for the ...J family if that family doesn't exist
if ( !$fd{"\U$option{encoding}\E${FONTFAMILY}J"} ) { 
    delete $fd{"TS1${FONTFAMILY}J"};
}

for my $filename ( keys %fd ) {
    
    # Sort the DeclareFontShape entries
    for my $fd_fontshape ( sort compare_fd keys %{ $fd_entry{$filename} } ) {
    
        # Add the DeclareFontShape entry to the text of the fd file
        $fd{$filename} .= $fd_fontshape . '{';
        
        # Sort the size-infos for this DeclareFontShape entry
        my @size_infos 
            = sort compare_size @{ $fd_entry{$filename}->{$fd_fontshape} } ;
        
        # Fix the size ranges
        my $end_previous_range = $EMPTY_STRING;
        for my $size_info (@size_infos) {
            $size_info =~ s{ $RE_START_SIZE_RANGE }
                           { $end_previous_range  }xmse;
            ($end_previous_range)
                = $size_info =~ m{ $RE_END_SIZE_RANGE }xms;
        }
        $size_infos[-1] =~ s{ $RE_END_SIZE_RANGE }
                            { $EMPTY_STRING      }xmse;
        
        # Add the size-infos to the text of the fd file
        for my $size_info (@size_infos) {
            $fd{$filename} .=  "\n    $size_info";
        }
        $fd{$filename} .=  "\n}{}\n\n";
    }
    $fd{$filename} .=<<"END_FD_FOOTER";
\\endinput
%%
%% End of file '$filename.fd'
END_FD_FOOTER
    
    # Print the fd file
    my $FD;
    open $FD, '>', "$filename.fd"
        or do {
            warn "WARNING: can't create '$filename.fd' - $!\n",
                 "Printing to <STDOUT> instead\n";
            $FD = *STDOUT;
        };
    print $FD $fd{$filename};
}



# Execute or print the generated commands
if ($option{manual}) {
    my $filename = "$FONTFAMILY.bat";
    my $CMD;
    open $CMD, '>', "$filename"
        or do {
            warn "WARNING: can't create '$filename' - $!\n",
                 "Printing to <STDOUT> instead\n";
            $CMD = *STDOUT;
        };
    for my $command (@commands) {
        print $CMD "$command\n";
    }
}
else { 
    for my $command (@commands) {
        print  "$command\n"; 
        system "$command"; 
    }
}



__END__



=pod

=head1 NAME

autoinst - wrapper script around F<otftotfm>, for installing 
(PostScript-flavored) OpenType fonts.


=head1 SYNOPSIS

autoinst [options] I<fontfile> [I<fontfile> ...]


=head1 DESCRIPTION

Eddie Kohler's F<otftotfm> is a great tool for preparing OpenType fonts for 
use with LaTeX, but its use (even in automatic mode) is quite difficult
because it needs lots of long command lines and still requires
you to write the F<fd> and F<sty> files by hand. B<autoinst> simplifies using
F<otftotfm> by generating and executing all commands for F<otftotfm> 
and by generating all necessary F<fd> and F<sty> files. All you need to do 
is move these F<fd> and F<sty> files to a suitable location 
(C<< $LOCALTEXMF/tex/latex/<supplier>/<FontFamily>/ >> is usually a 
good choice) and update TeX's filename database.

Given one or more OpenType fonts,
B<autoinst> will create several LaTeX font families:

=over 2

=over 2

=item B<->

A text family with lining figures, containing (for each weight and width)
the following shapes:

=over 2

=over 4

=item I<n>

Roman (upright) text

=item I<sc>

Small caps

=item I<nw>

`Upright swash'; usually roman text with extra 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), with different letterspacing and positioning 
of hyphens, parentheses etc. 
This doesn't use the separate `titling' glyphs found in some fonts; 
these are best installed manually.

=item I<it>

Italic text

=item I<si>

Italic small caps

=item I<sw>

Normal (italic) swash

=item I<ti>

Italic titling

=back

=back

=item B<->

A text family with oldstyle figures; this contains the same shapes as the
text family with lining figures, except for the titling shape (there's no
point in using oldstyle figures with all-caps text).

=item B<->

For each text family: a family of TS1-encoded symbol fonts, 
in roman and italic shapes.

=item B<->

Two families with superior and inferior letters and figures, 
in roman and italic shapes.

=item B<->

Two families with numerators and denominators (for creating fractions), 
in roman and italic shapes.

=item B<->

An ornament family, in roman and italic shapes.

=back

=back

Of course, if your font doesn't contain oldstyle figures, small caps etc.,
the corresponding shapes or families are not created. 
Creation of the non-text families is controlled 
using command line options (see below).

The generated font families are named I<< <FontFamily><suffix> >>, 
where I<< <suffix> >> is one of

=over 4

=over 4

=item X

lining figures

=item J

oldstyle figures

=item 1

superior letters and figures

=item 0

inferior letters and figures

=item 11

numerators

=item 00

denominators

=back

=back

The generated fonts don't follow the `fontname' (a.k.a. `Berry') scheme, 
but are named more verbosely: I<< <ENC>--<FontFile>--<features> >>, where
I<< <ENC> >> is the encoding (e.g., `LY1'), I<< <FontFile> >> is the 
name of the OpenType file (minus the extension `.otf') and 
I<< <features> >> is a list of some of the OpenType features 
(just enough to make the filename unique) that were used to create this font. 
A typical name in this scheme is F<LY1 --MinionPro-Regular --onum --smcp>.

B<autoinst> fully supports font families with multiple optical sizes.


=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 (especially the so-called `Pro' ones) 
contain alternate characters or additional ligatures such as fj and Th, 
and LY1 has some empty slots to accommodate these.

A different encoding can be selected using the B< --encoding> option 
(see below).


=head2 Using the fonts with LaTeX

B<autoinst> generates a LaTeX style file for using the font in your documents, 
named `I<FontFamily>.sty'.
Using the font is as simple as putting the command C<\usepackage{MinionPro}> 
(or whatever your font is called) in the preamble of your document.

The generated style file defines a few options:

=over 4

=item I<lining>

Use lining figures for text.

=item I<oldstyle>

(Only if the font contains oldstyle figures.) Use oldstyle figures for text.

=item I<medium>

=item I<demibold>

=item I<semibold>

=item I<bold>

=item I<black>

(Only if the font family contains the corresponding weight.) Choose the
default weight that LaTeX will use when you ask for `bold'.

=item I<normalfootnotes>

Use the standard footnotes (don't redefine C<\@makefnmark> to use superior
figures).

=back

If the font contains oldstyle figures, these are used by default; you can
use the lining figures by explicitly specifying the I<lining> option. 
The style file also calls the F<fontenc> and F<textcomp> packages if 
necessary, and defines a number of declarations (which don't take arguments, 
but affect all text until the end of the current group) and 
commands (which only affect their--one--argument) for easy access to 
the various font styles and shapes:

  DECLARATION     COMMAND         EFFECT

  \lnstyle        \textln         Use lining figures
  \osstyle        \textos         Use oldstyle figures
  \sishape        \textsi         Use italic small caps
  \swshape        \textsw         Use italic swash
  \tlshape        \texttl         Use the (roman) titling font
  \tishape        \textti         Use the italic titling font
  \sustyle        \textsu         Use superior letters and figures
  \instyle        \textin         Use inferior letters and figures

Most of these definitions were taken verbatim from Philipp Lehman's 
F<nfssext.sty> (but we can't include that package directly, because it assumes 
that fonts are named using the `fontname' scheme).

There are no commands for accessing numerators and denominators;
these are only useful for creating fractions, 
so the style file provides a command 
C<<< \fraction{I<< <numerator> >>}{I<< <denominator> >>} >>> instead.

Ornaments are accessed using the C<<< \ornament{I<< <number> >>} >>> command,
where C<<< I<< <number> >> >>> is a number between 1 and the total number of 
ornaments. Ornaments are typeset in the current fontseries and -shape. 

If the font contains superior glyphs, the generated style file 
redefines C<\@makefnmark> so that the superior figures are used for 
footnote marks. These usually look better than scaled-down normal figures.
The style file option I<normalfootnotes> can be used to switch back to
normal footnote marks.


=head2 Caveat: using multiple font families in one document

When using several font families in one document, keep the following 
points in mind:

=over 2

=over 2

=item B<->

All fonts should use the same encoding;

=item B<->

Sanserif and typewriter fonts should be installed using the 
B< --sanserif> and B< --typewriter> options, respectively; 
otherwise the various style files will override each other's changes to
C<\rmdefault>;

=item B<->

The style file for the main text font should be loaded I<last>;

=item B<->

If some of the fonts don't contain superior figures, 
I<all> style files should be loaded using the I<normalfootnotes> option.

=back

=back

The generated style files try pretty hard to make sure that the 
above-mentioned commands and declarations (C<\lnstyle> I<et al>) 
use fonts from the correct family; but let me know if they fail.

There is no easy way to use several serif fonts (or several sanserif fonts, 
or several typewriter fonts) in the same document. As any good book on
typography will tell you, this is something you shouldn't do anyway,
so this limitation will probably not be a big problem.


=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 
MiKTeX (and probably other TeX-installations that implement their own directory
searching as well) F<otftotfm> complains that it 
cannot find a writable F<texmf> directory and leaves all generated F<tfm>, 
F<vf> and F<map> files in your current working directory. You should move 
these manually to their destinations. You'll also need to manually tell
F<dvips> and F<pdfTeX> about your new font map files.

Furthermore, some OpenType fonts lead to F<pl> and F<vpl> files that are too 
big for MiKTeX's implementation of F<pltotf> and F<vptovf>; the versions that 
come with TeXLive (F<http://tug.org/ftp/texlive/Contents/live/bin/win32/>) 
don't have this problem.


=head1 OPTIONS

You need only type as many characters as needed to make the option name unique.

=over 4

=item B< --encoding>=I<encoding>

Use the encoding I<encoding> for the text fonts. The default is `ly1'. 
A file named `I<encoding>.enc' should be somewhere where F<otftotfm> 
can find it. Suitable encoding files (named in all I<lowercase>) 
for LY1, T1 and TS1 come with the I<fontools> package. 

=item B< --sanserif>

Install the font family as a sanserif font; the font is accessed through
C<\sffamily> and C<\textsf> rather than C<\rmfamily> and C<\textrm>.
(The generated style file redefines C<\familydefault>, so including the
style file will still make this font the default text font.) This option
is mutually exclusive with the B< --typewriter> option.

=item B< --typewriter>

Install the font family as a typewriter font; the font is accessed through
C<\ttfamily> and C<\texttt> rather than C<\rmfamily> and C<\textrm>.
(The generated style file redefines C<\familydefault>, so including the
style file will still make this font the default text font.) This option
is mutually exclusive with the B< --sanserif> option.

=item B< --ts1>

=item B< --nots1>

Turn the creation of TS1-encoded fonts on or off. The default is B< --ts1> 
if the text encoding is T1, B< --nots1> otherwise.

=item B< --superiors>

=item B< --nosuperiors>

Turn the creation of fonts with superior characters on or off. 
The default is B< --superiors>.

=item B< --inferiors>

=item B< --noinferiors>

Turn the creation of fonts with inferior characters on or off. 
The default is B< --noinferiors>.

=item B< --ornaments>

=item B< --noornaments>

Turn the creation of ornament fonts on or off. The default is B< --ornaments>.

=item B< --fractions>

=item B< --nofractions>

Turn the creation of fonts with numerators and denominators on or off. 
The default is B< --nofractions>.

=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 batch command file (named `I<font>.bat', to make it
executable 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.

=item B< --verbose>

Verbose mode; print detailed info about what B<autoinst> thinks it's doing.

=item B< --extra>=I<text>

Pass I<text> as options to I<otftotfm>. To prevent I<text> from accidentily 
being interpreted as options to B<autoinst>, it's best to quote it.

=back


=head1 RESTRICTIONS

=over 2

=item B<->

B<autoinst> needs Perl (at least version 5.6) and the F<LCDF TypeTools>.

=item B<->

Each font's weight, shape and width are determined by parsing the filename. 
This supposes Adobe's naming scheme; 
it probably won't work with fonts from other vendors. 
Also, Adobe's naming scheme seems to vary slightly from font to font. 
B<autoinst> tries hard to make sense of the filenames 
and most font families will install without problems, but some families 
(mostly those with highly unusual weights or widths) will break it.
If that happens to you, send me a bug report and I'll try to fix it.

=item B<->

When choosing which shapes and families to build, B<autoinst> relies on
information in the font; when that information isn't accurate (e.g.,
CourierStd claims a `sups' feature but only contains superior variants of 
`one', `two' and `three'), you may need to edit the generated files by hand
to fix the problem.

=item B<->

B<autoinst> does a pretty good job of handling many standard font families; 
however, its one-size-fits-all approach is less well suited to more `exotic'
families such as Poetica, Silentium and Zapfino. For fonts like these, 
it's usually better to write the commands for F<otftotfm> by hand, or even
to convert the font to Type 1 format and use F<fontinst>.

=item B<->

You can't install fonts from more than one family at the same time.

=back


=head1 SEE ALSO

Eddie Kohler's LCDF TypeTools at F<http://www.lcdf.org/type>.

The other programs in the I<fontools> bundle: F<afm2afm>, F<cmap2enc>, 
F<font2afm>, F<ot2kpx>, F<pfm2kpx>, F<showglyphs>.

If B<autoinst> doesn't work for you, I recommend you take a look at John Owens' 
F<otftex_install.py> (to be found at 
F<http://www.ece.ucdavis.edu/~jowens/code/otftex_install/>). This 
represents a very different approach to wrapping F<otftotfm>, and may work in 
situations where B<autoinst> fails.


=head1 AUTHOR

Marc Penninga <marc@penninga.info>

If you're sending a bug report, please give as much information as possible,
including the output from running B<autoinst> with the B< --verbose> option.
Also be sure to mention the name I<fontools> somewhere in the subject line;
otherwise you might get caught by my spam filter.


=head1 COPYRIGHT

Copyright (c) 2005 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>.


=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<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 makes 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 
and some non-Adobe fonts;
added the B< --sanserif> and B< --typewriter> options and hacked the
style files to support using several different font families in one document;
and added the I<normalfootnotes> option to the style file.

=item I<2005-09-12>

Cleaned up the code (it now runs under the F<strict> and F<warnings> pragmas);
fixed a (rather obscure) obscure bug that occurred when creating TS1-encoded 
fonts for families with multiple optical masters and oldstyle figures;
added the numerator and denominator families and the C<\fraction> command;
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.

=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. 
Added F<nfssext.sty>-like commands to the generated style file.
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 
for OT1, T1, LY1 and user-specific encodings; extended the output generated by
the B< --verbose> option; and rewrote and extended the documentation.

=item I<2005-06-16>

Did some more finetuning to the filename-parsing code.

=item I<2005-05-31>

Generate correct fontname for OT1-encoded fonts.

=item I<2005-05-18>

Tried to make the filename-parsing code a bit more robust by adding several
weights and widths; changed the error that's displayed when filename parsing
fails; commented the code.

=item I<2005-04-29>

Rewrote large parts of the code (yes it I<was> even worse).

=item I<2005-04-18>

Changed default text-encoding to T1, added TS1.

=item I<2005-03-29>

Added support for font families with multiple widths.

=item I<2005-03-15>

First version.

=back

=cut
