The problem with this font -- as far as its ligatures are concerned -- is that the ligature names in the internal font table are, shall we say, utterly non-standard. For instance, instead of going with standard names such as f_f
and f_f_i
for the ligatures, a search with the FontForge app reveals that the font uses the names Omega
and approxequal
. No joke!! (A not-uncharitable assessment of the situation might be that the font's name correspondence table got garbled at some point prior to compilation.)
Given this situation, it's probably not a surprise that LuaLaTeX and XeLaTeX are not able to figure out the name mappings without special help.
Using LuaLaTeX, I can think of two solutions to this mess. The first solution creates a custom "feature file", which informs the system about the ligature names actually used by the font. The second, shown further below, uses LuaTeX functionality directly to get the ligatures working.
With the help of FontForge I was able to find the "names" for all ten ligatures. These names are used to set up a so-called "Feature File", named addligs_HFTI.fea
, that can be loaded via an instruction such as \addfontfeatures{FeatureFile=addligs_HFTI.fea}
.
Unfortunately, despite having found the font's ligature "names" for all ten ligatures, this approach succeeds in activating only four of them (ct
, ff
, ffi
, and ffl
, to be specific). Maybe something else got garbled as well when the font was compiled?
% !TEX TS-program = lualatex
\RequirePackage{filecontents}
\begin{filecontents*}{addligs_HFTI.fea}
languagesystem DFLT dflt;
languagesystem latn dflt;
# Ligatures
feature liga {
sub a s by summation;
sub i s by Delta;
sub u s by divide;
sub c t by plusminus;
sub f f by Omega;
sub f i by fi;
sub f l by fl;
sub f f i by approxequal;
sub f f l by radical;
} liga;
\end{filecontents*}
\documentclass{article}
\newcommand\liglist{as is ct ff fi fl ffi ffl}
\usepackage{fontspec}
\defaultfontfeatures{Ligatures=Common}
\setmainfont{Historical-FellTypeItalic}
\begin{document}
w/o ligatures: \liglist
\addfontfeatures{FeatureFile=addligs_HFTI.fea}
with ligatures: \liglist
\end{document}
Addendum. Given that the feature file approach doesn't succeed in activating all ten ligatures present in the font, the following solution, which is entirely coded in Lua, may be worth considering. It uses the process_input_buffer
callback to run a function that performs a "brute force" substitution of the ten character pairs and triples with the corresponding glyphs that represent the ligated versions. (Full disclosure: The code used below gratefully uses code originally provided by @michal.h21 in his answer to my recent posting, entitled LuaLaTeX: How to use a \char directive inside a string.gsub function?) Observe that special care had to be taken to ensure that any LaTeX macros that may include strings such as "ff", "fi", etc aren't caught up in the brute-force substitution.
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Historical-FellTypeItalic}
\usepackage{luacode,luatexbase}
\begin{luacode}
local uchar = unicode.utf8.char
function ligsub ( s )
local x = s:gsub('(\\?)([%a%@]+)',
function(back,text)
if back~="" then
return back .. text
end
text = text:gsub ( 'ffi', uchar(8776))
text = text:gsub ( 'ffl', uchar(8730))
text = text:gsub ( 'ff', uchar(937))
text = text:gsub ( 'fi', uchar(64257))
text = text:gsub ( 'fl', uchar(64258))
text = text:gsub ( 'as', uchar(8721))
text = text:gsub ( 'is', uchar(916))
text = text:gsub ( 'us', uchar(247))
text = text:gsub ( 'ct', uchar(177))
text = text:gsub ( 'st', uchar(9674))
return text
end)
print("x", x)
return x
end
\end{luacode}
\AtBeginDocument{%
\directlua{luatexbase.add_to_callback (
"process_input_buffer", ligsub, "ligsub" )}}
\newcommand\off{off} % dummy macro (see below)
\begin{document}
off fit fly office baffle
as is us act step
\off --note: no ff-ligature
\end{document}
Remark: The only downside I can see to taking this approach is that it's definitely going to mess up the work of a screen-reader: eight of the ten ligatures -- those for ff
, ffi
and fl
, as
, is
, us
, ct
, and st
-- get rendered as Ω
, ≈
, √
, Σ
, Δ
, ±
, and ◊
, respectively. Argghh. (In contrast, fi
and fl
do get rendered correctly; probably not coincidentally, those are the two ligatures that have a "normal" name in the feature file, which was shown earlier.) That's not really the fault of the LuaLaTeX-based approach, though; rather, the font's messed-up name tables are to blame. Ideally, the authors and/or maintainers of the font would re-release it, this time with the name table cleaned up drastically.
In my view, the following ligature suppression rules are needed.
In order to enable the fi
ligature, suppress the is
, iv
, and ix
ligatures if is
/iv
/ix
is preceded by f
;
In order to enable the sp
and st
ligatures, suppress the is
ligature if is
is followed by either p
or t
.
In the jargon of Opentype fonts, fi
is called a common ligature, and is
, iv
, and ix
, as well as sp
and st
, are called rare or discretionary ligatures.
The following solution, which works under LuaLaTeX (but not under XeLaTeX), employs the selnolig package. (Full disclosure: I'm the main author of the selnolig
package.) The ligature suppression rules given above are implemented via several \nolig
instructions:
\nolig{fis}{fi|s} % break up 'is' lig. if preceded by 'f'
\nolig{fiv}{fi|v} % break up 'iv' lig. if preceded by 'f'
\nolig{fix}{fi|x} % break up 'ix' lig. if preceded by 'f'
\nolig{isp}{i|sp} % break up 'is' lig. if followed by 'p'
\nolig{ist}{i|st} % break up 'is' lig. if followed by 't'
More concisely, one would write:
\nolig{fi[svx]}{fi|.}
\nolig{is[pt]}{i|s.}
The .
character after the |
is shorthand for "any glyph". I'm not sure if the increase in terseness and density is worth the cost of reduced (human) legibility.
If one wanted to suppress the is
, iv
, and ix
ligatures globally, while still allowing other "rare" ligatures to be used, a single \nolig
instruction would do the job:
\nolig{i[svx]}{i|.}
In the following code, the upright shape of Junicode
is used for the iv
and ix
cases, and the italic shape is used of Garamond Premier Pro
is used for the sp
and st
ligatures. The first data row shows the outcome with selnolig
being "on"; for comparison, the second data row shows the outcome with selnolig
being turned "off".
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{fontspec,booktabs}
\setmainfont[Ligatures = Rare,
ItalicFeatures = {Scale = MatchLowercase},
ItalicFont = {Garamond Premier Pro Italic}]
{Junicode}
\setsansfont[Scale=MatchLowercase]{Palatino Sans Com}
\usepackage{selnolig}
\nolig{fis}{fi|s} % break up 'is' lig. if preceded by 'f'
\nolig{fiv}{fi|v} % break up 'iv' lig. if preceded by 'f'
\nolig{fix}{fi|x} % break up 'ix' lig. if preceded by 'f'
\nolig{isp}{i|sp} % break up 'is' lig. if followed by 'p'
\nolig{ist}{i|st} % break up 'is' lig. if followed by 't'
%% Or, more concisely:
% \nolig{fi[svx]}{fi|.}
% \nolig{is[pt]}{i|s.}
\begin{document}
\noindent
\begin{tabular}{@{}lll@{}}
\textsf{selnolig} & Junicode: iv, ix & \em Gar.\ Prem.\ Pro Italic: is\\
\midrule
On & five fix affix & \em fish fissure fist gist lisp\\[0.5ex]
\selnoligoff % turn off selnolig's operations
Off & five fix affix & \em fish fissure fist gist lisp\\
\end{tabular}
\end{document}
Best Answer
Some thing like this using feature files should work:
First the feature file:
The order of the above is important, this way regular “ft” and “fft” are used even with
Rare
ligatures, but not withHistoric
.The glyph names should match those in the font with
f_t.alt
being the name of the unwanted “ft” ligature, andf_t
&f_f_t
being the names of the wanted ones.The full feature file syntax is documented by Adobe (but LuaTeX supports v1.6 f the syntax + FontForge extension, not the current one, so there are some differences).
Then it can be applied to the font by using
FeatureFile
fontspec option: