texlive[50947] trunk: fontools (23apr19)

commits+karl at tug.org commits+karl at tug.org
Fri May 3 00:48:32 CEST 2019


Revision: 50947
          http://tug.org/svn/texlive?view=revision&revision=50947
Author:   karl
Date:     2019-05-03 00:48:32 +0200 (Fri, 03 May 2019)
Log Message:
-----------
fontools (23apr19)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst
    trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx
    trunk/Master/texmf-dist/doc/man/man1/afm2afm.1
    trunk/Master/texmf-dist/doc/man/man1/afm2afm.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/autoinst.1
    trunk/Master/texmf-dist/doc/man/man1/autoinst.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1
    trunk/Master/texmf-dist/doc/man/man1/ot2kpx.man1.pdf
    trunk/Master/texmf-dist/doc/support/fontools/README
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ly1.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ot1.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t1.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2a.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2b.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2c.enc
    trunk/Master/texmf-dist/scripts/fontools/autoinst
    trunk/Master/texmf-dist/scripts/fontools/ot2kpx

Modified: trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst	2019-05-02 22:48:32 UTC (rev 50947)
@@ -38,6 +38,7 @@
 use File::Spec ();
 use Getopt::Long ();
 use Pod::Usage ();
+use POSIX ();
 
 my ($d, $m, $y) = (localtime time)[3 .. 5];
 my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d;
@@ -66,7 +67,7 @@
 
 =begin Comment
 
-    Latex's NFSS contains a limited number of standard codes for weight and width:
+    LaTeX's NFSS contains a limited number of standard codes for weight and width:
     - weight: ul, el, l, sl, m, sb, b, eb, ub
     - width:  uc, ec, c, sc, m, sx, x, ex, ux
 
@@ -82,11 +83,11 @@
     2.  We add "ssub" rules to the .fd files that map the standard NFSS codes
         to actual fonts.
 
-    In step 1, we follow NFSS in leaving out any occurrence of the word "regular"
-    unless *both* weight and width are Regular; in that case, the series attribute
-    becomes "regular".
+    In step 1, we follow NFSS in leaving out any occurrence of
+    the word "regular" unless *both* weight and width are Regular;
+    in that case, the 'series' attribute becomes "regular".
 
-    The two tables %NFSS_WEIGHT and %NFSS_WIDTH are used to control step 2.
+    The two tables NFSS_WEIGHT and NFSS_WIDTH are used to control step 2.
     It contains several entries of the form
 
         sc  =>  [ qw( semicondensed narrow ) ],
@@ -94,12 +95,6 @@
     This should be read as follows: the NFSS code "sc" is mapped to the *first*
     width on the right hand side that is present in the current font family.
 
-    Given the lack of a standardised font naming scheme, this mapping system
-    will probably leave some fonts without matching NFSS codes and, vice versa,
-    some NFSS codes without matching font. It is, however, probably the best
-    that can be done in an automated way. If you think you can do better,
-    I welcome pull requests :-)
-
     Please note that the tables contain empty keys instead of "m" for
     the regular weight and width. NFSS actually combines weight and width
     into a single "series" attribute; a weight or width of "m" is left out of
@@ -112,8 +107,8 @@
     to be searched for.
 
     These tables can be extended to teach autoinst about new weights or widths.
-    Suppose your font family contains a "Hemibold" weight. Then simply add the name
-    "hemibold" to the right hand side of the "sb" entry in the %NFSS_WEIGHT
+    Suppose your font family contains a "Hemibold" weight. Then add the name
+    "hemibold" to the right hand side of the "sb" entry in the NFSS_WEIGHT
     table:
 
         sb  =>  [ qw( semibold demi demibold medium hemibold ) ],
@@ -124,9 +119,13 @@
     NFSS code).
 
     Note that autoinst converts all metadata to lowercase to avoid inconsistent
-    capitalization; hence all entries in these tables should be *lowercase* as well.
+    capitalization; so all entries in these tables should be *lowercase* as well.
 
+    Technical note:
+    We define NFSS_WEIGHT and NFSS_WIDTH first as arrays and then as hashtables;
+    this allows us to use the array-variants as an *ordered* list of keys.
 
+
     Finally, some random remarks about these tables:
     - Poster and Super aren't just "very heavy" weights; in most cases, they're
         more like separate designs. The same holds for the Compact width.
@@ -136,30 +135,31 @@
         mostly, however, it is a very light weight below Ultralight.
     - Semilight weights are virtually nonexistent, except for Thesis
         (which contains a Semilight weight) and Arnhem (which has Blond).
-    - Book is usually slightly lighter than Regular (and so could be mapped to "sl"),
-        but sometimes (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
+    - Book is usually slightly lighter than Regular, but sometimes
+        (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
     - Likewise, Medium can really be two different things:
         - a synonym for Semibold
         - (especially in newer fonts) an extra step between Regular and Semibold
         I treat it as if it's always the first.
     - Heavy can mean very different things; it's often heavier than Black,
-        but sometimes it's a synonym for Extrabold, and in some families (Futura)
-        it's even lighter than Bold. I treat it here as "very black".
+        but sometimes it's a synonym for Extrabold, and in Futura it's even
+        lighter than Bold. I treat it here as "very black".
     - Font families that have both Condensed and Compressed widths
         seem to define Compressed as narrower than Condensed.
-    - In Basic Sans (which is the only family I know with both Narrow and Condensed
-        fonts) Narrow is a bit wider than Condensed. So I mapped Narrow to "sc".
+    - In Basic Sans and Input (which are the only families I know with both
+        Narrow and Condensed), Narrow is a bit wider than Condensed.
+        So I mapped Narrow to "sc".
     - Extended and Expanded seem to be used interchangeably.
-    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts in the wild,
-        so the ex and ux entries are currently empty
+    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts,
+        so the ex and ux entries are currently empty.
 
 =end Comment
 
 =cut
 
-my %NFSS_WEIGHT = (
-    ul  =>  [ qw( ultralight hair hairline eight four two ) ],
-    el  =>  [ qw( extralight thin ) ],
+my @NFSS_WEIGHT = (
+    ul  =>  [ qw( ultralight thin hair hairline eight four two ) ],
+    el  =>  [ qw( extralight ) ],
     l   =>  [ qw( light ) ],
     sl  =>  [ qw( semilight blond ) ],
     ''  =>  [ qw( regular text book ) ],
@@ -169,8 +169,11 @@
     ub  =>  [ qw( ultrabold black heavy extrablack ultra ultrablack ultraheavy
                   poster super ) ],
 );
+my %NFSS_WEIGHT = @NFSS_WEIGHT;
+ at NFSS_WEIGHT = grep { !ref } @NFSS_WEIGHT;
+my @WEIGHTS = map { @{$_} } values %NFSS_WEIGHT;
 
-my %NFSS_WIDTH = (
+my @NFSS_WIDTH = (
     uc  =>  [ qw( ultracondensed extracompressed ultracompressed ) ],
     ec  =>  [ qw( extracondensed cmp comp compressed compact ) ],
     c   =>  [ qw( cond condensed ) ],
@@ -181,10 +184,13 @@
     ex  =>  [ ],
     ux  =>  [ ],
 );
+my %NFSS_WIDTH = @NFSS_WIDTH;
+ at NFSS_WIDTH = grep { !ref } @NFSS_WIDTH;
+my @WIDTHS = map { @{$_} } values %NFSS_WIDTH;
 
 =begin Comment
 
-    The %NFSS_SHAPE table maps various shape names to NFSS codes.
+    The NFSS_SHAPE table maps various shape names to NFSS codes.
 
     Note that this table works the other way around compared to
     the two previous tables; it directly maps shape names to NFSS codes.
@@ -195,7 +201,7 @@
     For shapes, that's not the case; font families don't have both Slanted and
     Oblique shapes, since these are just different names for the same thing.
 
-    Like in the other %NFSS_* tables, entries may be added to teach autoinst
+    Like in the other NFSS_* tables, entries may be added to teach autoinst
     about new shapes.
 
 =end Comment
@@ -202,7 +208,7 @@
 
 =cut
 
-my %NFSS_SHAPE = (
+my @NFSS_SHAPE = (
     roman       =>  'n',
     upright     =>  'n',
     italic      =>  'it',
@@ -215,14 +221,15 @@
     oblique     =>  'sl',
     slanted     =>  'sl',
     slant       =>  'sl',
-    romani      =>  'n',    # Adobe Silentium Pro has two roman shapes, but no italic;
+    romani      =>  'n',    # Silentium Pro has two roman shapes, but no italic;
     romanii     =>  'it',   # so we cheat by mapping the second roman shape to 'it'
 );
+my %NFSS_SHAPE = @NFSS_SHAPE;
 
 =begin Comment
 
     The %SHAPE table is used in deciding which font shapes
-    (normal, small caps, swash, titling or textcomp) to generate.
+    (normal, small caps, swash or textcomp) to generate.
 
     Each key in this table names a shape; the corresponding value
     is an anonymous hash with several key/value pairs:
@@ -271,18 +278,11 @@
     # comes last in the command line; else 'aalt' might be overridden
     swash => {
         code  => { n => 'nw', it => 'sw' },
-        reqd  => [ 'swsh', 'dlig' ],
-        nice  => [ 'kern', 'liga' ],
+        reqd  => [ 'swsh' ],
+        nice  => [ 'kern', 'liga', 'dlig' ],
         extra => '--include-alternates="*.swash" --feature=aalt',
         name  => 'swash',
     },
-    titling => {
-        code  => { n => 'tl', it => 'tlit', sl => 'tlsl' },
-        reqd  => [ 'titl', 'case', 'cpsp' ],
-        nice  => [ 'kern', 'liga' ],
-        extra => '',
-        name  => 'titling',
-    },
     textcomp => {
         code  => { n => 'n', it => 'it', sl => 'sl' },
         reqd  => [ ],
@@ -304,10 +304,8 @@
 my %SSUB_SHAPE = (
     sl      =>  'it',
     scsl    =>  'scit',
-    tlsl    =>  'tlit',
     it      =>  'sl',
     scit    =>  'scsl',
-    tlit    =>  'tlsl',
 );
 
 =begin Comment
@@ -344,13 +342,13 @@
         reqd   => [ ],
         nice   => [ ],
         extra  => '',
-        shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ],
+        shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ],
     },
     LF => {
         reqd   => [ ],
         nice   => [ ],
         extra  => '',
-        shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ],
+        shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ],
     },
     TOsF => {
         reqd   => [ ],
@@ -388,6 +386,12 @@
         extra  => '--ligkern="* {KL} *"',
         shapes => [ 'normal' ],
     },
+    Titl => {
+        reqd   => [ 'titl' ],
+        nice   => [ 'kern', 'liga' ],
+        extra  => '',
+        shapes => [ 'normal' ],
+    },
     Orn => {
         reqd   => [ 'ornm' ],
         nice   => [ ],
@@ -458,20 +462,8 @@
     # since this requires knowing which inferior figures this font supports;
     # so we have to do the font info parsing first.
     if ($ARGV{inferiors} eq 'auto') {
-        FONT:
-        for my $font (@fonts) {
-            for my $inf (qw(subs sinf dnom)) {
-                if (exists $font->{feature}{$inf}) {
-                    $ARGV{inferiors} = $inf;
-                    $STYLE{Inf}{reqd} = [$inf];
-                    last FONT;
-                }
-            }
-        }
+        Fontinfo::handle_auto_inferiors(@fonts);
     }
-    # If we didn't find any inferior figures, delete the 'Inf' entry
-    # frin the %STYLE table to indicate we don't want to generate this style.
-    delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto';
 
     # For each font, figure out the styles, shapes and encodings to generate
     my @worklist
@@ -492,6 +484,9 @@
              [ $minsize, $maxsize, $item->{fontname} ];
     }
 
+    # Decide to which weights and widths we'll map the standard NFSS codes
+    decide_nfss_mappings(@fonts);
+
     create_logfile(@worklist);
 
     if (!$ARGV{dryrun}) {
@@ -604,6 +599,19 @@
         my ($font, $style, $shape, $encoding)
             = @{$item}{qw(font style shape encoding)};
 
+        # make unique copy of fontdata, since we're modifying it;
+        # otherwise, the mergesmallcaps only works for
+        # the first encoding in the list
+        my %font = %$font;
+        $font = $item->{font} = \%font;
+
+        # handle fonts that put small caps fonts into separate family
+        if ($ARGV{mergesmallcaps}) {
+            if ($font->{family} =~ s/smallcaps$//xmsi) {
+                $shape = $item->{shape} = 'smallcaps';
+            }
+        }
+
         # generate unique name for this font
         $item->{fontname} = join '-', grep { $_ } $font->{name},
                                                   lc $style,
@@ -637,6 +645,55 @@
 }
 
 #-----------------------------------------------------------------------
+# Modify NFSS_WEIGHT and _WIDTH tables: pick one choice for each NFSS code
+#-----------------------------------------------------------------------
+sub decide_nfss_mappings {
+    my ( %weight, %width );
+    for my $font (@_) {
+        $weight{ $font->{weight} } = 1;
+        $width{ $font->{width} } = 1;
+    }
+
+    NFSSWEIGHT:
+    for my $nfssweight (@NFSS_WEIGHT) {
+        for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
+            if ( $weight{$weight} ) {
+                $NFSS_WEIGHT{$nfssweight} = [ $weight ];
+                next NFSSWEIGHT;
+            }
+        }
+        $NFSS_WEIGHT{$nfssweight} = [];
+    }
+    if ( !$ARGV{el} and !$ARGV{ul} ) {
+        if ( @{$NFSS_WEIGHT{ul}}
+                and $NFSS_WEIGHT{ul}[0] ne 'ultralight'
+                and !@{$NFSS_WEIGHT{el}} ) {
+            $NFSS_WEIGHT{el} = $NFSS_WEIGHT{ul};
+            $NFSS_WEIGHT{ul} = [];
+        }
+    }
+    if ( !$ARGV{eb} and !$ARGV{ub} ) {
+        if ( @{$NFSS_WEIGHT{ub}}
+                and $NFSS_WEIGHT{ub}[0] ne 'ultrabold'
+                and !@{$NFSS_WEIGHT{eb}} ) {
+            $NFSS_WEIGHT{eb} = $NFSS_WEIGHT{ub};
+            $NFSS_WEIGHT{ub} = [];
+        }
+    }
+
+    NFSSWIDTH:
+    for my $nfsswidth (@NFSS_WIDTH) {
+        for my $width ( @{$NFSS_WIDTH{$nfsswidth}} ) {
+            if ( $width{$width} ) {
+                $NFSS_WIDTH{$nfsswidth} = [ $width ];
+                next NFSSWIDTH;
+            }
+        }
+        $NFSS_WIDTH{$nfsswidth} = [];
+    }
+}
+
+#-----------------------------------------------------------------------
 # Dump all relevant info to the logfile
 #-----------------------------------------------------------------------
 sub create_logfile {
@@ -646,17 +703,28 @@
                     || $a->{style} cmp $b->{style}
                } @_;
 
-    open my $LOG, '>', $ARGV{logfile}
+    if (-e $ARGV{logfile}) {
+        print "[INFO]: file '$ARGV{logfile}' already exists;\n" .
+              "        appending new log data to end\n\n";
+    }
+    open my $LOG, '>>', $ARGV{logfile}
         or die "$0: cannot create $ARGV{logfile}: $!";
 
     print {$LOG} <<"END_ARGUMENTS";
 
-$ARGV{cmdline}
 
+############################################################################
 
-****************************************************************************
 
+@{[ POSIX::strftime("[%F %T]", localtime time) ]}  $0
 
+
+    "$ARGV{cmdline}"
+
+
+----------------------------------------------------------------------------
+
+
 I'm using the following options:
 
     encoding(s):        @{[ join ', ', @{$ARGV{encoding}} ]}
@@ -678,6 +746,7 @@
     inferiors:          $ARGV{inferiors}
     ornaments:          @{[ $ARGV{ornaments}    ? 'yes' : 'no' ]}
     fractions:          @{[ $ARGV{fractions}    ? 'yes' : 'no' ]}
+    ligatures:          @{[ $ARGV{ligatures}    ? 'yes' : 'no' ]}
 
     dry run/real:       @{[ $ARGV{dryrun}       ? 'dry run'   : 'real'   ]}
     auto/manual:        @{[ $ARGV{manual}       ? 'manual'    : 'auto'   ]}
@@ -684,8 +753,9 @@
     target:             $ARGV{target}
     extra:              @{[ $ARGV{extra} || '<empty>' ]}
 
-    figurekern:         @{[ $ARGV{figurekern}   ? 'no action' : 'remove' ]}
-    mergewidths:        @{[ $ARGV{mergewidths}  ? 'yes' : 'no' ]}
+    figurekern:         @{[ $ARGV{figurekern}       ? 'no action' : 'remove' ]}
+    mergewidths:        @{[ $ARGV{mergewidths}      ? 'yes' : 'no' ]}
+    mergesmallcaps:     @{[ $ARGV{mergesmallcaps}   ? 'yes' : 'no' ]}
 
 
     font files:
@@ -693,18 +763,29 @@
 
 END_ARGUMENTS
 
+    printf {$LOG} "\n" . '-' x 76 . "\n\n\nNFSS mappings:\n\n";
+    for my $weight (@NFSS_WEIGHT) {
+        printf {$LOG} "    %-3s =>  %s\n",
+                $weight || 'm', $NFSS_WEIGHT{$weight}[0] || '';
+    }
+    printf {$LOG} "\n";
+    for my $width (@NFSS_WIDTH) {
+        printf {$LOG} "    %-3s =>  %s\n",
+                $width || 'm', $NFSS_WIDTH{$width}[0] || '';
+    }
+    printf {$LOG} "\n";
+
+    return if $ARGV{verbose} < 1;
+
     my ($prevfn, $prevsty, $prevenc) = ('') x 3;
     my @cmds;
     for my $item (@worklist) {
         if ($prevfn ne $item->{font}{filename}) {
-            push @cmds, "\n" . '*' x 76;
             print {$LOG} <<"END_FONTINFO";
 
+    ------------------------------------------------------------------------
 
-****************************************************************************
-
-
-$item->{font}{filename}
+    $item->{font}{filename}
         Name:       $item->{font}{name}
         Family:     $item->{font}{family}
         Subfamily:  $item->{font}{subfamily}
@@ -715,10 +796,9 @@
         Features:   @{[ join ', ', sort keys %{$item->{font}{feature}} ]}
 
 
-Generating these encodings, figure styles and shapes:
+        Generating these encodings, figure styles and shapes:
 
-    ENC     STYLE   SHAPE   FEATURES USED
-    --------------------------------------------------------------------
+        ENC     STYLE   SHAPE   FEATURES USED
 END_FONTINFO
         }
         if ($prevenc ne $item->{encoding}[1]
@@ -725,7 +805,7 @@
             || $prevsty ne $item->{style}) {
             print {$LOG} "\n";
         }
-        printf {$LOG} "    %-3s     %-4s    %-4s    %s\n",
+        printf {$LOG} "        %-3s     %-4s    %-4s    %s\n",
                             $item->{encoding}[1],
                             $item->{style},
                             $item->{fdshape},
@@ -738,6 +818,7 @@
         push @cmds, $item->{cmdline};
     }
 
+    return if $ARGV{verbose} < 2;
     print {$LOG} join "\n\n", @cmds;
     print {$LOG} "\n";
     close $LOG;
@@ -799,13 +880,13 @@
                         ? qq(--coding-scheme="$SCHEME{$item->{encoding}[0]}")
                         : ''),
                      (map { "--feature=$_" } @{$item->{features}}),
-                     ((grep { $_ eq 'liga' } @{$item->{features}})
-                        ? ''
-                        : ( '--ligkern="f i =: fi"',
+                     ($ARGV{ligatures}
+                        ? ( '--ligkern="f i =: fi"',
                             '--ligkern="f l =: fl"',
                             '--ligkern="f f =: ff"',
                             '--ligkern="ff i =: ffi"',
-                            '--ligkern="ff l =: ffl"' )),
+                            '--ligkern="ff l =: ffl"' )
+                        : ''),
                      $STYLE{$item->{style}}{extra},
                      $SHAPE{$item->{shape}}{extra},
                      $ARGV{extra},
@@ -873,7 +954,9 @@
                             Use this style for subscripts (see docs)
     -(no)ornaments          Toggle creation of ornament fonts
     -(no)fractions          Toggle creation of fonts with digits for fractions
+    -(no)ligatures          Toggle manual addition of f-ligatures to font
 
+    -serif                  Install font as serif font
     -sanserif               Install font as sanserif font
     -typewriter             Install font as typewriter font
 
@@ -891,11 +974,17 @@
 
     -(no)figurekern         Keep or remove kerns between tabular figures
     -(no)mergewidths        Merge Condended/Extended subfamilies with main family
+    -(no)mergesmallcaps     Merge small caps subfamilies with main family
 
+    -nfssweight=xx=yyyy     Map the "xx" NFSS code to the "yyyy" weight
+    -nfsswidth=xx=yyyy      Map the "xx" NFSS code to the "yyyy" width
+
     -help                   Print this text and exit
     -doc                    Print the complete documentation and exit
     -dryrun                 Don't generate fonts, only log what would be done
-
+    -logfile="FILE"         Write log data to "FILE" (default: <fontfamily>.log)
+    -verbose                Print more data to log file
+                            (repeat for even higher verbosity)
     font[s]                 The fonts (.otf or .ttf format) to install.
 
 Please report any bugs or suggestions to <marcpenninga at gmail.com>.
@@ -903,32 +992,35 @@
 
 # Default values for the command-line arguments
 %ARGV = (
-    encoding     => 'OT1,T1,LY1',
-    textcomp     => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
-    lining       => '1',     # 0 = no, 1 = yes
-    oldstyle     => '1',     # 0 = no, 1 = yes
-    proportional => '1',     # 0 = no, 1 = yes
-    tabular      => '1',     # 0 = no, 1 = yes
-    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    => 'none',  # possible values: none, auto, subs, sinf, dnom
-    ornaments    => '1',     # 0 = no, 1 = yes
-    fractions    => '0',     # 0 = no, 1 = yes
-    nfss         => 'rm',
-    fig_height   => 'lnum',
-    fig_width    => 'tnum',
-    extra        => '',
-    target       => '',
-    vendor       => 'lcdftools',
-    typeface     => '',
-    updmap       => '1',     # 0 = no, 1 = yes
-    manual       => '0',     # 0 = no, 1 = yes
-    dryrun       => '0',     # 0 = no, 1 = yes
-    logfile      => 'autoinst.log',
-    figurekern   => '1',     # 0 = no, 1 = yes
-    mergewidths  => '0',     # 0 = no, 1 = yes
+    encoding        => 'OT1,T1,LY1',
+    textcomp        => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
+    lining          => '1',     # 0 = no, 1 = yes
+    oldstyle        => '1',     # 0 = no, 1 = yes
+    proportional    => '1',     # 0 = no, 1 = yes
+    tabular         => '1',     # 0 = no, 1 = yes
+    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       => 'none',  # possible values: none, auto, subs, sinf, dnom
+    ornaments       => '1',     # 0 = no, 1 = yes
+    fractions       => '0',     # 0 = no, 1 = yes
+    ligatures       => '0',     # 0 = no, 1 = yes
+    nfss            => 'rm',
+    fig_height      => 'lnum',
+    fig_width       => 'tnum',
+    extra           => '',
+    target          => '',
+    vendor          => 'lcdftools',
+    typeface        => '',
+    updmap          => '1',     # 0 = no, 1 = yes
+    manual          => '0',     # 0 = no, 1 = yes
+    dryrun          => '0',     # 0 = no, 1 = yes
+    logfile         => '',
+    figurekern      => '1',     # 0 = no, 1 = yes
+    mergewidths     => '1',     # 0 = no, 1 = yes
+    mergesmallcaps  => '1',     # 0 = no, 1 = yes
+    verbose         => 0,
 );
 
 #-----------------------------------------------------------------------
@@ -953,6 +1045,8 @@
         'inferiors=s'         => \$ARGV{inferiors},
         'ornaments!'          => \$ARGV{ornaments},
         'fractions!'          => \$ARGV{fractions},
+        'ligatures!'          => \$ARGV{ligatures},
+        'serif'               =>  sub { $ARGV{nfss} = 'rm' },
         'sanserif'            =>  sub { $ARGV{nfss} = 'sf' },
         'typewriter'          =>  sub { $ARGV{nfss} = 'tt' },
         'defaultlining'       =>  sub { $ARGV{fig_height} = 'lnum' },
@@ -968,7 +1062,21 @@
         'manual'              => \$ARGV{manual},
         'figurekern!'         => \$ARGV{figurekern},
         'mergewidths!'        => \$ARGV{mergewidths},
-        'verbose+'            => sub {},
+        'mergesmallcaps!'     => \$ARGV{mergesmallcaps},
+        'logfile=s'           => \$ARGV{logfile},
+        'verbose+'            => \$ARGV{verbose},
+        'nfssweight=s%'       => sub {
+                                     my ( $ignored, $key, $values ) = @_;
+                                     my @values = split m/,/, lc $values;
+                                     $NFSS_WEIGHT{$key} = \@values;
+                                     $ARGV{$key} = 'user-defined';
+                                 },
+        'nfsswidth=s%'        => sub {
+                                     my ( $ignored, $key, $values ) = @_;
+                                     my @values = split m/,/, lc $values;
+                                     $NFSS_WIDTH{$key} = \@values;
+                                     $ARGV{$key} = 'user-defined';
+                                 },
     )
     or die "$USAGE";
 
@@ -976,8 +1084,8 @@
 
     delete $SHAPE{smallcaps}     unless $ARGV{smallcaps};
     delete $SHAPE{swash}         unless $ARGV{swash};
-    delete $SHAPE{titling}       unless $ARGV{titling};
 
+    delete $STYLE{Titl}          unless $ARGV{titling};
     delete $STYLE{Sup}           unless $ARGV{superiors};
     delete $STYLE{Orn}           unless $ARGV{ornaments};
     delete @STYLE{qw(Numr Dnom)} unless $ARGV{fractions};
@@ -1138,13 +1246,13 @@
     # 1.  Search for matching widths before matching weights
     #     (as none of the widths is a proper substring of some weight)
     # 2.  Remove any recognised search string from the 'fullinfo'
