10

A LaTeX package I'm currently writing makes use of -- and definitely requires -- some of the power of LuaLaTeX. I would like to make my package's user interface -- in particular, the options that need to be loaded -- as simple as possible by making the package determine on its own which "font features" have been activated via commands such as \fontspec, \setmainfont, \defaultfontfeatures, and \addfontfeatures that are provided by the fontspec package.

The font features I'm most interested in are ligatures, in particular those called "Common" (activated by +liga), "Required" (+rlig), "Contextual" (+clig), "Historic" (+hlig), and "Discretionary"/"Rare" (+dlig).

Some functionality of the type I'm looking for is mentioned in section 25.3 of the user guide (named "Programmer's interface) of the fontspec manual. However, no specific examples are provided to demonstrate how the macros listed in this section might be used in practice. Moreover, I must confess, I'm not at all familiar with LaTeX3, the LaTeX dialect used by the fontspec package. Thus, I'm in no position to construct a user macro of this type on my own.

My question thus is: How would one write a Boolean test -- likely based on a macro that uses the interface noted in section 25.3 of the fontspec manual -- to query if, say, "historic" ligatures have been activated via one of the methods provided by the fontspec package?

  • 4
    You're probably looking for \fontspec_if_feature:nTF {rawfeature}{true}{false} which could be \let to a more convenient name: \ExplSyntaxOn \cs_new_eq:NN \testforfeature \fontspec_if_feature:nTF \ExplSyntaxOff. This could then be used like feauture hlig is \testforfeature{hlig}{active}{inactive} – clemens Nov 11 '12 at 14:44
  • @cgnieder You should make this into an answer. – egreg Nov 11 '12 at 21:39
  • @egreg After reading the manual again I'm not so sure. It says about \fontspec_if_feature:nTF: “Test whether the currently selected font contains the raw OpenType feature #1.” So the test is apparently not for active features but for existent ones. – clemens Nov 12 '12 at 10:32
9
+100

First of all: there might be better ways to do this. Or at least other recommended ways...

It appears that fontspec updates what it calls a “sclist” with the activated raw features. A sclist is a list separated with a semicolon which means it is basically a token list. The idea would now be to look if a given raw feature is stored in that token list or not. The list containing the raw features appears to be \l_fontspec_rawfeatures_sclist. One can now test with \tl_if_in:NnTF <tokenlistmacro> { tokens } { true } { false } if a given feature is active.

\cs_new:Npn basically is a wrapper for \long\def and \cs_new_eq:NN basically is \let. The arg spec nTF means that the macro has three arguments, the n being a group of tokens given in braces. T and F also are arguments given in braces and are expanded if the test is either true or false, respectively.

\ExplSyntaxOn
% test if active font has feature:
\cs_new_eq:NN \IfFontFeatureExists \fontspec_if_feature:nTF
% test if feature is active:
\cs_new:Npn \mico_fontfeature_if_active:nTF #1
  { \tl_if_in:NnTF \l_fontspec_rawfeatures_sclist { #1 } }
\cs_new_eq:NN \IfFontFeatureActive \mico_fontfeature_if_active:nTF
\ExplSyntaxOff

A whole MWE could now look as follows:

\documentclass{article}
\usepackage{fontspec}
\setmainfont[Numbers=OldStyle]{LinLibertineO}

\ExplSyntaxOn
\cs_new_eq:NN \IfFontFeatureExists \fontspec_if_feature:nTF
\cs_new:Npn \mico_fontfeature_if_active:nTF #1
  { \tl_if_in:NnTF \l_fontspec_rawfeatures_sclist { #1 } }
\cs_new_eq:NN \IfFontFeatureActive \mico_fontfeature_if_active:nTF
\ExplSyntaxOff

\begin{document}

liga \IfFontFeatureExists{liga}{exists}{does not exist},
clig \IfFontFeatureExists{clig}{exists}{does not exist},
rlig \IfFontFeatureExists{rlig}{exists}{does not exist},
hlig \IfFontFeatureExists{hlig}{exists}{does not exist},
dlig \IfFontFeatureExists{dlig}{exists}{does not exist}

liga is \IfFontFeatureActive{liga}{}{not} active,
hlig is \IfFontFeatureActive{hlig}{}{not} active,
dlig is \IfFontFeatureActive{dlig}{}{not} active

\addfontfeatures{Ligatures={Common,Historic}}
liga is \IfFontFeatureActive{liga}{}{not} active,
hlig is \IfFontFeatureActive{hlig}{}{not} active,
dlig is \IfFontFeatureActive{dlig}{}{not} active

\end{document}

enter image description here

  • Any idea why \IfFontFeaturesActive doesn't work right for pnum, tnum, onum, lnum ? – user22108 Nov 25 '13 at 3:19
  • @user22108 No... actually I don't know too much about the innards of fontspec. Maybe you should ask the fontspec maintainer. He should be able to give some insights – clemens Nov 25 '13 at 9:23
  • I hate to have to bother you about this, but your MWE has stopped working. :-( In particular, the \l_fontspec_rawfeatures_sclist macro appears to no longer exist in version 2.5a (dated 2016/02/01) of fontspec. fontspec now provides a somewhat similarly named macro, viz., \l_@@_rawfeatures_sclist. Unfortunately, just replacing the one macro name doesn't restore the MWE to proper working order. May I ask you to look into what may be going on and, hopefullly, get your code to work once more? Thanks so much in advance! – Mico Mar 11 '16 at 5:51
  • @Mico I'll check this in a few hours. If fontspec actually has a @@ macro then this may be an unintended bug. During the build process “@@” should be replaced by “fontspec”. – clemens Mar 11 '16 at 7:37
  • 2
    @Mico it is now called \l__fontspec_rawfeatures_sclist (two underscores after the \l). This means it is no longer a public variable but now is an internal variable. IMHO this is unfortunate: you should have been able to rely on a public variable. You definitely can't rely on an internal one. It maybe worth asking Will for a public interface. – clemens Mar 11 '16 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.