-    for my $width ( mqrs( map { @{$_} } values %NFSS_WIDTH ) ) {
+    for my $width ( mqrs(@WIDTHS) ) {
         if ($fullinfo =~ s/${width}//gxmsi) {
             $info->{width} = $width;
             last;
         }
     }
-    for my $weight ( mqrs( map { @{$_} } values %NFSS_WEIGHT ) ) {
+    for my $weight ( mqrs(@WEIGHTS) ) {
         if ($fullinfo =~ s/${weight}//gxmsi) {
             $info->{weight} = $weight;
             last;
@@ -1169,10 +1277,13 @@
     $info->{family}    = $data{family};
     $info->{subfamily} = $data{subfamily};
 
+    if ( !$ARGV{logfile} ) {
+        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
+    }
     # Some font families put condensed or extended widths into separate families;
     # we provide an option to merge these with the 'main' font family.
     if ($ARGV{mergewidths}) {
-        my $widths = join '|', mqrs( map { @{$_} } values %NFSS_WIDTH );
+        my $widths = join '|', mqrs(@WIDTHS);
         if ($info->{width} eq 'regular'
             && $info->{family} =~ m/(.+?) [ ]* (${widths})$/xmsi)
         {
@@ -1197,13 +1308,13 @@
 
     # We define 'series' as 'weight + width'. This matches NFSS, but contradicts
     # how most fonts are named (which is 'width + weight').
-    $info->{series} 
+    $info->{series}
         = ($info->{width} eq 'regular')  ? $info->{weight}
         : ($info->{weight} eq 'regular') ? $info->{width}
         :                                  $info->{weight} . $info->{width}
         ;
 
-    return $info;
+    return;
 }
 
 #-----------------------------------------------------------------------
@@ -1234,7 +1345,7 @@
     $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
     close $otfinfo;
 
-    return $info;
+    return;
 }
 
 #-----------------------------------------------------------------------
@@ -1279,7 +1390,7 @@
     }
     close $otfinfo;
 
-    return $info;
+    return;
 }
 
 
@@ -1304,7 +1415,7 @@
         -   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
-            '%NFSS_WIDTH', '%NFSS_WEIGHT' or '%NFSS_SHAPE' near the top
+            'NFSS_WIDTH', 'NFSS_WEIGHT' or 'NFSS_SHAPE' near the top
             of the source code;
 
         Please also send a bug report to the author.
@@ -1382,7 +1493,27 @@
     return $enc_name;
 }
 
+#-----------------------------------------------------------------------
+# Handle the -inferiors=auto option
+#-----------------------------------------------------------------------
+sub handle_auto_inferiors {
+    FONT:
+    for my $font (@_) {
+        for my $inf (qw(subs sinf dnom)) {
+            if (exists $font->{feature}{$inf}) {
+                $ARGV{inferiors} = $inf;
+                $STYLE{Inf}{reqd} = [$inf];
+                last FONT;
+            }
+        }
+    }
 
+    # If we didn't find any inferior figures, delete the 'Inf' entry
+    # from the %STYLE table to indicate we don't want to generate this style.
+    delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto';
+}
+
+
 ############################################################################
 
 
@@ -1389,7 +1520,7 @@
 package LaTeX;
 
 #-----------------------------------------------------------------------
-# Create a Latex style file
+# Create a LaTeX style file
 #-----------------------------------------------------------------------
 sub write_stylefile {
     my ($fam, $data) = @_;
@@ -1423,20 +1554,7 @@
     \RequirePackage{fontaxes}
 END_STY_FONTAXES_START
 
-        if ($seen{tl} or $seen{tlit}) {
-        print {$STY} <<'END_STY_FONTAXES_TL';
-    \providecommand{\tldefault}{tl}
-    \DeclareRobustCommand\tlshape{\not at math@alphabet\tlshape\relax
-        \fontsecondaryshape\tldefault\selectfont}
-    \DeclareTextFontCommand{\texttl}{\tlshape}
-    \let\texttitling\texttl
-    \fa at naming@exception{shape}{{n}{tl}}{tl}
-    \fa at naming@exception{shape}{{it}{tl}}{tlit}
-    \fa at naming@exception{shape}{{sl}{tl}}{tlsl}
 
-END_STY_FONTAXES_TL
-    }
-
     if ($seen{nw} or $seen{sw}) {
         print {$STY} <<'END_STY_FONTAXES_SW';
     \DeclareRobustCommand\swshape{\not at math@alphabet\swshape\relax
@@ -1471,6 +1589,18 @@
 END_STY_FONTAXES_INF
     }
 
+    if ($seen{Titl}) {
+        print {$STY} <<'END_STY_FONTAXES_TITL';
+    \fa at naming@exception{figures}{{titlingshape}{proportional}}{Titl}
+    \fa at naming@exception{figures}{{titlingshape}{tabular}}{Titl}
+    \def\tlshape{\@nomath\tlshape
+        \fontfigurestyle{titlingshape}\selectfont}
+    \DeclareTextFontCommand{\texttl}{\tlshape}
+    \let\texttitling\texttl
+
+END_STY_FONTAXES_TITL
+    }
+
     if ($seen{Orn}) {
         print {$STY} <<'END_STY_FONTAXES_ORN';
     \fa at naming@exception{figures}{{ornament}{proportional}}{Orn}
@@ -1540,8 +1670,7 @@
         :               die "[ERROR] Internal bug, please report!";
 
     my $default_bold;
-    for my $series (qw(heavy black extrabold demibold semibold bold))
-    {
+    for my $series (qw(heavy black extrabold demibold semibold bold)) {
         if ( $seen{$series} ) {
             print {$STY}
                 "\\DeclareOptionX{$series}{\\edef\\bfseries\@$ARGV{nfss}",
@@ -1655,14 +1784,14 @@
 
     print {$FD} <<"END_COMMENT";
 %
-%   ====  Extra 'ssub' rules to map the standard NFSS codes to our fancy names  ====
+%  Extra 'ssub' rules to map the standard NFSS codes to our fancy names
 %
 END_COMMENT
     my %seen;
     NFSSWEIGHT:
-    for my $nfssweight (keys %NFSS_WEIGHT) {
+    for my $nfssweight (@NFSS_WEIGHT) {
         NFSSWIDTH:
-        for my $nfsswidth (keys %NFSS_WIDTH) {
+        for my $nfsswidth (@NFSS_WIDTH) {
             my $nfssseries = ( $nfssweight . $nfsswidth) || 'm';
 
             for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
@@ -1732,7 +1861,7 @@
 =head1 NAME
 
 autoinst - wrapper around the F<LCDF TypeTools>,
-for installing and using OpenType fonts in (La)TeX.
+for installing and using OpenType fonts in LaTeX.
 
 
 =head1 SYNOPSIS
@@ -1778,29 +1907,17 @@
 
 Small caps
 
-=item I<sw>
-
-Swash
-
-=item I<tl>
-
-Titling shape. Meant for all-caps text; letterspacing and the positioning of
-punctuation characters have been adjusted to suit all-caps text.
-(This shape is only generated for the families with lining digits,
-since old-style digits make no sense with all-caps text.)
-
 =item I<scit>, I<scsl>
 
 Italic and slanted small caps
 
-=item I<nw>
+=item I<sw>
 
-"Upright swash"; usually roman text with a few "oldstyle" ligatures
-like ct, sp and st.
+Swash
 
-=item I<tlit>, I<tlsl>
+=item I<nw>
 
-Italic and slanted titling text
+"Upright swash"
 
 =back
 
@@ -1818,6 +1935,14 @@
 
 =item -
 
+Families with "Titling" characters; these "... replace the default glyphs
+with corresponding forms designed specifically for titling.
+These may be all-capital and/or larger on the body,
+and adjusted for viewing at larger sizes"
+(according to the OpenType Specification).
+
+=item -
+
 An ornament family, also in roman, italic and slanted shapes.
 
 =back
@@ -1861,6 +1986,10 @@
 inferior characters; usually only digits and some punctuation,
 normal forms for other characters
 
+=item I<Titl>
+
+Titling characters; see above.
+
 =item I<Orn>
 
 ornaments
@@ -1877,11 +2006,22 @@
 
 The individual 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",
+I<< <shape> >> is either empty, "sc" or "swash",
 and I<< <enc> >> is the encoding (also in lowercase).
 A typical name in this scheme would be "FiraSans-Light-osf-sc-ly1".
 
 
+=head2 About the log file
+
+B<autoinst> writes some info about what it thinks it's doing to a log file.
+By default this is called F<< <fontfamily>.log >>,
+but this choice can be overridden by the user;
+see the I<-logfile> command-line option in L</"COMMAND-LINE OPTIONS"> below.
+If this log file already exists, B<autoinst> will append its data to the end
+rather than overwrite it.
+Use the I<-verbose> command-line option to ask for more detailed info.
+
+
 =head2 A note for MiKTeX users
 
 Automatically installing the fonts into a suitable TEXMF tree
@@ -2014,31 +2154,36 @@
 
 =head2 NFSS codes
 
-I<< B<CAVEAT>: this functionality was almost completely rewritten in release 2019-03-14.
+I<< B<CAVEAT>: this functionality was almost completely rewritten
+in release 2019-03-14.
 Older versions tried to map all fonts directly to short NFSS codes,
 but often had to invent non-standard codes in order to deal with the
 many different weights and widths that occur in the wild.
-These non-standard NFSS codes used by older versions of B<autoinst> will no longer
+Such non-standard NFSS codes will no longer
 work for fonts installed with newer versions; for those you'll have to either
 use the long names or stick to the standard NFSS codes.
-This change mainly concerns very light or very heavy weights and very condensed widths;
-for more moderate weights and widths, existing code will very probably continue to work.
+(This change mainly concerns very light or very heavy weights
+and very condensed widths;
+for more moderate weights and widths,
+existing code will very probably continue to work.)
 >>
 
 LaTeX's New Font Selection System (NFSS)
 identifies fonts by a combination of family,
 series (the concatenation of weight and width), shape and size.
-B<autoinst> parses the font's metadata (more precisely: the output of C<otfinfo --info>)
+B<autoinst> parses the font's metadata
+(more precisely: the output of C<otfinfo --info>)
 to determine these parameters.
-When this fails (usually because the font family contains uncommon weights, widths
-or shapes),
+When this fails (usually because the font family contains uncommon weights,
+widths or shapes),
 B<autoinst> ends up with different fonts having the I<same> values
 for these font parameters; such fonts cannot be used in NFSS,
 since there's no way distinguish them.
-When B<autoinst> detects such a situation, it will print an error message and abort.
+When B<autoinst> detects such a situation, it will print an error message
+and abort.
 If that happens, either rerun B<autoinst> on a smaller set of fonts,
-or add the missing widths, weights and shapes to the tables C<%NFSS_WIDTH>,
-C<%NFSS_WEIGHT> and C<%NFSS_SHAPE>, near the top of the source code.
+or add the missing widths, weights and shapes to the tables C<NFSS_WIDTH>,
+C<NFSS_WEIGHT> and C<NFSS_SHAPE>, near the top of the source code.
 Please also send a bug report (see L<AUTHOR> below).
 
 The mapping of shapes to NFSS codes is done using the following table:
@@ -2049,58 +2194,44 @@
     Italic, Cursive, Kursive            it
     Oblique, Slant(ed), Incline(d)      sl
 
-(I<Exception:> Adobe Silentium Pro contains two Roman shapes; we map the first of these
-to "n", for the second one we [ab]use the "it" code as this family doesn't contain
-an Italic shape.)
+(I<Exception:> Adobe Silentium Pro contains two Roman shapes;
+we map the first of these to "n", for the second one we (ab)use the "it" code
+as this family doesn't contain an Italic shape.)
 
-The mapping of weights and widths to NFSS code is a more complex, two-step proces.
+The mapping of weights and widths to NFSS codes is a more complex,
+two-step proces.
 In the first step, all fonts are assigned a "series" name that is simply
-the concatenation of its full weight and width (after expanding any abbreviations
-and converting to lowercase).
-So a font with "Cond" width and "Ultra" weight will be known as "ultrablackcondensed".
+the concatenation of its weight and width
+(after expanding any abbreviations and converting to lowercase).
+A font with "Cond" width and "Ultra" weight will then be known
+as "ultrablackcondensed".
 
 In the second step, B<autoinst> tries to map all combinations of NFSS codes
 (ul, el, l, sl, m, sb, b, eb and ub for weights;
 uc, ec, c, sc, m, sx, x, ex and ux for widths) to actual fonts.
-Of course, not all 81 combinations of these NFSS weights and widths will map to
-existing fonts; and conversely it may not be possible to assign every existing font
+Of course, not all 81 combinations of these NFSS weights and widths will map
+to existing fonts;
+and conversely it may not be possible to assign every existing font
 a unique code in a sane way (especially on the weight axis, some font families
 offer more choices or finer granularity than NFSS's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional "Medium" weight between Regular and Semibold).
 
-This mapping between NFSS codes and actual fonts is based on a few principles:
+B<autoinst> tries hard to ensure that the most common NFSS codes
+(and high-level commands such as C<\bfseries>,
+which are built on top of those codes) will "just work".
 
-=over 4
+To see exactly which NFSS codes map to which fonts, see the log file
+(pro tip: run B<autoinst> with the I<-dryrun> option
+to check the chosen mapping beforehand).
+The I<-nfssweight> and I<-nfsswidth> command-line options can be used
+to finetune the mapping between NFSS codes and fonts.
 
-=item B<Usefulness>. As many of the most commonly used NFSS codes as possible
-should point to actual fonts.
+To access specific weights or widths,
+one can always use the C<\fontseries> command with the full series name
+(i.e., C<\fontseries{demibold}\selectfont>).
 
-=item B<Exactness>. Exact matches always win: if the font family contains
-a Semibold Condensed font, that's what the "sbc" code will map to.
 
-=item B<Sanity>. A code like "sb" will always map to something semi-boldish.
-If there's no Semibold font it might map to Demibold or Medium,
-but never to Black. If there is no close match, the NFSS code will simply not be used.
-
-=item B<Well-ordering>. The mapping respects the ordering that is inherent in
-the NFSS codes, so "sb" will be heavier than "m" and lighter than "b".
-
-=item B<Uniqueness>. No two NFSS codes will map to the same font (with the exception
-of "bx"; since this is so ubiquitous in Latex, B<autoinst> will treat it as a synonym
-for "b" if there is no BoldExtended font).
-
-=back
-
-These rules should ensure that the standard NFSS codes (and high-level commands
-such as C<\bfseries>, which are built on top of these codes) will "just work".
-To access specific weights or widths, use the C<\fontseries> command with
-the full series name (i.e., C<\fontseries{demibold}\selectfont>).
-
-To see exactly which NFSS codes map to which fonts, please refer to
-the generated F<fd> files.
-
-
 =head1 COMMAND-LINE OPTIONS
 
 B<autoinst> tries hard to do The Right Thing (TM) by default,
@@ -2117,15 +2248,26 @@
 
 =item B<-dryrun>
 
-Don't generate any output files; only parse the input fonts and create
-F<autoinst.log> showing which fonts would have been generated.
+Don't generate output; just parse input fonts and write
+a log file saying what it would have done.
 
+=item B<-logfile>=I<filename>
+
+Write log data to F<filename> instead of the default F<< <fontfamily>.log >>.
+If the file already exist, B<autoinst> appends to it;
+it doesn't overwrite an existing file.
+
+=item B<-verbose>
+
+Add more details to the log file. Repeat this option for even more info.
+
 =item B<-encoding>=I<encoding[,encoding]>
 
-Generate the specified encoding(s) for the text fonts. Multiple text encodings may be
-specified as a comma-separated list: C<-encoding=OT1,T1,LY1> (without spaces!).
-The generated style file passes these encodings to F<fontenc> in the specified order,
-so the last one will become the default text encoding for your document.
+Generate the specified encoding(s) for the text fonts.
+Multiple encodings may be specified as a comma-separated list:
+C<-encoding=OT1,T1,LY1> (without spaces!).
+The style file passes these to F<fontenc> in the specified order,
+so the I<last> one will become the default text encoding of your document.
 
 The default choice of encodings is "OT1,T1,LY1".
 For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>!)
@@ -2140,19 +2282,14 @@
 if the text encodings (see I<-encoding> above) include T1,
 B<-nots1> otherwise.
 
-=item B<-sanserif>
+=item B<-serif>, B<-sanserif>, B<-typewriter>
 
-Install the font as a sanserif font, accessed via C<\sffamily> and C<\textsf>.
+Install the font as a serif, sanserif or typewriter font, respectively.
+This changes how you access the font in LaTeX: with C<\rmfamily>/C<\textrm>,
+C<\sffamily>/C<\textsf> or C<\ttfamily>/C<\texttt>.
 The generated style file redefines C<\familydefault>,
 so including it will still make this font the default text font.
 
-=item B<-typewriter>
-
-Install the font as a typewriter font, accessed via C<\ttfamily> and
-C<\texttt>.
-The generated style file redefines C<\familydefault>,
-so including it will still make this font the default text font.
-
 =item B<-lining> / B<-nolining>
 
 Control the creation of fonts with lining figures. The default is
@@ -2184,7 +2321,7 @@
 
 =item B<-titling> / B<-notitling>
 
-Control the creation of titling fonts. The default is B<-titling>.
+Control the creation of titling families. The default is B<-titling>.
 
 =item B<-superiors> / B<-nosuperiors>
 
@@ -2202,10 +2339,9 @@
 in the list "subs", "sinf" or "dnom" that is supported by the fonts.
 The default value is "none".
 
-I<< Note that if you specify a style of inferiors that isn't
-present in the font, B<autoinst> silently falls back to its default behaviour
-of not creating fonts with inferiors; it doesn't try to substitute one of
-the other features. >>
+I<< If you specify a style of inferiors that isn't present in the font,
+B<autoinst> will fall back to its default behaviour of not creating fonts
+with inferiors at all; it won't try to substitute one of the other styles. >>
 
 =item B<-fractions> / B<-nofractions>
 
@@ -2212,9 +2348,15 @@
 Control the creation of fonts with numerators and denominators.
 The default is B<-nofractions>.
 
-=item B<-ornaments> / B<-noornaments>
+=item B<-ligatures> / B<-noligatures>
 
-Control the creation of ornament fonts. The default is B<-ornaments>.
+Some fonts create glyphs for the standard f-ligatures (ff, fi, fl, ffi, ffl),
+but don't provide a "liga" feature to access these.
+This option tells B<autoinst> to add extra C<LIGKERN> rules to
+the generated fonts to enable the use of these ligatures.
+Since this option is rarely necessary
+(most fonts with f-ligatures do provide the matching "liga" feature),
+the default is B<-noligatures>.
 
 =item B<-defaultlining> / B<-defaultoldstyle>
 
@@ -2241,10 +2383,29 @@
 
 =item B<-mergewidths> / B<-nomergewidths>
 
-Some font families put Condensed, Narrow, Extended etc. fonts in separate families;
-this option tells B<autoinst> to merge those separate families into the main family.
-The default is B<-nomergewidths>.
+Some font families put their Condensed, Narrow, Extended etc. widths
+in separate families;
+this option tells B<autoinst> to merge those separate families into
+the main family.
+The default is B<-mergewidths>.
 
+=item B<-mergesmallcaps> / B<-nomergesmallcaps>
+
+Even more annoyingly, some font families put their small caps fonts
+in a separate family;
+this option tells B<autoinst> to merge the small caps fonts into
+the main family.
+The default is B<-mergesmallcaps>.
+
+=item B<-nfssweight>=I<code>=I<weight>, B<-nfsswidth>=I<code>=I<width>
+
+Map the NFSS code I<code> to the given weight or width,
+overriding the built-in tables.
+Each of these options may be given multiple times,
+to override more than one NFSS code.
+Example: to map the "ul" code to the "Thin" weight, use C<-nfssweight=ul=thin>.
+To inhibit the use of the "ul" code completely, use C<-nfssweight=ul=>.
+
 =item B<-extra>=I<text>
 
 Append I<text> as extra options to the command lines for I<otftotfm>.
@@ -2254,7 +2415,8 @@
 =item B<-manual>
 
 Manual mode; for users who want to post-process the generated files and commands.
-By default, B<autoinst> immediately executes all F<otftotfm> commands it generates;
+By default, B<autoinst> immediately executes all F<otftotfm> commands
+it generates;
 in manual mode, these are instead written to a file F<autoinst.bat>.
 Furthermore it tells F<otftotfm> to generate human readable (and editable)
 F<pl/vpl> files instead of the default F<tfm/vf> ones,
@@ -2272,7 +2434,8 @@
 =item B<-> move all generated files to a proper TEXMF tree,
 and, if necessary, update the filename database;
 
-=item B<-> tell TeX about the new F<map> file (usually by running C<updmap> or similar).
+=item B<-> tell TeX about the new F<map> file
+(usually by running C<updmap> or similar).
 
 =back
 
@@ -2334,11 +2497,11 @@
 
 Marc Penninga (F<marcpenninga at gmail.com>)
 
-When sending a bug report, please give as much relevant information as
-possible.
-If you see any error messages
-(whether from B<autoinst> itself, from the I<LCDF TypeTools>, from Perl
-or from the OS), include these I<verbatim>; don't paraphrase.
+When sending a bug report, please give as much relevant information as possible;
+this usually includes (but may not be limited to) the log file
+(please add the I<-verbose> command-line option, for extra info).
+If you see any error messages, please include these I<verbatim>;
+don't paraphase.
 
 
 =head1 COPYRIGHT
@@ -2371,6 +2534,31 @@
 
 =over 12
 
+=item I<2019-04-22>
+
+Fixed a bug in the generation of swash shapes.
+
+=item I<2019-04-19>
+
+Fixed a bug that affected -mergesmallcaps with multiple encodings.
+
+=item I<2019-04-16>
+
+Added the <-mergesmallcaps> option, to handle cases where
+the small caps fonts are in separate font families.
+Titling shape is now treated as a separate family instead of a distinct shape;
+it is generated only for fonts with the 'titl' feature.
+Only add f-ligatures to fonts when explicitly asked to (<-fligatures>).
+
+=item I<2019-04-11>
+
+Tried to make the log file more relevant.
+Added the I<-nfssweight> and I<-nfsswidth> options,
+and finetuned the automatic mapping between fonts and NFSS codes.
+Changed the name of the generated log file to F<< <fontfamily>.log >>,
+and revived the I<-logfile> option to allow overriding this choice.
+Made I<-mergewidths> the default (instead of I<-nomergewidths>).
+
 =item I<2019-04-01>
 
 Fine-tuned the decision where to put generated files;
@@ -2381,16 +2569,20 @@
 put all generated files into a subdirectory C<./autoinst_output/>
 instead of all over the current working directory.
 
-Added to "auto" value to the I<inferiors> option,
+Added "auto" value to the I<inferiors> option,
 to tell B<autoinst> to use whatever inferior characters are available.
 
-=item I<2019-03-14> (never released to CTAN)
+=item I<2019-03-14>
 
+(never released to CTAN)
+
 Overhauled the mapping of fonts (more specifically of weights and widths;
-the mapping of shapes didn't change) to NFSS codes. Instead of inventing our own codes
-to deal with every possible weight and width out there, we now create "long" codes
-based on the names in the font metadata. Then we add "ssub" rules to the F<fd>
-files to map the standard NFSS codes to our fancy names (see the section B<NFSS codes>;
+the mapping of shapes didn't change) to NFSS codes.
+Instead of inventing our own codes to deal with every possible weight
+and width out there, we now create "long" codes based on the names
+in the font metadata.
+Then we add "ssub" rules to the F<fd> files to map the standard NFSS codes
+to our fancy names (see the section B<NFSS codes>;
 based on discussions with Frank Mittelbach and Bob Tennent).
 
 =item I<2018-08-10>
@@ -2433,7 +2625,7 @@
 
 =item I<2015-11-22>
 
-Bugfix: Latex doesn't like command names with dashes in it.
+Bugfix: LaTeX doesn't like command names with dashes in it.
 
 =item I<2015-05-13>
 

Modified: trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx	2019-05-02 22:48:32 UTC (rev 50947)
@@ -4,7 +4,7 @@
 
 ----------------------------------------------------------------------------
 
-    Copyright (C) 2005-2013 Marc Penninga.
+    Copyright (C) 2005-2019 Marc Penninga.
 
     This program is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
@@ -34,12 +34,24 @@
 use warnings;
 
 use integer;
+use Getopt::Long ();
 use List::Util @List::Util::EXPORT_OK;
 use Pod::Usage;
 
-our ($NUM_GLYPHS, $UNITS_PER_EM, %KPX);
+our ($NUM_GLYPHS, $UNITS_PER_EM, %kern);
 
 sub main {
+    %ARGV = (
+        print_func  =>  \&print_kpx,
+    );
+
+    Getopt::Long::GetOptions(
+        'help|?'    =>  sub { pod2usage(-verbose => 0); },
+        'doc'       =>  sub { pod2usage(-verbose => 2); },
+        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx; },
+        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx; },
+        'lua'       =>  sub { $ARGV{print_func} = \&print_lua; },
+    ) or pod2usage(-verbose => 0);
     pod2usage(-verbose => 0) if @ARGV != 1;
 
     my %font = OTF::get_tables($ARGV[0]);
@@ -65,7 +77,7 @@
 
         for my $subtable (@subtables) {
             my $pos_format = unpack 'n', $subtable;
-            if ($pos_format == 1) { 
+            if ($pos_format == 1) {
                 OTF::GPOS::parse_pos_format_1($subtable);
             }
             elsif ($pos_format == 2) {
@@ -77,21 +89,57 @@
         }
     }
 
-    my $num_kernpairs = sum map { scalar keys %{$KPX{$_}} } keys %KPX;
+    &{$ARGV{print_func}}( \%kern, \@glyph_name );
+    return;
+}
+
+# ------------------------------------------------------------------------
+# Print kerning data in Adobe's KPX format
+# ------------------------------------------------------------------------
+sub print_kpx {
+    my %kern = %{ shift @_; };
+    my @glyph = @{ shift @_; };
+
+    my $num_kernpairs = sum map { scalar keys %{$kern{$_}} } keys %kern;
     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";
+    for my $l (sort { $glyph[$a] cmp $glyph[$b] } keys %kern) {
+        my $l_glyph = $glyph[$l];
+        for my $r (sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}}) {
+            print "KPX $l_glyph $glyph[$r] ",
+                  "$kern{$l}{$r}\n";
         }
     }
     print "EndKernPairs\nEndKernData\n";
+}
 
-    return;
+# ------------------------------------------------------------------------
+# Print kerning data as a Luatex custom font feature
+# ------------------------------------------------------------------------
+sub print_lua {
+    my %kern = %{ shift @_; };
+    my @glyph = @{ shift @_; };
+
+    print <<'END_FEATURE_PREFIX';
+fonts.handlers.otf.addfeature {
+    name = 'kern',
+    type = 'kern',
+    data = {
+END_FEATURE_PREFIX
+
+    for my $l ( sort { $glyph[$a] cmp $glyph[$b] } keys %kern ) {
+        print ' ' x 8, "[ '$glyph[$l]' ] = {";
+        for my $r ( sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}} ) {
+            print "\n", ' ' x 12, "[ '$glyph[$r]' ] = $kern{$l}{$r},";
+        }
+        print " },\n";
+    }
+
+    print <<'END_FEATURE_POSTFIX';
+    }
 }
+END_FEATURE_POSTFIX
+}
 
-
 ########################################################################
 
 
@@ -467,7 +515,7 @@
 }
 
 #-----------------------------------------------------------------------
-# Parse subtable in PairPosFormat 1, store kern pairs in global %KPX
+# Parse subtable in PairPosFormat 1, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_pos_format_1 {
     my $subtable = shift;
@@ -495,7 +543,7 @@
             my ($second, $value)
                 = unpack "n\@${value_offset}s>", $pair_value_record;
             next if $value == 0;
-            $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
+            $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
         }
     }
 
@@ -503,7 +551,7 @@
 }
 
 #-----------------------------------------------------------------------
-# Parse subtable in PairPosFormat 2, store kern pairs in global %KPX
+# Parse subtable in PairPosFormat 2, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_pos_format_2 {
     my $subtable = shift;
@@ -540,7 +588,7 @@
 
             for my $first (@first) {
                 for my $second (@second) {
-                    $KPX{$first}{$second} ||= $value;
+                    $kern{$first}{$second} ||= $value;
                 }
             }
         }
@@ -631,7 +679,7 @@
 package OTF::Kern;
 
 #-----------------------------------------------------------------------
-# Parse "kern"table, store kern pairs in global %KPX
+# Parse "kern"table, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_kerntable {
     my $kern = shift;
@@ -653,7 +701,7 @@
             my ($first, $second, $value) = unpack 'nns>', $kern_pair;
             next if $value == 0;
 
-            $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
+            $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
         }
     }
 
@@ -688,19 +736,14 @@
 
 =head1 SYNOPSIS
 
-=over 8
+B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<fontfile>
 
-=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>.
+B<ot2kpx> extract the kerning data from OpenType fonts and prints it
+to C<stdout>, either in Adobe's KPX format (for adding to an F<afm> file)
+or as a Luatex custom feature, for use with the C<\directlua> command.
 
 
 =head1 OPTIONS AND ARGUMENTS
@@ -707,9 +750,19 @@
 
 =over 4
 
+=item B<-afm>, B<-kpx>
+
+Output the kerning data in Adobe's KPX format, as used in F<afm> files.
+This is the default output format.
+
+=item B<-lua>
+
+Output the kerning data as a Luatex custom font feature,
+to be included in a C<\directlua> command.
+
 =item B<fontfile>
 
-The OpenType font (in either F<otf> or F<ttf> format).
+The OpenType font (both F<otf> and F<ttf> format are supported).
 
 =back
 
@@ -771,7 +824,7 @@
 
 =head1 COPYRIGHT
 
-Copyright (C) 2005-2013 Marc Penninga.
+Copyright (C) 2005-2019 Marc Penninga.
 
 
 =head1 LICENSE
@@ -798,6 +851,11 @@
 
 =over 12
 
+=item I<2019-04-15>
+
+Added the -lua command-line option to get output in Luatex's
+custom feature format.
+
 =item I<2013-08-07>
 
 Replaced all C<given/when> constructions in the source code by C<if>'s,

Modified: trunk/Master/texmf-dist/doc/man/man1/afm2afm.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/afm2afm.1	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/doc/man/man1/afm2afm.1	2019-05-02 22:48:32 UTC (rev 50947)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "AFM2AFM 1"
-.TH AFM2AFM 1 "2019-03-14" "fontools" "Marc Penninga"
+.TH AFM2AFM 1 "2013-08-07" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l

Modified: trunk/Master/texmf-dist/doc/man/man1/afm2afm.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/man/man1/autoinst.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/autoinst.1	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/doc/man/man1/autoinst.1	2019-05-02 22:48:32 UTC (rev 50947)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "AUTOINST 1"
-.TH AUTOINST 1 "2019-04-01" "fontools" "Marc Penninga"
+.TH AUTOINST 1 "2019-04-22" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -140,7 +140,7 @@
 .nh
 .SH "NAME"
 autoinst \- wrapper around the LCDF TypeTools,
-for installing and using OpenType fonts in (La)TeX.
+for installing and using OpenType fonts in LaTeX.
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBautoinst\fR [\fIoptions\fR] \fBfontfile(s)\fR
@@ -171,25 +171,15 @@
 .IP "\fIsc\fR" 8
 .IX Item "sc"
 Small caps
+.IP "\fIscit\fR, \fIscsl\fR" 8
+.IX Item "scit, scsl"
+Italic and slanted small caps
 .IP "\fIsw\fR" 8
 .IX Item "sw"
 Swash
-.IP "\fItl\fR" 8
-.IX Item "tl"
-Titling shape. Meant for all-caps text; letterspacing and the positioning of
-punctuation characters have been adjusted to suit all-caps text.
-(This shape is only generated for the families with lining digits,
-since old-style digits make no sense with all-caps text.)
-.IP "\fIscit\fR, \fIscsl\fR" 8
-.IX Item "scit, scsl"
-Italic and slanted small caps
 .IP "\fInw\fR" 8
 .IX Item "nw"
-\&\*(L"Upright swash\*(R"; usually roman text with a few \*(L"oldstyle\*(R" ligatures
-like ct, sp and st.
-.IP "\fItlit\fR, \fItlsl\fR" 8
-.IX Item "tlit, tlsl"
-Italic and slanted titling text
+\&\*(L"Upright swash\*(R"
 .RE
 .RS 2
 .RE
@@ -203,6 +193,12 @@
 Families with superiors, inferiors, numerators and denominators,
 in roman, italic and slanted shapes.
 .IP "\-" 3
+Families with \*(L"Titling\*(R" characters; these \*(L"... replace the default glyphs
+with corresponding forms designed specifically for titling.
+These may be all-capital and/or larger on the body,
+and adjusted for viewing at larger sizes\*(R"
+(according to the OpenType Specification).
+.IP "\-" 3
 An ornament family, also in roman, italic and slanted shapes.
 .RE
 .RS 2
@@ -236,6 +232,9 @@
 .IX Item "Inf"
 inferior characters; usually only digits and some punctuation,
 normal forms for other characters
+.IP "\fITitl\fR" 8
+.IX Item "Titl"
+Titling characters; see above.
 .IP "\fIOrn\fR" 8
 .IX Item "Orn"
 ornaments
@@ -248,9 +247,18 @@
 .PP
 The individual fonts are named \fI<FontName>\-<suffix>\-<shape>\-<enc>\fR,
 where \fI<suffix>\fR is the same as above (but in lowercase),
-\&\fI<shape>\fR is either empty, \*(L"sc\*(R", \*(L"swash\*(R" or \*(L"titling\*(R",
+\&\fI<shape>\fR is either empty, \*(L"sc\*(R" or \*(L"swash\*(R",
 and \fI<enc>\fR is the encoding (also in lowercase).
 A typical name in this scheme would be \*(L"FiraSans\-Light\-osf\-sc\-ly1\*(R".
+.SS "About the log file"
+.IX Subsection "About the log file"
+\&\fBautoinst\fR writes some info about what it thinks it's doing to a log file.
+By default this is called \fI<fontfamily>.log\fR,
+but this choice can be overridden by the user;
+see the \fI\-logfile\fR command-line option in \*(L"COMMAND-LINE \s-1OPTIONS\*(R"\s0 below.
+If this log file already exists, \fBautoinst\fR will append its data to the end
+rather than overwrite it.
+Use the \fI\-verbose\fR command-line option to ask for more detailed info.
 .SS "A note for MiKTeX users"
 .IX Subsection "A note for MiKTeX users"
 Automatically installing the fonts into a suitable \s-1TEXMF\s0 tree
@@ -371,30 +379,35 @@
 (see \*(L"COMMAND-LINE \s-1OPTIONS\*(R"\s0 below).
 .SS "\s-1NFSS\s0 codes"
 .IX Subsection "NFSS codes"
-\&\fI\f(BI\s-1CAVEAT\s0\fI: this functionality was almost completely rewritten in release 2019\-03\-14.
+\&\fI\f(BI\s-1CAVEAT\s0\fI: this functionality was almost completely rewritten
+in release 2019\-03\-14.
 Older versions tried to map all fonts directly to short \s-1NFSS\s0 codes,
 but often had to invent non-standard codes in order to deal with the
 many different weights and widths that occur in the wild.
-These non-standard \s-1NFSS\s0 codes used by older versions of \f(BIautoinst\fI will no longer
+Such non-standard \s-1NFSS\s0 codes will no longer
 work for fonts installed with newer versions; for those you'll have to either
 use the long names or stick to the standard \s-1NFSS\s0 codes.
-This change mainly concerns very light or very heavy weights and very condensed widths;
-for more moderate weights and widths, existing code will very probably continue to work.\fR
+(This change mainly concerns very light or very heavy weights
+and very condensed widths;
+for more moderate weights and widths,
+existing code will very probably continue to work.)\fR
 .PP
 LaTeX's New Font Selection System (\s-1NFSS\s0)
 identifies fonts by a combination of family,
 series (the concatenation of weight and width), shape and size.
-\&\fBautoinst\fR parses the font's metadata (more precisely: the output of \f(CW\*(C`otfinfo \-\-info\*(C'\fR)
+\&\fBautoinst\fR parses the font's metadata
+(more precisely: the output of \f(CW\*(C`otfinfo \-\-info\*(C'\fR)
 to determine these parameters.
-When this fails (usually because the font family contains uncommon weights, widths
-or shapes),
+When this fails (usually because the font family contains uncommon weights,
+widths or shapes),
 \&\fBautoinst\fR ends up with different fonts having the \fIsame\fR values
 for these font parameters; such fonts cannot be used in \s-1NFSS,\s0
 since there's no way distinguish them.
-When \fBautoinst\fR detects such a situation, it will print an error message and abort.
+When \fBautoinst\fR detects such a situation, it will print an error message
+and abort.
 If that happens, either rerun \fBautoinst\fR on a smaller set of fonts,
-or add the missing widths, weights and shapes to the tables \f(CW%NFSS_WIDTH\fR,
-\&\f(CW%NFSS_WEIGHT\fR and \f(CW%NFSS_SHAPE\fR, near the top of the source code.
+or add the missing widths, weights and shapes to the tables \f(CW\*(C`NFSS_WIDTH\*(C'\fR,
+\&\f(CW\*(C`NFSS_WEIGHT\*(C'\fR and \f(CW\*(C`NFSS_SHAPE\*(C'\fR, near the top of the source code.
 Please also send a bug report (see \s-1AUTHOR\s0 below).
 .PP
 The mapping of shapes to \s-1NFSS\s0 codes is done using the following table:
@@ -407,51 +420,42 @@
 \&    Oblique, Slant(ed), Incline(d)      sl
 .Ve
 .PP
-(\fIException:\fR Adobe Silentium Pro contains two Roman shapes; we map the first of these
-to \*(L"n\*(R", for the second one we [ab]use the \*(L"it\*(R" code as this family doesn't contain
-an Italic shape.)
+(\fIException:\fR Adobe Silentium Pro contains two Roman shapes;
+we map the first of these to \*(L"n\*(R", for the second one we (ab)use the \*(L"it\*(R" code
+as this family doesn't contain an Italic shape.)
 .PP
-The mapping of weights and widths to \s-1NFSS\s0 code is a more complex, two-step proces.
+The mapping of weights and widths to \s-1NFSS\s0 codes is a more complex,
+two-step proces.
 In the first step, all fonts are assigned a \*(L"series\*(R" name that is simply
-the concatenation of its full weight and width (after expanding any abbreviations
-and converting to lowercase).
-So a font with \*(L"Cond\*(R" width and \*(L"Ultra\*(R" weight will be known as \*(L"ultrablackcondensed\*(R".
+the concatenation of its weight and width
+(after expanding any abbreviations and converting to lowercase).
+A font with \*(L"Cond\*(R" width and \*(L"Ultra\*(R" weight will then be known
+as \*(L"ultrablackcondensed\*(R".
 .PP
 In the second step, \fBautoinst\fR tries to map all combinations of \s-1NFSS\s0 codes
 (ul, el, l, sl, m, sb, b, eb and ub for weights;
 uc, ec, c, sc, m, sx, x, ex and ux for widths) to actual fonts.
-Of course, not all 81 combinations of these \s-1NFSS\s0 weights and widths will map to
-existing fonts; and conversely it may not be possible to assign every existing font
+Of course, not all 81 combinations of these \s-1NFSS\s0 weights and widths will map
+to existing fonts;
+and conversely it may not be possible to assign every existing font
 a unique code in a sane way (especially on the weight axis, some font families
 offer more choices or finer granularity than \s-1NFSS\s0's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional \*(L"Medium\*(R" weight between Regular and Semibold).
 .PP
-This mapping between \s-1NFSS\s0 codes and actual fonts is based on a few principles:
-.IP "\fBUsefulness\fR. As many of the most commonly used \s-1NFSS\s0 codes as possible should point to actual fonts." 4
-.IX Item "Usefulness. As many of the most commonly used NFSS codes as possible should point to actual fonts."
-.PD 0
-.ie n .IP "\fBExactness\fR. Exact matches always win: if the font family contains a Semibold Condensed font, that's what the ""sbc"" code will map to." 4
-.el .IP "\fBExactness\fR. Exact matches always win: if the font family contains a Semibold Condensed font, that's what the ``sbc'' code will map to." 4
-.IX Item "Exactness. Exact matches always win: if the font family contains a Semibold Condensed font, that's what the sbc code will map to."
-.ie n .IP "\fBSanity\fR. A code like ""sb"" will always map to something semi-boldish. If there's no Semibold font it might map to Demibold or Medium, but never to Black. If there is no close match, the \s-1NFSS\s0 code will simply not be used." 4
-.el .IP "\fBSanity\fR. A code like ``sb'' will always map to something semi-boldish. If there's no Semibold font it might map to Demibold or Medium, but never to Black. If there is no close match, the \s-1NFSS\s0 code will simply not be used." 4
-.IX Item "Sanity. A code like sb will always map to something semi-boldish. If there's no Semibold font it might map to Demibold or Medium, but never to Black. If there is no close match, the NFSS code will simply not be used."
-.ie n .IP "\fBWell-ordering\fR. The mapping respects the ordering that is inherent in the \s-1NFSS\s0 codes, so ""sb"" will be heavier than ""m"" and lighter than ""b""." 4
-.el .IP "\fBWell-ordering\fR. The mapping respects the ordering that is inherent in the \s-1NFSS\s0 codes, so ``sb'' will be heavier than ``m'' and lighter than ``b''." 4
-.IX Item "Well-ordering. The mapping respects the ordering that is inherent in the NFSS codes, so sb will be heavier than m and lighter than b."
-.ie n .IP "\fBUniqueness\fR. No two \s-1NFSS\s0 codes will map to the same font (with the exception of ""bx""; since this is so ubiquitous in Latex, \fBautoinst\fR will treat it as a synonym for ""b"" if there is no BoldExtended font)." 4
-.el .IP "\fBUniqueness\fR. No two \s-1NFSS\s0 codes will map to the same font (with the exception of ``bx''; since this is so ubiquitous in Latex, \fBautoinst\fR will treat it as a synonym for ``b'' if there is no BoldExtended font)." 4
-.IX Item "Uniqueness. No two NFSS codes will map to the same font (with the exception of bx; since this is so ubiquitous in Latex, autoinst will treat it as a synonym for b if there is no BoldExtended font)."
-.PD
+\&\fBautoinst\fR tries hard to ensure that the most common \s-1NFSS\s0 codes
+(and high-level commands such as \f(CW\*(C`\ebfseries\*(C'\fR,
+which are built on top of those codes) will \*(L"just work\*(R".
 .PP
-These rules should ensure that the standard \s-1NFSS\s0 codes (and high-level commands
-such as \f(CW\*(C`\ebfseries\*(C'\fR, which are built on top of these codes) will \*(L"just work\*(R".
-To access specific weights or widths, use the \f(CW\*(C`\efontseries\*(C'\fR command with
-the full series name (i.e., \f(CW\*(C`\efontseries{demibold}\eselectfont\*(C'\fR).
+To see exactly which \s-1NFSS\s0 codes map to which fonts, see the log file
+(pro tip: run \fBautoinst\fR with the \fI\-dryrun\fR option
+to check the chosen mapping beforehand).
+The \fI\-nfssweight\fR and \fI\-nfsswidth\fR command-line options can be used
+to finetune the mapping between \s-1NFSS\s0 codes and fonts.
 .PP
-To see exactly which \s-1NFSS\s0 codes map to which fonts, please refer to
-the generated \fIfd\fR files.
+To access specific weights or widths,
+one can always use the \f(CW\*(C`\efontseries\*(C'\fR command with the full series name
+(i.e., \f(CW\*(C`\efontseries{demibold}\eselectfont\*(C'\fR).
 .SH "COMMAND-LINE OPTIONS"
 .IX Header "COMMAND-LINE OPTIONS"
 \&\fBautoinst\fR tries hard to do The Right Thing (\s-1TM\s0) by default,
@@ -464,14 +468,23 @@
 but \fB\-e\fR is ambiguous (it may mean either \fB\-encoding\fR or \fB\-extra\fR)).
 .IP "\fB\-dryrun\fR" 4
 .IX Item "-dryrun"
-Don't generate any output files; only parse the input fonts and create
-\&\fIautoinst.log\fR showing which fonts would have been generated.
+Don't generate output; just parse input fonts and write
+a log file saying what it would have done.
+.IP "\fB\-logfile\fR=\fIfilename\fR" 4
+.IX Item "-logfile=filename"
+Write log data to \fIfilename\fR instead of the default \fI<fontfamily>.log\fR.
+If the file already exist, \fBautoinst\fR appends to it;
+it doesn't overwrite an existing file.
+.IP "\fB\-verbose\fR" 4
+.IX Item "-verbose"
+Add more details to the log file. Repeat this option for even more info.
 .IP "\fB\-encoding\fR=\fIencoding[,encoding]\fR" 4
 .IX Item "-encoding=encoding[,encoding]"
-Generate the specified encoding(s) for the text fonts. Multiple text encodings may be
-specified as a comma-separated list: \f(CW\*(C`\-encoding=OT1,T1,LY1\*(C'\fR (without spaces!).
-The generated style file passes these encodings to \fIfontenc\fR in the specified order,
-so the last one will become the default text encoding for your document.
+Generate the specified encoding(s) for the text fonts.
+Multiple encodings may be specified as a comma-separated list:
+\&\f(CW\*(C`\-encoding=OT1,T1,LY1\*(C'\fR (without spaces!).
+The style file passes these to \fIfontenc\fR in the specified order,
+so the \fIlast\fR one will become the default text encoding of your document.
 .Sp
 The default choice of encodings is \*(L"\s-1OT1,T1,LY1\*(R".\s0
 For each encoding, a file \fI<encoding>.enc\fR (in all \fIlowercase\fR!)
@@ -484,17 +497,13 @@
 Control the creation of TS1\-encoded fonts. The default is \fB\-ts1\fR
 if the text encodings (see \fI\-encoding\fR above) include T1,
 \&\fB\-nots1\fR otherwise.
-.IP "\fB\-sanserif\fR" 4
-.IX Item "-sanserif"
-Install the font as a sanserif font, accessed via \f(CW\*(C`\esffamily\*(C'\fR and \f(CW\*(C`\etextsf\*(C'\fR.
+.IP "\fB\-serif\fR, \fB\-sanserif\fR, \fB\-typewriter\fR" 4
+.IX Item "-serif, -sanserif, -typewriter"
+Install the font as a serif, sanserif or typewriter font, respectively.
+This changes how you access the font in LaTeX: with \f(CW\*(C`\ermfamily\*(C'\fR/\f(CW\*(C`\etextrm\*(C'\fR,
+\&\f(CW\*(C`\esffamily\*(C'\fR/\f(CW\*(C`\etextsf\*(C'\fR or \f(CW\*(C`\ettfamily\*(C'\fR/\f(CW\*(C`\etexttt\*(C'\fR.
 The generated style file redefines \f(CW\*(C`\efamilydefault\*(C'\fR,
 so including it will still make this font the default text font.
-.IP "\fB\-typewriter\fR" 4
-.IX Item "-typewriter"
-Install the font as a typewriter font, accessed via \f(CW\*(C`\ettfamily\*(C'\fR and
-\&\f(CW\*(C`\etexttt\*(C'\fR.
-The generated style file redefines \f(CW\*(C`\efamilydefault\*(C'\fR,
-so including it will still make this font the default text font.
 .IP "\fB\-lining\fR / \fB\-nolining\fR" 4
 .IX Item "-lining / -nolining"
 Control the creation of fonts with lining figures. The default is
@@ -520,7 +529,7 @@
 Control the creation of swash fonts. The default is \fB\-swash\fR.
 .IP "\fB\-titling\fR / \fB\-notitling\fR" 4
 .IX Item "-titling / -notitling"
-Control the creation of titling fonts. The default is \fB\-titling\fR.
+Control the creation of titling families. The default is \fB\-titling\fR.
 .IP "\fB\-superiors\fR / \fB\-nosuperiors\fR" 4
 .IX Item "-superiors / -nosuperiors"
 Control the creation of fonts with superior characters.
@@ -536,17 +545,22 @@
 in the list \*(L"subs\*(R", \*(L"sinf\*(R" or \*(L"dnom\*(R" that is supported by the fonts.
 The default value is \*(L"none\*(R".
 .Sp
-\&\fINote that if you specify a style of inferiors that isn't
-present in the font, \f(BIautoinst\fI silently falls back to its default behaviour
-of not creating fonts with inferiors; it doesn't try to substitute one of
-the other features.\fR
+\&\fIIf you specify a style of inferiors that isn't present in the font,
+\&\f(BIautoinst\fI will fall back to its default behaviour of not creating fonts
+with inferiors at all; it won't try to substitute one of the other styles.\fR
 .IP "\fB\-fractions\fR / \fB\-nofractions\fR" 4
 .IX Item "-fractions / -nofractions"
 Control the creation of fonts with numerators and denominators.
 The default is \fB\-nofractions\fR.
-.IP "\fB\-ornaments\fR / \fB\-noornaments\fR" 4
-.IX Item "-ornaments / -noornaments"
-Control the creation of ornament fonts. The default is \fB\-ornaments\fR.
+.IP "\fB\-ligatures\fR / \fB\-noligatures\fR" 4
+.IX Item "-ligatures / -noligatures"
+Some fonts create glyphs for the standard f\-ligatures (ff, fi, fl, ffi, ffl),
+but don't provide a \*(L"liga\*(R" feature to access these.
+This option tells \fBautoinst\fR to add extra \f(CW\*(C`LIGKERN\*(C'\fR rules to
+the generated fonts to enable the use of these ligatures.
+Since this option is rarely necessary
+(most fonts with f\-ligatures do provide the matching \*(L"liga\*(R" feature),
+the default is \fB\-noligatures\fR.
 .IP "\fB\-defaultlining\fR / \fB\-defaultoldstyle\fR" 4
 .IX Item "-defaultlining / -defaultoldstyle"
 .PD 0
@@ -572,9 +586,26 @@
 one hundred \fI \-\-ligkern\fR options), which may cause problems on some systems.
 .IP "\fB\-mergewidths\fR / \fB\-nomergewidths\fR" 4
 .IX Item "-mergewidths / -nomergewidths"
-Some font families put Condensed, Narrow, Extended etc. fonts in separate families;
-this option tells \fBautoinst\fR to merge those separate families into the main family.
-The default is \fB\-nomergewidths\fR.
+Some font families put their Condensed, Narrow, Extended etc. widths
+in separate families;
+this option tells \fBautoinst\fR to merge those separate families into
+the main family.
+The default is \fB\-mergewidths\fR.
+.IP "\fB\-mergesmallcaps\fR / \fB\-nomergesmallcaps\fR" 4
+.IX Item "-mergesmallcaps / -nomergesmallcaps"
+Even more annoyingly, some font families put their small caps fonts
+in a separate family;
+this option tells \fBautoinst\fR to merge the small caps fonts into
+the main family.
+The default is \fB\-mergesmallcaps\fR.
+.IP "\fB\-nfssweight\fR=\fIcode\fR=\fIweight\fR, \fB\-nfsswidth\fR=\fIcode\fR=\fIwidth\fR" 4
+.IX Item "-nfssweight=code=weight, -nfsswidth=code=width"
+Map the \s-1NFSS\s0 code \fIcode\fR to the given weight or width,
+overriding the built-in tables.
+Each of these options may be given multiple times,
+to override more than one \s-1NFSS\s0 code.
+Example: to map the \*(L"ul\*(R" code to the \*(L"Thin\*(R" weight, use \f(CW\*(C`\-nfssweight=ul=thin\*(C'\fR.
+To inhibit the use of the \*(L"ul\*(R" code completely, use \f(CW\*(C`\-nfssweight=ul=\*(C'\fR.
 .IP "\fB\-extra\fR=\fItext\fR" 4
 .IX Item "-extra=text"
 Append \fItext\fR as extra options to the command lines for \fIotftotfm\fR.
@@ -583,7 +614,8 @@
 .IP "\fB\-manual\fR" 4
 .IX Item "-manual"
 Manual mode; for users who want to post-process the generated files and commands.
-By default, \fBautoinst\fR immediately executes all \fIotftotfm\fR commands it generates;
+By default, \fBautoinst\fR immediately executes all \fIotftotfm\fR commands
+it generates;
 in manual mode, these are instead written to a file \fIautoinst.bat\fR.
 Furthermore it tells \fIotftotfm\fR to generate human readable (and editable)
 \&\fIpl/vpl\fR files instead of the default \fItfm/vf\fR ones,
@@ -657,11 +689,11 @@
 .IX Header "AUTHOR"
 Marc Penninga (\fImarcpenninga at gmail.com\fR)
 .PP
-When sending a bug report, please give as much relevant information as
-possible.
-If you see any error messages
-(whether from \fBautoinst\fR itself, from the \fI\s-1LCDF\s0 TypeTools\fR, from Perl
-or from the \s-1OS\s0), include these \fIverbatim\fR; don't paraphrase.
+When sending a bug report, please give as much relevant information as possible;
+this usually includes (but may not be limited to) the log file
+(please add the \fI\-verbose\fR command-line option, for extra info).
+If you see any error messages, please include these \fIverbatim\fR;
+don't paraphase.
 .SH "COPYRIGHT"
 .IX Header "COPYRIGHT"
 Copyright (C) 2005\-2019 Marc Penninga.
@@ -682,6 +714,27 @@
 .SH "RECENT CHANGES"
 .IX Header "RECENT CHANGES"
 (See the source for the full story, all the way back to 2005.)
+.IP "\fI2019\-04\-22\fR" 12
+.IX Item "2019-04-22"
+Fixed a bug in the generation of swash shapes.
+.IP "\fI2019\-04\-19\fR" 12
+.IX Item "2019-04-19"
+Fixed a bug that affected \-mergesmallcaps with multiple encodings.
+.IP "\fI2019\-04\-16\fR" 12
+.IX Item "2019-04-16"
+Added the <\-mergesmallcaps> option, to handle cases where
+the small caps fonts are in separate font families.
+Titling shape is now treated as a separate family instead of a distinct shape;
+it is generated only for fonts with the 'titl' feature.
+Only add f\-ligatures to fonts when explicitly asked to (<\-fligatures>).
+.IP "\fI2019\-04\-11\fR" 12
+.IX Item "2019-04-11"
+Tried to make the log file more relevant.
+Added the \fI\-nfssweight\fR and \fI\-nfsswidth\fR options,
+and finetuned the automatic mapping between fonts and \s-1NFSS\s0 codes.
+Changed the name of the generated log file to \fI<fontfamily>.log\fR,
+and revived the \fI\-logfile\fR option to allow overriding this choice.
+Made \fI\-mergewidths\fR the default (instead of \fI\-nomergewidths\fR).
 .IP "\fI2019\-04\-01\fR" 12
 .IX Item "2019-04-01"
 Fine-tuned the decision where to put generated files;
@@ -692,15 +745,19 @@
 put all generated files into a subdirectory \f(CW\*(C`./autoinst_output/\*(C'\fR
 instead of all over the current working directory.
 .Sp
-Added to \*(L"auto\*(R" value to the \fIinferiors\fR option,
+Added \*(L"auto\*(R" value to the \fIinferiors\fR option,
 to tell \fBautoinst\fR to use whatever inferior characters are available.
-.IP "\fI2019\-03\-14\fR (never released to \s-1CTAN\s0)" 12
-.IX Item "2019-03-14 (never released to CTAN)"
+.IP "\fI2019\-03\-14\fR" 12
+.IX Item "2019-03-14"
+(never released to \s-1CTAN\s0)
+.Sp
 Overhauled the mapping of fonts (more specifically of weights and widths;
-the mapping of shapes didn't change) to \s-1NFSS\s0 codes. Instead of inventing our own codes
-to deal with every possible weight and width out there, we now create \*(L"long\*(R" codes
-based on the names in the font metadata. Then we add \*(L"ssub\*(R" rules to the \fIfd\fR
-files to map the standard \s-1NFSS\s0 codes to our fancy names (see the section \fB\s-1NFSS\s0 codes\fR;
+the mapping of shapes didn't change) to \s-1NFSS\s0 codes.
+Instead of inventing our own codes to deal with every possible weight
+and width out there, we now create \*(L"long\*(R" codes based on the names
+in the font metadata.
+Then we add \*(L"ssub\*(R" rules to the \fIfd\fR files to map the standard \s-1NFSS\s0 codes
+to our fancy names (see the section \fB\s-1NFSS\s0 codes\fR;
 based on discussions with Frank Mittelbach and Bob Tennent).
 .IP "\fI2018\-08\-10\fR" 12
 .IX Item "2018-08-10"

Modified: trunk/Master/texmf-dist/doc/man/man1/autoinst.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1	2019-05-02 22:48:32 UTC (rev 50947)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "OT2KPX 1"
-.TH OT2KPX 1 "2019-03-14" "fontools" "Marc Penninga"
+.TH OT2KPX 1 "2019-04-15" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -142,18 +142,25 @@
 ot2kpx \- extract kerning information from OpenType fonts
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-.IP "\fBot2kpx\fR" 8
-.IX Item "ot2kpx"
-\&\fBfontfile\fR
+\&\fBot2kpx\fR [ \fI\-afm\fR | \fI\-kpx\fR | \fI\-lua\fR ] \fBfontfile\fR
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
-\&\fBot2kpx\fR extract the kerning data from OpenType fonts (both \fIotf\fR
-and \fIttf\fR formats) and prints it (in \fIafm\fR format) to \f(CW\*(C`stdout\*(C'\fR.
+\&\fBot2kpx\fR extract the kerning data from OpenType fonts and prints it
+to \f(CW\*(C`stdout\*(C'\fR, either in Adobe's \s-1KPX\s0 format (for adding to an \fIafm\fR file)
+or as a Luatex custom feature, for use with the \f(CW\*(C`\edirectlua\*(C'\fR command.
 .SH "OPTIONS AND ARGUMENTS"
 .IX Header "OPTIONS AND ARGUMENTS"
+.IP "\fB\-afm\fR, \fB\-kpx\fR" 4
+.IX Item "-afm, -kpx"
+Output the kerning data in Adobe's \s-1KPX\s0 format, as used in \fIafm\fR files.
+This is the default output format.
+.IP "\fB\-lua\fR" 4
+.IX Item "-lua"
+Output the kerning data as a Luatex custom font feature,
+to be included in a \f(CW\*(C`\edirectlua\*(C'\fR command.
 .IP "\fBfontfile\fR" 4
 .IX Item "fontfile"
-The OpenType font (in either \fIotf\fR or \fIttf\fR format).
+The OpenType font (both \fIotf\fR and \fIttf\fR format are supported).
 .SH "RESTRICTIONS"
 .IX Header "RESTRICTIONS"
 .IP "\fB\-\fR" 4
@@ -198,7 +205,7 @@
 Marc Penninga <marcpenninga at gmail.com>
 .SH "COPYRIGHT"
 .IX Header "COPYRIGHT"
-Copyright (C) 2005\-2013 Marc Penninga.
+Copyright (C) 2005\-2019 Marc Penninga.
 .SH "LICENSE"
 .IX Header "LICENSE"
 This program is free software; you can redistribute it and/or modify
@@ -216,6 +223,10 @@
 .SH "RECENT CHANGES"
 .IX Header "RECENT CHANGES"
 (See the source code for the rest of the story.)
+.IP "\fI2019\-04\-15\fR" 12
+.IX Item "2019-04-15"
+Added the \-lua command-line option to get output in Luatex's
+custom feature format.
 .IP "\fI2013\-08\-07\fR" 12
 .IX Item "2013-08-07"
 Replaced all \f(CW\*(C`given/when\*(C'\fR constructions in the source code by \f(CW\*(C`if\*(C'\fR's,

Modified: trunk/Master/texmf-dist/doc/man/man1/ot2kpx.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/fontools/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/fontools/README	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/doc/support/fontools/README	2019-05-02 22:48:32 UTC (rev 50947)
@@ -1,68 +1,72 @@
 
                          -=- FONTOOLS -=-
-                         
 
+
 This package provides tools to simplify using OpenType fonts with LaTeX.
 
-Currently, this bundle contains the following programs:
+By far the most important program in this bundle is autoinst:
 
-AUTOINST - a wrapper script around Eddie Kohler's LCDF TypeTools. 
-    Autoinst aims to automate the installation of OpenType fonts in LaTeX 
-    by calling the LCDF TypeTools (with the correct options) for all fonts 
-    you wish to install, and by generating the necessary .fd and .sty files.
+    AUTOINST - a wrapper script around Eddie Kohler's LCDF TypeTools.
+        Autoinst aims to automate the installation of OpenType fonts in LaTeX
+        by calling the LCDF TypeTools (with the correct options) for all fonts
+        you wish to install, and generating the necessary .fd and .sty files.
 
-AFM2AFM - re-encode .afm files
+In addition, this bundle contains a few other, less important utilities:
 
-OT2KPX - extract kerning pairs from OpenType fonts.
+    AFM2AFM - re-encode .afm files
 
+    OT2KPX - extract kerning pairs from OpenType fonts.
 
 
+
 PREREQUISITES
--------------
+=============
 
 Perl
 
     The Fontools are written in Perl; any version since v5.10.1 should work.
-    Perl is usually installed on Linux and Unix systems; 
-    for Windows, try ActivePerl (http://www.activestate.com) 
+    Perl is usually installed on Linux and Unix systems;
+    for Windows, try ActivePerl (http://www.activestate.com)
     or Strawberry Perl (http://strawberryperl.com).
 
 LCDF TypeTools
-    Of course, Autoinst needs the LCDF TypeTools; 
+    Of course, Autoinst needs the LCDF TypeTools;
     they should be installed in a directory on your PATH.
 
 Kpathsea
     Automatically installing the fonts into a suitable TEXMF tree
-    (as Autoinst does by default) requires a TeX-installation that uses 
-    the kpathsea library; with TeX distributions that implement their 
-    own directory searching (such as MiKTeX), Autoinst will complain that 
+    (as Autoinst does by default) requires a TeX-installation that uses
+    the kpathsea library; with TeX distributions that implement their
+    own directory searching (such as MiKTeX), Autoinst will complain that
     it cannot find the kpsewhich program and install all generated files
-    into subdirectories of the current directory. 
-    
-    If you use such a TeX distribution, either move these files to their 
+    into subdirectories of the current directory.
+
+    If you use such a TeX distribution, either move these files to their
     destinations by hand, or use the -target command line option
     (please see the manual for more information).
 
-Other
-    The encoding files in the "share" directory should be installed 
-    in a standard location where otftotfm can find them.
 
+Installation
+------------
+The encoding files in the "share" directory should be moved
+to a standard location where otftotfm can find them.
 
+
 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. 
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.
 
 
 LICENSE & COPYRIGHT
--------------------
+===================
 
-This software is copyright (C) 2005-2019 Marc Penninga. It is released under 
-the terms of the GNU General Public Licence; see the file GPLv2.txt for 
+This software is copyright (C) 2005-2019 Marc Penninga. It is released under
+the terms of the GNU General Public Licence; see the file GPLv2.txt for
 the license conditions.
 
 
-                                                Marc Penninga, 2019/04/01
+                                                Marc Penninga, 2019/04/22

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ly1.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ly1.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ly1.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -14,11 +14,11 @@
 /.notdef
 /.notdef
 /cwm
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x10
 /dotlessi
 /dotlessj
@@ -302,4 +302,5 @@
 % LIGKERN greater greater =: guillemotright;
 %
 % LIGKERN || = 32;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ot1.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ot1.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ot1.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -14,11 +14,11 @@
 /Phi
 /Psi
 /Omega
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x10
 /dotlessi
 /dotlessj
@@ -299,4 +299,5 @@
 % LIGKERN quoteright quoteright =: quotedblright;
 %
 % LIGKERN || = 32;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t1.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t1.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t1.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -32,11 +32,11 @@
 /perthousandzero
 /dotlessi
 /dotlessj
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x20
 /space
 /exclam
@@ -302,4 +302,5 @@
 % LIGKERN greater greater =: guillemotright;
 %
 % LIGKERN || = 32 ;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2a.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2a.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2a.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -32,11 +32,11 @@
 /perthousandzero
 /dotlessi
 /dotlessj
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x20
 /space
 /exclam
@@ -300,4 +300,5 @@
 % LIGKERN greater greater =: guillemotright4;
 %
 % LIGKERN || = 32 ;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2b.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2b.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2b.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -32,11 +32,11 @@
 /perthousandzero
 /dotlessi
 /dotlessj
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x20
 /space
 /exclam
@@ -300,4 +300,5 @@
 % LIGKERN greater greater =: guillemotright4;
 %
 % LIGKERN || = 32 ;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2c.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2c.enc	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t2c.enc	2019-05-02 22:48:32 UTC (rev 50947)
@@ -32,11 +32,11 @@
 /perthousandzero
 /dotlessi
 /dotlessj
-/.notdef    % was /ff
-/.notdef    % was /fi
-/.notdef    % was /fl
-/.notdef    % was /ffi
-/.notdef    % was /ffl
+/ff
+/fi
+/fl
+/ffi
+/ffl
 % 0x20
 /space
 /exclam
@@ -300,4 +300,5 @@
 % LIGKERN greater greater =: guillemotright4;
 %
 % LIGKERN || = 32 ;
-
+%
+% UNICODING ff =: ; fi =: ; fl =: ; ffi =: ; ffl =: ;

Modified: trunk/Master/texmf-dist/scripts/fontools/autoinst
===================================================================
--- trunk/Master/texmf-dist/scripts/fontools/autoinst	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/scripts/fontools/autoinst	2019-05-02 22:48:32 UTC (rev 50947)
@@ -38,6 +38,7 @@
 use File::Spec ();
 use Getopt::Long ();
 use Pod::Usage ();
+use POSIX ();
 
 my ($d, $m, $y) = (localtime time)[3 .. 5];
 my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d;
@@ -66,7 +67,7 @@
 
 =begin Comment
 
-    Latex's NFSS contains a limited number of standard codes for weight and width:
+    LaTeX's NFSS contains a limited number of standard codes for weight and width:
     - weight: ul, el, l, sl, m, sb, b, eb, ub
     - width:  uc, ec, c, sc, m, sx, x, ex, ux
 
@@ -82,11 +83,11 @@
     2.  We add "ssub" rules to the .fd files that map the standard NFSS codes
         to actual fonts.
 
-    In step 1, we follow NFSS in leaving out any occurrence of the word "regular"
-    unless *both* weight and width are Regular; in that case, the series attribute
-    becomes "regular".
+    In step 1, we follow NFSS in leaving out any occurrence of
+    the word "regular" unless *both* weight and width are Regular;
+    in that case, the 'series' attribute becomes "regular".
 
-    The two tables %NFSS_WEIGHT and %NFSS_WIDTH are used to control step 2.
+    The two tables NFSS_WEIGHT and NFSS_WIDTH are used to control step 2.
     It contains several entries of the form
 
         sc  =>  [ qw( semicondensed narrow ) ],
@@ -94,12 +95,6 @@
     This should be read as follows: the NFSS code "sc" is mapped to the *first*
     width on the right hand side that is present in the current font family.
 
-    Given the lack of a standardised font naming scheme, this mapping system
-    will probably leave some fonts without matching NFSS codes and, vice versa,
-    some NFSS codes without matching font. It is, however, probably the best
-    that can be done in an automated way. If you think you can do better,
-    I welcome pull requests :-)
-
     Please note that the tables contain empty keys instead of "m" for
     the regular weight and width. NFSS actually combines weight and width
     into a single "series" attribute; a weight or width of "m" is left out of
@@ -112,8 +107,8 @@
     to be searched for.
 
     These tables can be extended to teach autoinst about new weights or widths.
-    Suppose your font family contains a "Hemibold" weight. Then simply add the name
-    "hemibold" to the right hand side of the "sb" entry in the %NFSS_WEIGHT
+    Suppose your font family contains a "Hemibold" weight. Then add the name
+    "hemibold" to the right hand side of the "sb" entry in the NFSS_WEIGHT
     table:
 
         sb  =>  [ qw( semibold demi demibold medium hemibold ) ],
@@ -124,9 +119,13 @@
     NFSS code).
 
     Note that autoinst converts all metadata to lowercase to avoid inconsistent
-    capitalization; hence all entries in these tables should be *lowercase* as well.
+    capitalization; so all entries in these tables should be *lowercase* as well.
 
+    Technical note:
+    We define NFSS_WEIGHT and NFSS_WIDTH first as arrays and then as hashtables;
+    this allows us to use the array-variants as an *ordered* list of keys.
 
+
     Finally, some random remarks about these tables:
     - Poster and Super aren't just "very heavy" weights; in most cases, they're
         more like separate designs. The same holds for the Compact width.
@@ -136,30 +135,31 @@
         mostly, however, it is a very light weight below Ultralight.
     - Semilight weights are virtually nonexistent, except for Thesis
         (which contains a Semilight weight) and Arnhem (which has Blond).
-    - Book is usually slightly lighter than Regular (and so could be mapped to "sl"),
-        but sometimes (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
+    - Book is usually slightly lighter than Regular, but sometimes
+        (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
     - Likewise, Medium can really be two different things:
         - a synonym for Semibold
         - (especially in newer fonts) an extra step between Regular and Semibold
         I treat it as if it's always the first.
     - Heavy can mean very different things; it's often heavier than Black,
-        but sometimes it's a synonym for Extrabold, and in some families (Futura)
-        it's even lighter than Bold. I treat it here as "very black".
+        but sometimes it's a synonym for Extrabold, and in Futura it's even
+        lighter than Bold. I treat it here as "very black".
     - Font families that have both Condensed and Compressed widths
         seem to define Compressed as narrower than Condensed.
-    - In Basic Sans (which is the only family I know with both Narrow and Condensed
-        fonts) Narrow is a bit wider than Condensed. So I mapped Narrow to "sc".
+    - In Basic Sans and Input (which are the only families I know with both
+        Narrow and Condensed), Narrow is a bit wider than Condensed.
+        So I mapped Narrow to "sc".
     - Extended and Expanded seem to be used interchangeably.
-    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts in the wild,
-        so the ex and ux entries are currently empty
+    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts,
+        so the ex and ux entries are currently empty.
 
 =end Comment
 
 =cut
 
-my %NFSS_WEIGHT = (
-    ul  =>  [ qw( ultralight hair hairline eight four two ) ],
-    el  =>  [ qw( extralight thin ) ],
+my @NFSS_WEIGHT = (
+    ul  =>  [ qw( ultralight thin hair hairline eight four two ) ],
+    el  =>  [ qw( extralight ) ],
     l   =>  [ qw( light ) ],
     sl  =>  [ qw( semilight blond ) ],
     ''  =>  [ qw( regular text book ) ],
@@ -169,8 +169,11 @@
     ub  =>  [ qw( ultrabold black heavy extrablack ultra ultrablack ultraheavy
                   poster super ) ],
 );
+my %NFSS_WEIGHT = @NFSS_WEIGHT;
+ at NFSS_WEIGHT = grep { !ref } @NFSS_WEIGHT;
+my @WEIGHTS = map { @{$_} } values %NFSS_WEIGHT;
 
-my %NFSS_WIDTH = (
+my @NFSS_WIDTH = (
     uc  =>  [ qw( ultracondensed extracompressed ultracompressed ) ],
     ec  =>  [ qw( extracondensed cmp comp compressed compact ) ],
     c   =>  [ qw( cond condensed ) ],
@@ -181,10 +184,13 @@
     ex  =>  [ ],
     ux  =>  [ ],
 );
+my %NFSS_WIDTH = @NFSS_WIDTH;
+ at NFSS_WIDTH = grep { !ref } @NFSS_WIDTH;
+my @WIDTHS = map { @{$_} } values %NFSS_WIDTH;
 
 =begin Comment
 
-    The %NFSS_SHAPE table maps various shape names to NFSS codes.
+    The NFSS_SHAPE table maps various shape names to NFSS codes.
 
     Note that this table works the other way around compared to
     the two previous tables; it directly maps shape names to NFSS codes.
@@ -195,7 +201,7 @@
     For shapes, that's not the case; font families don't have both Slanted and
     Oblique shapes, since these are just different names for the same thing.
 
-    Like in the other %NFSS_* tables, entries may be added to teach autoinst
+    Like in the other NFSS_* tables, entries may be added to teach autoinst
     about new shapes.
 
 =end Comment
@@ -202,7 +208,7 @@
 
 =cut
 
-my %NFSS_SHAPE = (
+my @NFSS_SHAPE = (
     roman       =>  'n',
     upright     =>  'n',
     italic      =>  'it',
@@ -215,14 +221,15 @@
     oblique     =>  'sl',
     slanted     =>  'sl',
     slant       =>  'sl',
-    romani      =>  'n',    # Adobe Silentium Pro has two roman shapes, but no italic;
+    romani      =>  'n',    # Silentium Pro has two roman shapes, but no italic;
     romanii     =>  'it',   # so we cheat by mapping the second roman shape to 'it'
 );
+my %NFSS_SHAPE = @NFSS_SHAPE;
 
 =begin Comment
 
     The %SHAPE table is used in deciding which font shapes
-    (normal, small caps, swash, titling or textcomp) to generate.
+    (normal, small caps, swash or textcomp) to generate.
 
     Each key in this table names a shape; the corresponding value
     is an anonymous hash with several key/value pairs:
@@ -271,18 +278,11 @@
     # comes last in the command line; else 'aalt' might be overridden
     swash => {
         code  => { n => 'nw', it => 'sw' },
-        reqd  => [ 'swsh', 'dlig' ],
-        nice  => [ 'kern', 'liga' ],
+        reqd  => [ 'swsh' ],
+        nice  => [ 'kern', 'liga', 'dlig' ],
         extra => '--include-alternates="*.swash" --feature=aalt',
         name  => 'swash',
     },
-    titling => {
-        code  => { n => 'tl', it => 'tlit', sl => 'tlsl' },
-        reqd  => [ 'titl', 'case', 'cpsp' ],
-        nice  => [ 'kern', 'liga' ],
-        extra => '',
-        name  => 'titling',
-    },
     textcomp => {
         code  => { n => 'n', it => 'it', sl => 'sl' },
         reqd  => [ ],
@@ -304,10 +304,8 @@
 my %SSUB_SHAPE = (
     sl      =>  'it',
     scsl    =>  'scit',
-    tlsl    =>  'tlit',
     it      =>  'sl',
     scit    =>  'scsl',
-    tlit    =>  'tlsl',
 );
 
 =begin Comment
@@ -344,13 +342,13 @@
         reqd   => [ ],
         nice   => [ ],
         extra  => '',
-        shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ],
+        shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ],
     },
     LF => {
         reqd   => [ ],
         nice   => [ ],
         extra  => '',
-        shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ],
+        shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ],
     },
     TOsF => {
         reqd   => [ ],
@@ -388,6 +386,12 @@
         extra  => '--ligkern="* {KL} *"',
         shapes => [ 'normal' ],
     },
+    Titl => {
+        reqd   => [ 'titl' ],
+        nice   => [ 'kern', 'liga' ],
+        extra  => '',
+        shapes => [ 'normal' ],
+    },
     Orn => {
         reqd   => [ 'ornm' ],
         nice   => [ ],
@@ -458,20 +462,8 @@
     # since this requires knowing which inferior figures this font supports;
     # so we have to do the font info parsing first.
     if ($ARGV{inferiors} eq 'auto') {
-        FONT:
-        for my $font (@fonts) {
-            for my $inf (qw(subs sinf dnom)) {
-                if (exists $font->{feature}{$inf}) {
-                    $ARGV{inferiors} = $inf;
-                    $STYLE{Inf}{reqd} = [$inf];
-                    last FONT;
-                }
-            }
-        }
+        Fontinfo::handle_auto_inferiors(@fonts);
     }
-    # If we didn't find any inferior figures, delete the 'Inf' entry
-    # frin the %STYLE table to indicate we don't want to generate this style.
-    delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto';
 
     # For each font, figure out the styles, shapes and encodings to generate
     my @worklist
@@ -492,6 +484,9 @@
              [ $minsize, $maxsize, $item->{fontname} ];
     }
 
+    # Decide to which weights and widths we'll map the standard NFSS codes
+    decide_nfss_mappings(@fonts);
+
     create_logfile(@worklist);
 
     if (!$ARGV{dryrun}) {
@@ -604,6 +599,19 @@
         my ($font, $style, $shape, $encoding)
             = @{$item}{qw(font style shape encoding)};
 
+        # make unique copy of fontdata, since we're modifying it;
+        # otherwise, the mergesmallcaps only works for
+        # the first encoding in the list
+        my %font = %$font;
+        $font = $item->{font} = \%font;
+
+        # handle fonts that put small caps fonts into separate family
+        if ($ARGV{mergesmallcaps}) {
+            if ($font->{family} =~ s/smallcaps$//xmsi) {
+                $shape = $item->{shape} = 'smallcaps';
+            }
+        }
+
         # generate unique name for this font
         $item->{fontname} = join '-', grep { $_ } $font->{name},
                                                   lc $style,
@@ -637,6 +645,55 @@
 }
 
 #-----------------------------------------------------------------------
+# Modify NFSS_WEIGHT and _WIDTH tables: pick one choice for each NFSS code
+#-----------------------------------------------------------------------
+sub decide_nfss_mappings {
+    my ( %weight, %width );
+    for my $font (@_) {
+        $weight{ $font->{weight} } = 1;
+        $width{ $font->{width} } = 1;
+    }
+
+    NFSSWEIGHT:
+    for my $nfssweight (@NFSS_WEIGHT) {
+        for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
+            if ( $weight{$weight} ) {
+                $NFSS_WEIGHT{$nfssweight} = [ $weight ];
+                next NFSSWEIGHT;
+            }
+        }
+        $NFSS_WEIGHT{$nfssweight} = [];
+    }
+    if ( !$ARGV{el} and !$ARGV{ul} ) {
+        if ( @{$NFSS_WEIGHT{ul}}
+                and $NFSS_WEIGHT{ul}[0] ne 'ultralight'
+                and !@{$NFSS_WEIGHT{el}} ) {
+            $NFSS_WEIGHT{el} = $NFSS_WEIGHT{ul};
+            $NFSS_WEIGHT{ul} = [];
+        }
+    }
+    if ( !$ARGV{eb} and !$ARGV{ub} ) {
+        if ( @{$NFSS_WEIGHT{ub}}
+                and $NFSS_WEIGHT{ub}[0] ne 'ultrabold'
+                and !@{$NFSS_WEIGHT{eb}} ) {
+            $NFSS_WEIGHT{eb} = $NFSS_WEIGHT{ub};
+            $NFSS_WEIGHT{ub} = [];
+        }
+    }
+
+    NFSSWIDTH:
+    for my $nfsswidth (@NFSS_WIDTH) {
+        for my $width ( @{$NFSS_WIDTH{$nfsswidth}} ) {
+            if ( $width{$width} ) {
+                $NFSS_WIDTH{$nfsswidth} = [ $width ];
+                next NFSSWIDTH;
+            }
+        }
+        $NFSS_WIDTH{$nfsswidth} = [];
+    }
+}
+
+#-----------------------------------------------------------------------
 # Dump all relevant info to the logfile
 #-----------------------------------------------------------------------
 sub create_logfile {
@@ -646,17 +703,28 @@
                     || $a->{style} cmp $b->{style}
                } @_;
 
-    open my $LOG, '>', $ARGV{logfile}
+    if (-e $ARGV{logfile}) {
+        print "[INFO]: file '$ARGV{logfile}' already exists;\n" .
+              "        appending new log data to end\n\n";
+    }
+    open my $LOG, '>>', $ARGV{logfile}
         or die "$0: cannot create $ARGV{logfile}: $!";
 
     print {$LOG} <<"END_ARGUMENTS";
 
-$ARGV{cmdline}
 
+############################################################################
 
-****************************************************************************
 
+@{[ POSIX::strftime("[%F %T]", localtime time) ]}  $0
 
+
+    "$ARGV{cmdline}"
+
+
+----------------------------------------------------------------------------
+
+
 I'm using the following options:
 
     encoding(s):        @{[ join ', ', @{$ARGV{encoding}} ]}
@@ -678,6 +746,7 @@
     inferiors:          $ARGV{inferiors}
     ornaments:          @{[ $ARGV{ornaments}    ? 'yes' : 'no' ]}
     fractions:          @{[ $ARGV{fractions}    ? 'yes' : 'no' ]}
+    ligatures:          @{[ $ARGV{ligatures}    ? 'yes' : 'no' ]}
 
     dry run/real:       @{[ $ARGV{dryrun}       ? 'dry run'   : 'real'   ]}
     auto/manual:        @{[ $ARGV{manual}       ? 'manual'    : 'auto'   ]}
@@ -684,8 +753,9 @@
     target:             $ARGV{target}
     extra:              @{[ $ARGV{extra} || '<empty>' ]}
 
-    figurekern:         @{[ $ARGV{figurekern}   ? 'no action' : 'remove' ]}
-    mergewidths:        @{[ $ARGV{mergewidths}  ? 'yes' : 'no' ]}
+    figurekern:         @{[ $ARGV{figurekern}       ? 'no action' : 'remove' ]}
+    mergewidths:        @{[ $ARGV{mergewidths}      ? 'yes' : 'no' ]}
+    mergesmallcaps:     @{[ $ARGV{mergesmallcaps}   ? 'yes' : 'no' ]}
 
 
     font files:
@@ -693,18 +763,29 @@
 
 END_ARGUMENTS
 
+    printf {$LOG} "\n" . '-' x 76 . "\n\n\nNFSS mappings:\n\n";
+    for my $weight (@NFSS_WEIGHT) {
+        printf {$LOG} "    %-3s =>  %s\n",
+                $weight || 'm', $NFSS_WEIGHT{$weight}[0] || '';
+    }
+    printf {$LOG} "\n";
+    for my $width (@NFSS_WIDTH) {
+        printf {$LOG} "    %-3s =>  %s\n",
+                $width || 'm', $NFSS_WIDTH{$width}[0] || '';
+    }
+    printf {$LOG} "\n";
+
+    return if $ARGV{verbose} < 1;
+
     my ($prevfn, $prevsty, $prevenc) = ('') x 3;
     my @cmds;
     for my $item (@worklist) {
         if ($prevfn ne $item->{font}{filename}) {
-            push @cmds, "\n" . '*' x 76;
             print {$LOG} <<"END_FONTINFO";
 
+    ------------------------------------------------------------------------
 
-****************************************************************************
-
-
-$item->{font}{filename}
+    $item->{font}{filename}
         Name:       $item->{font}{name}
         Family:     $item->{font}{family}
         Subfamily:  $item->{font}{subfamily}
@@ -715,10 +796,9 @@
         Features:   @{[ join ', ', sort keys %{$item->{font}{feature}} ]}
 
 
-Generating these encodings, figure styles and shapes:
+        Generating these encodings, figure styles and shapes:
 
-    ENC     STYLE   SHAPE   FEATURES USED
-    --------------------------------------------------------------------
+        ENC     STYLE   SHAPE   FEATURES USED
 END_FONTINFO
         }
         if ($prevenc ne $item->{encoding}[1]
@@ -725,7 +805,7 @@
             || $prevsty ne $item->{style}) {
             print {$LOG} "\n";
         }
-        printf {$LOG} "    %-3s     %-4s    %-4s    %s\n",
+        printf {$LOG} "        %-3s     %-4s    %-4s    %s\n",
                             $item->{encoding}[1],
                             $item->{style},
                             $item->{fdshape},
@@ -738,6 +818,7 @@
         push @cmds, $item->{cmdline};
     }
 
+    return if $ARGV{verbose} < 2;
     print {$LOG} join "\n\n", @cmds;
     print {$LOG} "\n";
     close $LOG;
@@ -799,13 +880,13 @@
                         ? qq(--coding-scheme="$SCHEME{$item->{encoding}[0]}")
                         : ''),
                      (map { "--feature=$_" } @{$item->{features}}),
-                     ((grep { $_ eq 'liga' } @{$item->{features}})
-                        ? ''
-                        : ( '--ligkern="f i =: fi"',
+                     ($ARGV{ligatures}
+                        ? ( '--ligkern="f i =: fi"',
                             '--ligkern="f l =: fl"',
                             '--ligkern="f f =: ff"',
                             '--ligkern="ff i =: ffi"',
-                            '--ligkern="ff l =: ffl"' )),
+                            '--ligkern="ff l =: ffl"' )
+                        : ''),
                      $STYLE{$item->{style}}{extra},
                      $SHAPE{$item->{shape}}{extra},
                      $ARGV{extra},
@@ -873,7 +954,9 @@
                             Use this style for subscripts (see docs)
     -(no)ornaments          Toggle creation of ornament fonts
     -(no)fractions          Toggle creation of fonts with digits for fractions
+    -(no)ligatures          Toggle manual addition of f-ligatures to font
 
+    -serif                  Install font as serif font
     -sanserif               Install font as sanserif font
     -typewriter             Install font as typewriter font
 
@@ -891,11 +974,17 @@
 
     -(no)figurekern         Keep or remove kerns between tabular figures
     -(no)mergewidths        Merge Condended/Extended subfamilies with main family
+    -(no)mergesmallcaps     Merge small caps subfamilies with main family
 
+    -nfssweight=xx=yyyy     Map the "xx" NFSS code to the "yyyy" weight
+    -nfsswidth=xx=yyyy      Map the "xx" NFSS code to the "yyyy" width
+
     -help                   Print this text and exit
     -doc                    Print the complete documentation and exit
     -dryrun                 Don't generate fonts, only log what would be done
-
+    -logfile="FILE"         Write log data to "FILE" (default: <fontfamily>.log)
+    -verbose                Print more data to log file
+                            (repeat for even higher verbosity)
     font[s]                 The fonts (.otf or .ttf format) to install.
 
 Please report any bugs or suggestions to <marcpenninga at gmail.com>.
@@ -903,32 +992,35 @@
 
 # Default values for the command-line arguments
 %ARGV = (
-    encoding     => 'OT1,T1,LY1',
-    textcomp     => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
-    lining       => '1',     # 0 = no, 1 = yes
-    oldstyle     => '1',     # 0 = no, 1 = yes
-    proportional => '1',     # 0 = no, 1 = yes
-    tabular      => '1',     # 0 = no, 1 = yes
-    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    => 'none',  # possible values: none, auto, subs, sinf, dnom
-    ornaments    => '1',     # 0 = no, 1 = yes
-    fractions    => '0',     # 0 = no, 1 = yes
-    nfss         => 'rm',
-    fig_height   => 'lnum',
-    fig_width    => 'tnum',
-    extra        => '',
-    target       => '',
-    vendor       => 'lcdftools',
-    typeface     => '',
-    updmap       => '1',     # 0 = no, 1 = yes
-    manual       => '0',     # 0 = no, 1 = yes
-    dryrun       => '0',     # 0 = no, 1 = yes
-    logfile      => 'autoinst.log',
-    figurekern   => '1',     # 0 = no, 1 = yes
-    mergewidths  => '0',     # 0 = no, 1 = yes
+    encoding        => 'OT1,T1,LY1',
+    textcomp        => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
+    lining          => '1',     # 0 = no, 1 = yes
+    oldstyle        => '1',     # 0 = no, 1 = yes
+    proportional    => '1',     # 0 = no, 1 = yes
+    tabular         => '1',     # 0 = no, 1 = yes
+    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       => 'none',  # possible values: none, auto, subs, sinf, dnom
+    ornaments       => '1',     # 0 = no, 1 = yes
+    fractions       => '0',     # 0 = no, 1 = yes
+    ligatures       => '0',     # 0 = no, 1 = yes
+    nfss            => 'rm',
+    fig_height      => 'lnum',
+    fig_width       => 'tnum',
+    extra           => '',
+    target          => '',
+    vendor          => 'lcdftools',
+    typeface        => '',
+    updmap          => '1',     # 0 = no, 1 = yes
+    manual          => '0',     # 0 = no, 1 = yes
+    dryrun          => '0',     # 0 = no, 1 = yes
+    logfile         => '',
+    figurekern      => '1',     # 0 = no, 1 = yes
+    mergewidths     => '1',     # 0 = no, 1 = yes
+    mergesmallcaps  => '1',     # 0 = no, 1 = yes
+    verbose         => 0,
 );
 
 #-----------------------------------------------------------------------
@@ -953,6 +1045,8 @@
         'inferiors=s'         => \$ARGV{inferiors},
         'ornaments!'          => \$ARGV{ornaments},
         'fractions!'          => \$ARGV{fractions},
+        'ligatures!'          => \$ARGV{ligatures},
+        'serif'               =>  sub { $ARGV{nfss} = 'rm' },
         'sanserif'            =>  sub { $ARGV{nfss} = 'sf' },
         'typewriter'          =>  sub { $ARGV{nfss} = 'tt' },
         'defaultlining'       =>  sub { $ARGV{fig_height} = 'lnum' },
@@ -968,7 +1062,21 @@
         'manual'              => \$ARGV{manual},
         'figurekern!'         => \$ARGV{figurekern},
         'mergewidths!'        => \$ARGV{mergewidths},
-        'verbose+'            => sub {},
+        'mergesmallcaps!'     => \$ARGV{mergesmallcaps},
+        'logfile=s'           => \$ARGV{logfile},
+        'verbose+'            => \$ARGV{verbose},
+        'nfssweight=s%'       => sub {
+                                     my ( $ignored, $key, $values ) = @_;
+                                     my @values = split m/,/, lc $values;
+                                     $NFSS_WEIGHT{$key} = \@values;
+                                     $ARGV{$key} = 'user-defined';
+                                 },
+        'nfsswidth=s%'        => sub {
+                                     my ( $ignored, $key, $values ) = @_;
+                                     my @values = split m/,/, lc $values;
+                                     $NFSS_WIDTH{$key} = \@values;
+                                     $ARGV{$key} = 'user-defined';
+                                 },
     )
     or die "$USAGE";
 
@@ -976,8 +1084,8 @@
 
     delete $SHAPE{smallcaps}     unless $ARGV{smallcaps};
     delete $SHAPE{swash}         unless $ARGV{swash};
-    delete $SHAPE{titling}       unless $ARGV{titling};
 
+    delete $STYLE{Titl}          unless $ARGV{titling};
     delete $STYLE{Sup}           unless $ARGV{superiors};
     delete $STYLE{Orn}           unless $ARGV{ornaments};
     delete @STYLE{qw(Numr Dnom)} unless $ARGV{fractions};
@@ -1138,13 +1246,13 @@
     # 1.  Search for matching widths before matching weights
     #     (as none of the widths is a proper substring of some weight)
     # 2.  Remove any recognised search string from the 'fullinfo'
-    for my $width ( mqrs( map { @{$_} } values %NFSS_WIDTH ) ) {
+    for my $width ( mqrs(@WIDTHS) ) {
         if ($fullinfo =~ s/${width}//gxmsi) {
             $info->{width} = $width;
             last;
         }
     }
-    for my $weight ( mqrs( map { @{$_} } values %NFSS_WEIGHT ) ) {
+    for my $weight ( mqrs(@WEIGHTS) ) {
         if ($fullinfo =~ s/${weight}//gxmsi) {
             $info->{weight} = $weight;
             last;
@@ -1169,10 +1277,13 @@
     $info->{family}    = $data{family};
     $info->{subfamily} = $data{subfamily};
 
+    if ( !$ARGV{logfile} ) {
+        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
+    }
     # Some font families put condensed or extended widths into separate families;
     # we provide an option to merge these with the 'main' font family.
     if ($ARGV{mergewidths}) {
-        my $widths = join '|', mqrs( map { @{$_} } values %NFSS_WIDTH );
+        my $widths = join '|', mqrs(@WIDTHS);
         if ($info->{width} eq 'regular'
             && $info->{family} =~ m/(.+?) [ ]* (${widths})$/xmsi)
         {
@@ -1197,13 +1308,13 @@
 
     # We define 'series' as 'weight + width'. This matches NFSS, but contradicts
     # how most fonts are named (which is 'width + weight').
-    $info->{series} 
+    $info->{series}
         = ($info->{width} eq 'regular')  ? $info->{weight}
         : ($info->{weight} eq 'regular') ? $info->{width}
         :                                  $info->{weight} . $info->{width}
         ;
 
-    return $info;
+    return;
 }
 
 #-----------------------------------------------------------------------
@@ -1234,7 +1345,7 @@
     $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
     close $otfinfo;
 
-    return $info;
+    return;
 }
 
 #-----------------------------------------------------------------------
@@ -1279,7 +1390,7 @@
     }
     close $otfinfo;
 
-    return $info;
+    return;
 }
 
 
@@ -1304,7 +1415,7 @@
         -   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
-            '%NFSS_WIDTH', '%NFSS_WEIGHT' or '%NFSS_SHAPE' near the top
+            'NFSS_WIDTH', 'NFSS_WEIGHT' or 'NFSS_SHAPE' near the top
             of the source code;
 
         Please also send a bug report to the author.
@@ -1382,7 +1493,27 @@
     return $enc_name;
 }
 
+#-----------------------------------------------------------------------
+# Handle the -inferiors=auto option
+#-----------------------------------------------------------------------
+sub handle_auto_inferiors {
+    FONT:
+    for my $font (@_) {
+        for my $inf (qw(subs sinf dnom)) {
+            if (exists $font->{feature}{$inf}) {
+                $ARGV{inferiors} = $inf;
+                $STYLE{Inf}{reqd} = [$inf];
+                last FONT;
+            }
+        }
+    }
 
+    # If we didn't find any inferior figures, delete the 'Inf' entry
+    # from the %STYLE table to indicate we don't want to generate this style.
+    delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto';
+}
+
+
 ############################################################################
 
 
@@ -1389,7 +1520,7 @@
 package LaTeX;
 
 #-----------------------------------------------------------------------
-# Create a Latex style file
+# Create a LaTeX style file
 #-----------------------------------------------------------------------
 sub write_stylefile {
     my ($fam, $data) = @_;
@@ -1423,20 +1554,7 @@
     \RequirePackage{fontaxes}
 END_STY_FONTAXES_START
 
-        if ($seen{tl} or $seen{tlit}) {
-        print {$STY} <<'END_STY_FONTAXES_TL';
-    \providecommand{\tldefault}{tl}
-    \DeclareRobustCommand\tlshape{\not at math@alphabet\tlshape\relax
-        \fontsecondaryshape\tldefault\selectfont}
-    \DeclareTextFontCommand{\texttl}{\tlshape}
-    \let\texttitling\texttl
-    \fa at naming@exception{shape}{{n}{tl}}{tl}
-    \fa at naming@exception{shape}{{it}{tl}}{tlit}
-    \fa at naming@exception{shape}{{sl}{tl}}{tlsl}
 
-END_STY_FONTAXES_TL
-    }
-
     if ($seen{nw} or $seen{sw}) {
         print {$STY} <<'END_STY_FONTAXES_SW';
     \DeclareRobustCommand\swshape{\not at math@alphabet\swshape\relax
@@ -1471,6 +1589,18 @@
 END_STY_FONTAXES_INF
     }
 
+    if ($seen{Titl}) {
+        print {$STY} <<'END_STY_FONTAXES_TITL';
+    \fa at naming@exception{figures}{{titlingshape}{proportional}}{Titl}
+    \fa at naming@exception{figures}{{titlingshape}{tabular}}{Titl}
+    \def\tlshape{\@nomath\tlshape
+        \fontfigurestyle{titlingshape}\selectfont}
+    \DeclareTextFontCommand{\texttl}{\tlshape}
+    \let\texttitling\texttl
+
+END_STY_FONTAXES_TITL
+    }
+
     if ($seen{Orn}) {
         print {$STY} <<'END_STY_FONTAXES_ORN';
     \fa at naming@exception{figures}{{ornament}{proportional}}{Orn}
@@ -1540,8 +1670,7 @@
         :               die "[ERROR] Internal bug, please report!";
 
     my $default_bold;
-    for my $series (qw(heavy black extrabold demibold semibold bold))
-    {
+    for my $series (qw(heavy black extrabold demibold semibold bold)) {
         if ( $seen{$series} ) {
             print {$STY}
                 "\\DeclareOptionX{$series}{\\edef\\bfseries\@$ARGV{nfss}",
@@ -1655,14 +1784,14 @@
 
     print {$FD} <<"END_COMMENT";
 %
-%   ====  Extra 'ssub' rules to map the standard NFSS codes to our fancy names  ====
+%  Extra 'ssub' rules to map the standard NFSS codes to our fancy names
 %
 END_COMMENT
     my %seen;
     NFSSWEIGHT:
-    for my $nfssweight (keys %NFSS_WEIGHT) {
+    for my $nfssweight (@NFSS_WEIGHT) {
         NFSSWIDTH:
-        for my $nfsswidth (keys %NFSS_WIDTH) {
+        for my $nfsswidth (@NFSS_WIDTH) {
             my $nfssseries = ( $nfssweight . $nfsswidth) || 'm';
 
             for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
@@ -1732,7 +1861,7 @@
 =head1 NAME
 
 autoinst - wrapper around the F<LCDF TypeTools>,
-for installing and using OpenType fonts in (La)TeX.
+for installing and using OpenType fonts in LaTeX.
 
 
 =head1 SYNOPSIS
@@ -1778,29 +1907,17 @@
 
 Small caps
 
-=item I<sw>
-
-Swash
-
-=item I<tl>
-
-Titling shape. Meant for all-caps text; letterspacing and the positioning of
-punctuation characters have been adjusted to suit all-caps text.
-(This shape is only generated for the families with lining digits,
-since old-style digits make no sense with all-caps text.)
-
 =item I<scit>, I<scsl>
 
 Italic and slanted small caps
 
-=item I<nw>
+=item I<sw>
 
-"Upright swash"; usually roman text with a few "oldstyle" ligatures
-like ct, sp and st.
+Swash
 
-=item I<tlit>, I<tlsl>
+=item I<nw>
 
-Italic and slanted titling text
+"Upright swash"
 
 =back
 
@@ -1818,6 +1935,14 @@
 
 =item -
 
+Families with "Titling" characters; these "... replace the default glyphs
+with corresponding forms designed specifically for titling.
+These may be all-capital and/or larger on the body,
+and adjusted for viewing at larger sizes"
+(according to the OpenType Specification).
+
+=item -
+
 An ornament family, also in roman, italic and slanted shapes.
 
 =back
@@ -1861,6 +1986,10 @@
 inferior characters; usually only digits and some punctuation,
 normal forms for other characters
 
+=item I<Titl>
+
+Titling characters; see above.
+
 =item I<Orn>
 
 ornaments
@@ -1877,11 +2006,22 @@
 
 The individual 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",
+I<< <shape> >> is either empty, "sc" or "swash",
 and I<< <enc> >> is the encoding (also in lowercase).
 A typical name in this scheme would be "FiraSans-Light-osf-sc-ly1".
 
 
+=head2 About the log file
+
+B<autoinst> writes some info about what it thinks it's doing to a log file.
+By default this is called F<< <fontfamily>.log >>,
+but this choice can be overridden by the user;
+see the I<-logfile> command-line option in L</"COMMAND-LINE OPTIONS"> below.
+If this log file already exists, B<autoinst> will append its data to the end
+rather than overwrite it.
+Use the I<-verbose> command-line option to ask for more detailed info.
+
+
 =head2 A note for MiKTeX users
 
 Automatically installing the fonts into a suitable TEXMF tree
@@ -2014,31 +2154,36 @@
 
 =head2 NFSS codes
 
-I<< B<CAVEAT>: this functionality was almost completely rewritten in release 2019-03-14.
+I<< B<CAVEAT>: this functionality was almost completely rewritten
+in release 2019-03-14.
 Older versions tried to map all fonts directly to short NFSS codes,
 but often had to invent non-standard codes in order to deal with the
 many different weights and widths that occur in the wild.
-These non-standard NFSS codes used by older versions of B<autoinst> will no longer
+Such non-standard NFSS codes will no longer
 work for fonts installed with newer versions; for those you'll have to either
 use the long names or stick to the standard NFSS codes.
-This change mainly concerns very light or very heavy weights and very condensed widths;
-for more moderate weights and widths, existing code will very probably continue to work.
+(This change mainly concerns very light or very heavy weights
+and very condensed widths;
+for more moderate weights and widths,
+existing code will very probably continue to work.)
 >>
 
 LaTeX's New Font Selection System (NFSS)
 identifies fonts by a combination of family,
 series (the concatenation of weight and width), shape and size.
-B<autoinst> parses the font's metadata (more precisely: the output of C<otfinfo --info>)
+B<autoinst> parses the font's metadata
+(more precisely: the output of C<otfinfo --info>)
 to determine these parameters.
-When this fails (usually because the font family contains uncommon weights, widths
-or shapes),
+When this fails (usually because the font family contains uncommon weights,
+widths or shapes),
 B<autoinst> ends up with different fonts having the I<same> values
 for these font parameters; such fonts cannot be used in NFSS,
 since there's no way distinguish them.
-When B<autoinst> detects such a situation, it will print an error message and abort.
+When B<autoinst> detects such a situation, it will print an error message
+and abort.
 If that happens, either rerun B<autoinst> on a smaller set of fonts,
-or add the missing widths, weights and shapes to the tables C<%NFSS_WIDTH>,
-C<%NFSS_WEIGHT> and C<%NFSS_SHAPE>, near the top of the source code.
+or add the missing widths, weights and shapes to the tables C<NFSS_WIDTH>,
+C<NFSS_WEIGHT> and C<NFSS_SHAPE>, near the top of the source code.
 Please also send a bug report (see L<AUTHOR> below).
 
 The mapping of shapes to NFSS codes is done using the following table:
@@ -2049,58 +2194,44 @@
     Italic, Cursive, Kursive            it
     Oblique, Slant(ed), Incline(d)      sl
 
-(I<Exception:> Adobe Silentium Pro contains two Roman shapes; we map the first of these
-to "n", for the second one we [ab]use the "it" code as this family doesn't contain
-an Italic shape.)
+(I<Exception:> Adobe Silentium Pro contains two Roman shapes;
+we map the first of these to "n", for the second one we (ab)use the "it" code
+as this family doesn't contain an Italic shape.)
 
-The mapping of weights and widths to NFSS code is a more complex, two-step proces.
+The mapping of weights and widths to NFSS codes is a more complex,
+two-step proces.
 In the first step, all fonts are assigned a "series" name that is simply
-the concatenation of its full weight and width (after expanding any abbreviations
-and converting to lowercase).
-So a font with "Cond" width and "Ultra" weight will be known as "ultrablackcondensed".
+the concatenation of its weight and width
+(after expanding any abbreviations and converting to lowercase).
+A font with "Cond" width and "Ultra" weight will then be known
+as "ultrablackcondensed".
 
 In the second step, B<autoinst> tries to map all combinations of NFSS codes
 (ul, el, l, sl, m, sb, b, eb and ub for weights;
 uc, ec, c, sc, m, sx, x, ex and ux for widths) to actual fonts.
-Of course, not all 81 combinations of these NFSS weights and widths will map to
-existing fonts; and conversely it may not be possible to assign every existing font
+Of course, not all 81 combinations of these NFSS weights and widths will map
+to existing fonts;
+and conversely it may not be possible to assign every existing font
 a unique code in a sane way (especially on the weight axis, some font families
 offer more choices or finer granularity than NFSS's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional "Medium" weight between Regular and Semibold).
 
-This mapping between NFSS codes and actual fonts is based on a few principles:
+B<autoinst> tries hard to ensure that the most common NFSS codes
+(and high-level commands such as C<\bfseries>,
+which are built on top of those codes) will "just work".
 
-=over 4
+To see exactly which NFSS codes map to which fonts, see the log file
+(pro tip: run B<autoinst> with the I<-dryrun> option
+to check the chosen mapping beforehand).
+The I<-nfssweight> and I<-nfsswidth> command-line options can be used
+to finetune the mapping between NFSS codes and fonts.
 
-=item B<Usefulness>. As many of the most commonly used NFSS codes as possible
-should point to actual fonts.
+To access specific weights or widths,
+one can always use the C<\fontseries> command with the full series name
+(i.e., C<\fontseries{demibold}\selectfont>).
 
-=item B<Exactness>. Exact matches always win: if the font family contains
-a Semibold Condensed font, that's what the "sbc" code will map to.
 
-=item B<Sanity>. A code like "sb" will always map to something semi-boldish.
-If there's no Semibold font it might map to Demibold or Medium,
-but never to Black. If there is no close match, the NFSS code will simply not be used.
-
-=item B<Well-ordering>. The mapping respects the ordering that is inherent in
-the NFSS codes, so "sb" will be heavier than "m" and lighter than "b".
-
-=item B<Uniqueness>. No two NFSS codes will map to the same font (with the exception
-of "bx"; since this is so ubiquitous in Latex, B<autoinst> will treat it as a synonym
-for "b" if there is no BoldExtended font).
-
-=back
-
-These rules should ensure that the standard NFSS codes (and high-level commands
-such as C<\bfseries>, which are built on top of these codes) will "just work".
-To access specific weights or widths, use the C<\fontseries> command with
-the full series name (i.e., C<\fontseries{demibold}\selectfont>).
-
-To see exactly which NFSS codes map to which fonts, please refer to
-the generated F<fd> files.
-
-
 =head1 COMMAND-LINE OPTIONS
 
 B<autoinst> tries hard to do The Right Thing (TM) by default,
@@ -2117,15 +2248,26 @@
 
 =item B<-dryrun>
 
-Don't generate any output files; only parse the input fonts and create
-F<autoinst.log> showing which fonts would have been generated.
+Don't generate output; just parse input fonts and write
+a log file saying what it would have done.
 
+=item B<-logfile>=I<filename>
+
+Write log data to F<filename> instead of the default F<< <fontfamily>.log >>.
+If the file already exist, B<autoinst> appends to it;
+it doesn't overwrite an existing file.
+
+=item B<-verbose>
+
+Add more details to the log file. Repeat this option for even more info.
+
 =item B<-encoding>=I<encoding[,encoding]>
 
-Generate the specified encoding(s) for the text fonts. Multiple text encodings may be
-specified as a comma-separated list: C<-encoding=OT1,T1,LY1> (without spaces!).
-The generated style file passes these encodings to F<fontenc> in the specified order,
-so the last one will become the default text encoding for your document.
+Generate the specified encoding(s) for the text fonts.
+Multiple encodings may be specified as a comma-separated list:
+C<-encoding=OT1,T1,LY1> (without spaces!).
+The style file passes these to F<fontenc> in the specified order,
+so the I<last> one will become the default text encoding of your document.
 
 The default choice of encodings is "OT1,T1,LY1".
 For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>!)
@@ -2140,19 +2282,14 @@
 if the text encodings (see I<-encoding> above) include T1,
 B<-nots1> otherwise.
 
-=item B<-sanserif>
+=item B<-serif>, B<-sanserif>, B<-typewriter>
 
-Install the font as a sanserif font, accessed via C<\sffamily> and C<\textsf>.
+Install the font as a serif, sanserif or typewriter font, respectively.
+This changes how you access the font in LaTeX: with C<\rmfamily>/C<\textrm>,
+C<\sffamily>/C<\textsf> or C<\ttfamily>/C<\texttt>.
 The generated style file redefines C<\familydefault>,
 so including it will still make this font the default text font.
 
-=item B<-typewriter>
-
-Install the font as a typewriter font, accessed via C<\ttfamily> and
-C<\texttt>.
-The generated style file redefines C<\familydefault>,
-so including it will still make this font the default text font.
-
 =item B<-lining> / B<-nolining>
 
 Control the creation of fonts with lining figures. The default is
@@ -2184,7 +2321,7 @@
 
 =item B<-titling> / B<-notitling>
 
-Control the creation of titling fonts. The default is B<-titling>.
+Control the creation of titling families. The default is B<-titling>.
 
 =item B<-superiors> / B<-nosuperiors>
 
@@ -2202,10 +2339,9 @@
 in the list "subs", "sinf" or "dnom" that is supported by the fonts.
 The default value is "none".
 
-I<< Note that if you specify a style of inferiors that isn't
-present in the font, B<autoinst> silently falls back to its default behaviour
-of not creating fonts with inferiors; it doesn't try to substitute one of
-the other features. >>
+I<< If you specify a style of inferiors that isn't present in the font,
+B<autoinst> will fall back to its default behaviour of not creating fonts
+with inferiors at all; it won't try to substitute one of the other styles. >>
 
 =item B<-fractions> / B<-nofractions>
 
@@ -2212,9 +2348,15 @@
 Control the creation of fonts with numerators and denominators.
 The default is B<-nofractions>.
 
-=item B<-ornaments> / B<-noornaments>
+=item B<-ligatures> / B<-noligatures>
 
-Control the creation of ornament fonts. The default is B<-ornaments>.
+Some fonts create glyphs for the standard f-ligatures (ff, fi, fl, ffi, ffl),
+but don't provide a "liga" feature to access these.
+This option tells B<autoinst> to add extra C<LIGKERN> rules to
+the generated fonts to enable the use of these ligatures.
+Since this option is rarely necessary
+(most fonts with f-ligatures do provide the matching "liga" feature),
+the default is B<-noligatures>.
 
 =item B<-defaultlining> / B<-defaultoldstyle>
 
@@ -2241,10 +2383,29 @@
 
 =item B<-mergewidths> / B<-nomergewidths>
 
-Some font families put Condensed, Narrow, Extended etc. fonts in separate families;
-this option tells B<autoinst> to merge those separate families into the main family.
-The default is B<-nomergewidths>.
+Some font families put their Condensed, Narrow, Extended etc. widths
+in separate families;
+this option tells B<autoinst> to merge those separate families into
+the main family.
+The default is B<-mergewidths>.
 
+=item B<-mergesmallcaps> / B<-nomergesmallcaps>
+
+Even more annoyingly, some font families put their small caps fonts
+in a separate family;
+this option tells B<autoinst> to merge the small caps fonts into
+the main family.
+The default is B<-mergesmallcaps>.
+
+=item B<-nfssweight>=I<code>=I<weight>, B<-nfsswidth>=I<code>=I<width>
+
+Map the NFSS code I<code> to the given weight or width,
+overriding the built-in tables.
+Each of these options may be given multiple times,
+to override more than one NFSS code.
+Example: to map the "ul" code to the "Thin" weight, use C<-nfssweight=ul=thin>.
+To inhibit the use of the "ul" code completely, use C<-nfssweight=ul=>.
+
 =item B<-extra>=I<text>
 
 Append I<text> as extra options to the command lines for I<otftotfm>.
@@ -2254,7 +2415,8 @@
 =item B<-manual>
 
 Manual mode; for users who want to post-process the generated files and commands.
-By default, B<autoinst> immediately executes all F<otftotfm> commands it generates;
+By default, B<autoinst> immediately executes all F<otftotfm> commands
+it generates;
 in manual mode, these are instead written to a file F<autoinst.bat>.
 Furthermore it tells F<otftotfm> to generate human readable (and editable)
 F<pl/vpl> files instead of the default F<tfm/vf> ones,
@@ -2272,7 +2434,8 @@
 =item B<-> move all generated files to a proper TEXMF tree,
 and, if necessary, update the filename database;
 
-=item B<-> tell TeX about the new F<map> file (usually by running C<updmap> or similar).
+=item B<-> tell TeX about the new F<map> file
+(usually by running C<updmap> or similar).
 
 =back
 
@@ -2334,11 +2497,11 @@
 
 Marc Penninga (F<marcpenninga at gmail.com>)
 
-When sending a bug report, please give as much relevant information as
-possible.
-If you see any error messages
-(whether from B<autoinst> itself, from the I<LCDF TypeTools>, from Perl
-or from the OS), include these I<verbatim>; don't paraphrase.
+When sending a bug report, please give as much relevant information as possible;
+this usually includes (but may not be limited to) the log file
+(please add the I<-verbose> command-line option, for extra info).
+If you see any error messages, please include these I<verbatim>;
+don't paraphase.
 
 
 =head1 COPYRIGHT
@@ -2371,6 +2534,31 @@
 
 =over 12
 
+=item I<2019-04-22>
+
+Fixed a bug in the generation of swash shapes.
+
+=item I<2019-04-19>
+
+Fixed a bug that affected -mergesmallcaps with multiple encodings.
+
+=item I<2019-04-16>
+
+Added the <-mergesmallcaps> option, to handle cases where
+the small caps fonts are in separate font families.
+Titling shape is now treated as a separate family instead of a distinct shape;
+it is generated only for fonts with the 'titl' feature.
+Only add f-ligatures to fonts when explicitly asked to (<-fligatures>).
+
+=item I<2019-04-11>
+
+Tried to make the log file more relevant.
+Added the I<-nfssweight> and I<-nfsswidth> options,
+and finetuned the automatic mapping between fonts and NFSS codes.
+Changed the name of the generated log file to F<< <fontfamily>.log >>,
+and revived the I<-logfile> option to allow overriding this choice.
+Made I<-mergewidths> the default (instead of I<-nomergewidths>).
+
 =item I<2019-04-01>
 
 Fine-tuned the decision where to put generated files;
@@ -2381,16 +2569,20 @@
 put all generated files into a subdirectory C<./autoinst_output/>
 instead of all over the current working directory.
 
-Added to "auto" value to the I<inferiors> option,
+Added "auto" value to the I<inferiors> option,
 to tell B<autoinst> to use whatever inferior characters are available.
 
-=item I<2019-03-14> (never released to CTAN)
+=item I<2019-03-14>
 
+(never released to CTAN)
+
 Overhauled the mapping of fonts (more specifically of weights and widths;
-the mapping of shapes didn't change) to NFSS codes. Instead of inventing our own codes
-to deal with every possible weight and width out there, we now create "long" codes
-based on the names in the font metadata. Then we add "ssub" rules to the F<fd>
-files to map the standard NFSS codes to our fancy names (see the section B<NFSS codes>;
+the mapping of shapes didn't change) to NFSS codes.
+Instead of inventing our own codes to deal with every possible weight
+and width out there, we now create "long" codes based on the names
+in the font metadata.
+Then we add "ssub" rules to the F<fd> files to map the standard NFSS codes
+to our fancy names (see the section B<NFSS codes>;
 based on discussions with Frank Mittelbach and Bob Tennent).
 
 =item I<2018-08-10>
@@ -2433,7 +2625,7 @@
 
 =item I<2015-11-22>
 
-Bugfix: Latex doesn't like command names with dashes in it.
+Bugfix: LaTeX doesn't like command names with dashes in it.
 
 =item I<2015-05-13>
 

Modified: trunk/Master/texmf-dist/scripts/fontools/ot2kpx
===================================================================
--- trunk/Master/texmf-dist/scripts/fontools/ot2kpx	2019-05-02 22:47:24 UTC (rev 50946)
+++ trunk/Master/texmf-dist/scripts/fontools/ot2kpx	2019-05-02 22:48:32 UTC (rev 50947)
@@ -4,7 +4,7 @@
 
 ----------------------------------------------------------------------------
 
-    Copyright (C) 2005-2013 Marc Penninga.
+    Copyright (C) 2005-2019 Marc Penninga.
 
     This program is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
@@ -34,12 +34,24 @@
 use warnings;
 
 use integer;
+use Getopt::Long ();
 use List::Util @List::Util::EXPORT_OK;
 use Pod::Usage;
 
-our ($NUM_GLYPHS, $UNITS_PER_EM, %KPX);
+our ($NUM_GLYPHS, $UNITS_PER_EM, %kern);
 
 sub main {
+    %ARGV = (
+        print_func  =>  \&print_kpx,
+    );
+
+    Getopt::Long::GetOptions(
+        'help|?'    =>  sub { pod2usage(-verbose => 0); },
+        'doc'       =>  sub { pod2usage(-verbose => 2); },
+        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx; },
+        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx; },
+        'lua'       =>  sub { $ARGV{print_func} = \&print_lua; },
+    ) or pod2usage(-verbose => 0);
     pod2usage(-verbose => 0) if @ARGV != 1;
 
     my %font = OTF::get_tables($ARGV[0]);
@@ -65,7 +77,7 @@
 
         for my $subtable (@subtables) {
             my $pos_format = unpack 'n', $subtable;
-            if ($pos_format == 1) { 
+            if ($pos_format == 1) {
                 OTF::GPOS::parse_pos_format_1($subtable);
             }
             elsif ($pos_format == 2) {
@@ -77,21 +89,57 @@
         }
     }
 
-    my $num_kernpairs = sum map { scalar keys %{$KPX{$_}} } keys %KPX;
+    &{$ARGV{print_func}}( \%kern, \@glyph_name );
+    return;
+}
+
+# ------------------------------------------------------------------------
+# Print kerning data in Adobe's KPX format
+# ------------------------------------------------------------------------
+sub print_kpx {
+    my %kern = %{ shift @_; };
+    my @glyph = @{ shift @_; };
+
+    my $num_kernpairs = sum map { scalar keys %{$kern{$_}} } keys %kern;
     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";
+    for my $l (sort { $glyph[$a] cmp $glyph[$b] } keys %kern) {
+        my $l_glyph = $glyph[$l];
+        for my $r (sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}}) {
+            print "KPX $l_glyph $glyph[$r] ",
+                  "$kern{$l}{$r}\n";
         }
     }
     print "EndKernPairs\nEndKernData\n";
+}
 
-    return;
+# ------------------------------------------------------------------------
+# Print kerning data as a Luatex custom font feature
+# ------------------------------------------------------------------------
+sub print_lua {
+    my %kern = %{ shift @_; };
+    my @glyph = @{ shift @_; };
+
+    print <<'END_FEATURE_PREFIX';
+fonts.handlers.otf.addfeature {
+    name = 'kern',
+    type = 'kern',
+    data = {
+END_FEATURE_PREFIX
+
+    for my $l ( sort { $glyph[$a] cmp $glyph[$b] } keys %kern ) {
+        print ' ' x 8, "[ '$glyph[$l]' ] = {";
+        for my $r ( sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}} ) {
+            print "\n", ' ' x 12, "[ '$glyph[$r]' ] = $kern{$l}{$r},";
+        }
+        print " },\n";
+    }
+
+    print <<'END_FEATURE_POSTFIX';
+    }
 }
+END_FEATURE_POSTFIX
+}
 
-
 ########################################################################
 
 
@@ -467,7 +515,7 @@
 }
 
 #-----------------------------------------------------------------------
-# Parse subtable in PairPosFormat 1, store kern pairs in global %KPX
+# Parse subtable in PairPosFormat 1, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_pos_format_1 {
     my $subtable = shift;
@@ -495,7 +543,7 @@
             my ($second, $value)
                 = unpack "n\@${value_offset}s>", $pair_value_record;
             next if $value == 0;
-            $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
+            $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
         }
     }
 
@@ -503,7 +551,7 @@
 }
 
 #-----------------------------------------------------------------------
-# Parse subtable in PairPosFormat 2, store kern pairs in global %KPX
+# Parse subtable in PairPosFormat 2, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_pos_format_2 {
     my $subtable = shift;
@@ -540,7 +588,7 @@
 
             for my $first (@first) {
                 for my $second (@second) {
-                    $KPX{$first}{$second} ||= $value;
+                    $kern{$first}{$second} ||= $value;
                 }
             }
         }
@@ -631,7 +679,7 @@
 package OTF::Kern;
 
 #-----------------------------------------------------------------------
-# Parse "kern"table, store kern pairs in global %KPX
+# Parse "kern"table, store kern pairs in global %kern
 #-----------------------------------------------------------------------
 sub parse_kerntable {
     my $kern = shift;
@@ -653,7 +701,7 @@
             my ($first, $second, $value) = unpack 'nns>', $kern_pair;
             next if $value == 0;
 
-            $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
+            $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM;
         }
     }
 
@@ -688,19 +736,14 @@
 
 =head1 SYNOPSIS
 
-=over 8
+B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<fontfile>
 
-=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>.
+B<ot2kpx> extract the kerning data from OpenType fonts and prints it
+to C<stdout>, either in Adobe's KPX format (for adding to an F<afm> file)
+or as a Luatex custom feature, for use with the C<\directlua> command.
 
 
 =head1 OPTIONS AND ARGUMENTS
@@ -707,9 +750,19 @@
 
 =over 4
 
+=item B<-afm>, B<-kpx>
+
+Output the kerning data in Adobe's KPX format, as used in F<afm> files.
+This is the default output format.
+
+=item B<-lua>
+
+Output the kerning data as a Luatex custom font feature,
+to be included in a C<\directlua> command.
+
 =item B<fontfile>
 
-The OpenType font (in either F<otf> or F<ttf> format).
+The OpenType font (both F<otf> and F<ttf> format are supported).
 
 =back
 
@@ -771,7 +824,7 @@
 
 =head1 COPYRIGHT
 
-Copyright (C) 2005-2013 Marc Penninga.
+Copyright (C) 2005-2019 Marc Penninga.
 
 
 =head1 LICENSE
@@ -798,6 +851,11 @@
 
 =over 12
 
+=item I<2019-04-15>
+
+Added the -lua command-line option to get output in Luatex's
+custom feature format.
+
 =item I<2013-08-07>
 
 Replaced all C<given/when> constructions in the source code by C<if>'s,



More information about the tex-live-commits mailing list