54

As of version 2.7 of luaotfload the support for font feature files (.fea) has been dropped.

On the ConTeXt mailing list Hans showed how to make font substitution work through Lua. More examples are available in the latest ConTeXt distribution (001, 002, 003, 004, 005, 006, 007)

In the past I have been using font feature files to adjust the kerning of fonts on-the-fly. From Hans' example it is not clear to me how to adjust kerning in the new syntax. The below example does not work as intended.

\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
    name = "kern",
    {
        type = "pair",
        data = {
            [0x0041] = { [0x0056] = { false, { -200, 0, 0, 0 } } },
        }
    }
}
}
\setmainfont{Latin Modern Roman}
\begin{document}
AV
\end{document}

Can we have a comprehensive guide on how to adjust font features with LuaTeX with the fonts.handlers technique?


Related questions:

(These involve hooking into the luaotfload.patch_font callback)

Henri Menke
  • 109,596

2 Answers2

66

Crimson is useful for experimenting with the new approach, because it’s free and defines few of the features it could support. Here are the features defined in its latest version:

       | r | i | b | bi | sb si |
|------+---+---+---+----+-------|
| c2sc | ✓ | ✓ | ✓ |    |       |
| kern | ✓ | ✓ | ✓ | ✓  | ✓     |
| liga |   |   |   | ✓  |       |
| onum | ✓ | ✓ |   | ✓  |       |
| ordn | ✓ |   |   |    |       |
| pnum | ✓ | ✓ |   | ✓  | ✓     |
| smcp | ✓ | ✓ | ✓ |    |       |
| zero | ✓ |   |   |    |       |

Ligatures

It’s most surprising that liga is defined only in the bold italic face, so let’s fix that first.

Here’s Crimson before we add the feature:

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Crimson}
\begin{document}
The five baffled officials flew off.

\textit{The five baffled officials flew off.} \end{document}

output of example

Now here’s the fix:

\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
    name = "liga",
    {
        type = "ligature",
        data = {
            ['f_f'] = { "f", "f" },
            ['f_i'] = { "f", "i" },
            ['f_f_i'] = { "f", "f", "i" },
            ['f_l'] = { "f", "l" },
            ['f_f_l'] = { "f", "f", "l" },
            ['T_h'] = { "T", "h" },
        }
    },
    "some ligatures"
  }
}
\setmainfont{Crimson}
\begin{document}
The five baffled officials flew off.

\textit{The five baffled officials flew off.} \end{document}

output of second example

In ['f_i'] = { "f", "i" }, ['f_i'] is the glyph name of the ligature, and { "f", "i" } are the letters to be ligatured. So if your font calls the ligature ‘fi’ rather than ‘f_i’, you should write ['fi'] = { "f", "i" }. Also note that, in some fonts, ['f_f_b'] = { "f", "f", "b" } doesn’t work, but ['f_f_b'] = { "ff", "b" } does.

As Ulrike Fischer explains in tex.stackexchange.com/a/352864 and in her answer to this question, if you have updated luaotfload recently (4 February 2017), you will need to revise the invocation of \directlua as follows:

\directlua{
  fonts.handlers.otf.addfeature{
    name = "liga",
    type = "ligature",
    data = {
      ['f_f'] = { "f", "f" },
      ['f_i'] = { "f", "i" },
      ['f_f_i'] = { "f", "f", "i" },
      ['f_l'] = { "f", "l" },
      ['f_f_l'] = { "f", "f", "l" },
      ['T_h'] = { "T", "h" },
    },
  }
}

Stylistic and Contextual Alternates

Some alternates are desirable or not depending on what’s nearby. For example, Crimson’s long-tailed ‘Q’ is attractive before ‘u,’ but looks silly or collides with other glyphs if it comes at the end of a word. Compare salt, which replaces a glyph by an alternate everywhere, and calt, which replaces it in some contexts only:

\documentclass{article}
\usepackage{fontspec}
\directlua{
  fonts.handlers.otf.addfeature{
    name = "salt",
    type = "alternate",
    data =
    {
      Q = "Q.alt01",
    },
  }
  fonts.handlers.otf.addfeature{
    name = "calt",
    type = "chainsubstitution",
    lookups = {
      {
        type = "substitution",
        data = {
          ["Q"] = "Q.alt01",
        },
      },
    },
    data = {
      rules = {
        {
          after  = { { "u" } },
          current = { { "Q" } },
          lookups = { 1 },
        },
      },
    },
  }
}
\setmainfont{Crimson}
\begin{document}
(Questions about NASDAQ.) Meh.

{\addfontfeature{RawFeature=+salt} (Questions about NASDAQ.) Oops!}

{\addfontfeature{RawFeature=+calt} (Questions about NASDAQ.) That’s better.} \end{document}

output of example

If Crimson had a long-tailed Q in its small caps, you’d get it by adding a line like this: ["q.sc"] = "q.scalt01",.

Superiors

Here I’ve found the principle, or part of it, but it’s probably better not applied to Crimson, because superiors 4–9 and 0 are designed to sit higher than superiors 1–3, as is especially noticeable in note 10 below:

\documentclass{article}
\usepackage{fontspec,realscripts}
% see Ulrike’s answer at tex.stackexchange.com/a/235302/7883
\renewcommand\footnotemarkfont{\addfontfeature{RawFeature={+sups}}}
\renewcommand\fakesuperscript[1]{#1}
\usepackage[paperwidth=180pt,paperheight=150pt,margin=12pt]{geometry}
\directlua{
fonts.handlers.otf.addfeature {
    name = "sups",
    {
        type = "substitution",
        data = {
            one = "¹",
            ["one.onum"] = "¹",
            two = "²",
            ["two.onum"] = "²",
            three = "³",
            ["three.onum"] = "³",
            four = "⁴",
            ["four.onum"] = "⁴",
            five = "⁵",
            ["five.onum"] = "⁵",
            six = "⁶",
            ["six.onum"] = "⁶",
            seven = "⁷",
            ["seven.onum"] = "⁷",
            eight = "⁸",
            ["eight.onum"] = "⁸",
            nine = "⁹",
            ["nine.onum"] = "⁹",
            zero = "⁰",
            ["zero.onum"] = "⁰",
        }
    },
    "footnote figures"
  }
}
\setmainfont{Crimson}
\begin{document}
There\footnote{Note.} are\footnote{Note.} far\footnote{Note.}
too\footnote{Note.} many\footnote{Note.}  footnotes\footnote{Note.}
in\footnote{Note.} this\footnote{Note.}  little\footnote{Note.}
sentence.\footnote{Note.}
\end{document}

sample of sups feature

You’ll have to add more such lines (e.g., ["one.prop"] = "¹", etc.,) if you want to have footnote figures whether you’re using the default figures, old-style figures, proportional figures, the slashed zero, or any other sort of figure provided.

For the luaotfload of February 2017, use \directlua this way:

\directlua{
  fonts.handlers.otf.addfeature{
    name = "sups",
    type = "substitution",
    data = {
      one = "¹",
      ["one.onum"] = "¹",
      two = "²",
      ["two.onum"] = "²",
      three = "³",
      ["three.onum"] = "³",
      four = "⁴",
      ["four.onum"] = "⁴",
      five = "⁵",
      ["five.onum"] = "⁵",
      six = "⁶",
      ["six.onum"] = "⁶",
      seven = "⁷",
      ["seven.onum"] = "⁷",
      eight = "⁸",
      ["eight.onum"] = "⁸",
      nine = "⁹",
      ["nine.onum"] = "⁹",
      zero = "⁰",
      ["zero.onum"] = "⁰",
    },
  }
}

Remove a ligature

Crimson isn’t of much use to illustrate removal of ligatures, so here’s FPL Neu (github.com/rstub/fplneu) without its ‘fk’ ligature:

\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
    name = "nofk",
    {
        type = "multiple",
        data = {
          ["f_k"] = { "f", "k" },
        }
    },
    "get rid of fk ligatures"
  }
}
\setmainfont{FPL Neu}
\begin{document}
Kafka

\addfontfeature{RawFeature=+nofk} Kafka \end{document}

output of example

The result is hardly visible in a font like Garamond Premier Pro, with its long-armed f, and I can’t seem to combine this nofk feature with extra kerning.

For the luaotfload of February 2017, use \directlua this way:

\directlua{
  fonts.handlers.otf.addfeature{
    name = "nofk",
    type = "multiple",
    data = {
      ["f_k"] = { "f", "k" },
    },
  }
}

Select among standard ligatures

Some fonts put more in their liga feature than one could wish. For example, LTC Kaatskill Pro, a lovely Goudy design, makes œ a standard rather than a discretionary ligature, with the result that not only words like ‘œdema’ but even ‘does’ and ‘poem’ are affected. Using type = "multiple", as for ‘fk’ above, would fix ‘does’ but interfere with ‘œdema,’ so we need another approach.

To illustrate, let’s examine a freely available Carolingian minuscule. With liga, it produces results one could use to ease students into a paleography course:

\documentclass[12pt,latin]{octavo}
\usepackage{babel,fontspec,microtype}
\setmainfont{0850 Carolina Tours}
\linespread{1.10345}
\begin{document}
Invocat te, Domine, fides mea quam dedisti mihi, quam inspirasti mihi
per humanitatem Filii tui, per ministerium praedicatoris tui.
\end{document}

output

For decorative rather than scholarly purposes, we’d want to remove whatever is defined in liga but unfamiliar to contemporary readers.

Besides the harmless ‘ff,’ ‘fi,’ ‘fl,’ ‘ft,’ and ‘ll,’ liga adds an ‘oe’ ligature and e caudata for ‘ae’; it also replaces ‘i’ and ‘j’ with their dotless versions, and substitutes ‘ſ’ for ‘s,’ ‘u’ for ‘v,’ and ‘V’ for ‘U.’ We can remove those ligatures and substitutions by turning off liga, and add back the harmless ligatures by defining them as rlig, a feature which is on by default:

\documentclass[12pt,latin]{octavo}
\usepackage{babel,fontspec,microtype}
\directlua{
  fonts.handlers.otf.addfeature{
    name = "rlig",
    type = "ligature",
    data = {
      ['f_f'] = { "f", "f" },
      ['fi'] = { "f", "i" },
      ['fl'] = { "f", "l" },
      ['f_t'] = { "f", "t" },
      ['l_l'] = { "l", "l" },
    },
  }
}
\setmainfont{0850 Carolina Tours}[
  Ligatures=NoCommon]
\linespread{1.10345}
\begin{document}
Invocat te, Domine, fides mea quam dedisti mihi, quam inspirasti mihi
per humanitatem Filii tui, per ministerium praedicatoris tui.
\end{document}

output

Stubborn fonts

Sometimes one or more ligatures don’t work, and adding them as above doesn’t help. This happens when a font’s lookups define the ligatures in the wrong order, as Khaled Hosny remarks. Fixing the problem without editing the font itself can be quite difficult if the lookups are especially complex, but often there’s no need to edit the font.

For example, Goudy’s Newstyle defines ‘fi’ and ‘fl’ in its liga feature, and slightly different ‘fi’ and ‘fl’ glyphs in its dlig feature. There are also glyphs for ‘ct,’ ‘fb,’ ‘ff,’ ‘ffi,’ ‘fj,’ ‘ffl,’ ‘fk,’ ‘st,’ and (in the italic) ‘Th,’ but no feature is defined to ease their use. Adding the two-character ligatures to liga works, but adding the ‘ffi’ and ‘ffl’ ligatures doesn’t, apparently because the ‘fi’ and ‘fl’ ligatures are already in the lookup. But all is well if we turn off liga and define the ligatures we want as rlig:

\documentclass{article}
\usepackage{fontspec}
\directlua{
  fonts.handlers.otf.addfeature{
    name = "rlig",
    type = "ligature",
    data = {
      ['ffi'] = { "f", "f", "i" },
      ['ffl'] = { "f", "f", "l" },
      ['fb'] = { "f", "b" },
      ['ff'] = { "f", "f" },
      ['fh'] = { "f", "h" },
      ['fi'] = { "f", "i" },
      ['fj'] = { "f", "j" },
      ['fk'] = { "f", "k" },
      ['fl'] = { "f", "l" },
    },
  }
  fonts.handlers.otf.addfeature{
    name = "ilig",
    type = "ligature",
    data = {
      ['Th'] = { "T", "h" },
      ['Th.swsh'] = { "T.swsh", "h" },
    },
  }
}
\setmainfont{Newstyle}[
  Script=Default,
  Ligatures=NoCommon,
  Numbers=OldStyle,
  ItalicFeatures={RawFeature=+ilig}]
\begin{document}
The five baffled officials flew off.

\textit{The five baffled officials flew off.}

\textit{\addfontfeatures{Style=Swash}The five baffled officials flew off.} \end{document}

output

If a font’s liga feature contains many ligatures, it’s easier to keep liga on, break up only the problematic ligatures, and then restore them in rlig. For example, this produces the same output as above:

\documentclass{article}
\usepackage{fontspec}
\directlua{
  fonts.handlers.otf.addfeature{
    name = "nolg",
    type = "multiple",
    data = {
      ['fi'] = { "f", "i" },
      ['fl'] = { "f", "l" },
    },
  }
  fonts.handlers.otf.addfeature{
    name = "rlig",
    type = "ligature",
    data = {
      ['ffi'] = { "f", "f", "i" },
      ['ffl'] = { "f", "f", "l" },
      ['fb'] = { "f", "b" },
      ['ff'] = { "f", "f" },
      ['fh'] = { "f", "h" },
      ['fi'] = { "f", "i" },
      ['fj'] = { "f", "j" },
      ['fk'] = { "f", "k" },
      ['fl'] = { "f", "l" },
    },
  }
  fonts.handlers.otf.addfeature{
    name = "ilig",
    type = "ligature",
    data = {
      ['Th'] = { "T", "h" },
      ['Th.swsh'] = { "T.swsh", "h" },
    },
  }
}
\setmainfont{Newstyle}[
  Script=Default,
  Numbers=OldStyle,
  ItalicFeatures={RawFeature=+ilig},
  RawFeature=+nolg]
\begin{document}
The five baffled officials flew off.

\textit{The five baffled officials flew off.}

\textit{\addfontfeatures{Style=Swash}The five baffled officials flew off.} \end{document}

CAVEAT

I don’t really understand what I’ve done, and there may be better ways (which I’d be glad to learn about), but at least things are more or less working.

ADDENDUM

With some trepidation, I’ve created my first (and probably last) GitHub repository, where I’ll gradually put notes on fonts I’ve tried to fix. That should prevent this answer from becoming cluttered with discussions of typefaces to which few have access, save others with the same fonts from duplicating my labor, and perhaps allow for joint discovery of more satisfactory solutions.

Thérèse
  • 12,679
  • This is really great, I wish I could upvote you more. Do you, by any chance, also know, how to deactivate a certain ligature? In German texts the ligature f_k is frowned upon, and I used to remove it via a liga feature sub \f_k by \f \k; – FredFisch Jul 15 '16 at 20:34
  • 1
    @FredFisch Before I work on this, have you tried selnolig? – Thérèse Jul 15 '16 at 22:09
  • Yes. The thing is that using selnolig I can't manually kern the pairs anymore which get broken up by the package. If there is no ligature, then the glyphs should not "touch" each other; unfortunately this is not possible with selnolig; see this question: http://tex.stackexchange.com/q/315123 – FredFisch Jul 16 '16 at 09:08
  • 1
    @FredFisch I’ve added a way to remove ligatures, but your kerning problem remains. I know little about German typography, but I get the best results for French texts with fonts made by French designers. It’s an enormous job to adapt a font for use with a language to which the designer wasn’t sensitive. – Thérèse Jul 16 '16 at 18:38
  • Thank you very much for your effort! What is your ressource that you used to produce these examples? – FredFisch Jul 16 '16 at 22:46
  • 5
    @FredFisch I keep staring at texlive/2016/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua, especially lines 1305–1326 and 1816–1943, guess at its meaning, and spend time in trial-and-error. I’d love to see documentation by someone who understands these things and isn’t just guessing. – Thérèse Jul 16 '16 at 23:02
  • 1
    It's possible to add another fonts.handlers.otf.addfeature into the same \directlua statement (named e.g. ktest of type kern, just like in Ulrikes answer, for the pair f, k), and to reference it like this: \setmainfont[RawFeature={+nofk,+ktest}]{Linux Libertine O} -- but the behaviour is very erratic! The inter-letter space changes on every compilation; very weird... Documentation is clearly missing... – FredFisch Jul 16 '16 at 23:10
  • Excellent post! Can you provide an example using character classes such as @uppercase? – meide Aug 30 '16 at 17:31
  • @meide Do you mean for producing something like a calt or init feature? I wish I knew how to do that. It would probably begin like type = "chainsubstitution", or type = "chainposition", but I don't know how it would continue. I’ll experiment if I have time (maybe ten months from now…). – Thérèse Aug 30 '16 at 19:23
  • Yeah, I think. It's really hard to find documentation for how the addfeature stuff works.... – meide Aug 30 '16 at 19:47
  • Thank you continuously improving your answer. Very useful! – Henri Menke Feb 15 '17 at 08:12
  • Your answer doesn't address the mysterious [0x0041] = { [0x0056] = { false, { -200, 0, 0, 0 } } }, syntax the question has. Is that sequence valid and if so, what does it do and how? I have problems setting up kerning in LuaLaTeX myself ... – lblb May 19 '17 at 16:53
  • @lblb Since the O.P. asked for a comprehensive guide, and since Ulrike Fischer had already written an answer about kerning, I decided to address other items that would go into a comprehensive guide. There are certainly many more parts needed before this page is comprehensive, but no single answer has to be comprehensive. Does Mrs. Fischer’s answer help with your question? If not, she’s better placed to answer you than I am, since I haven’t done much experimentation with kerning yet. – Thérèse May 19 '17 at 17:04
  • @Thérèse I'm sorry to re-up the subject. But I have made some code with contextual ligatures that no longer works (and I don't know why, probably some more change in Lua). Something seems to be broken with 'lookups'. By any chance do you know why? – R. Alexandre Jan 09 '20 at 13:57
  • @R.Alexandre The example above still works for me; if you post your code somewhere, I’ll take a look. – Thérèse Jan 09 '20 at 14:04
  • @Thérèse That would be very nice of you, thank you. https://tex.stackexchange.com/questions/523572/ligature-font-feature-no-longer-works – R. Alexandre Jan 09 '20 at 14:13
  • The long-tailed Q didn't work for me, but the others did. I use Overleaf with TeX Live version 2019. – Someone Aug 28 '20 at 15:09
  • @Someone With Crimson or with some other font? Crimson has been revised since I wrote this answer, so some parts may need adjusting. – Thérèse Aug 28 '20 at 18:34
  • @Thérèse I used Crimson. – Someone Aug 30 '20 at 00:28
  • @Someone The above example of changing the tail of Q with salt and calt still works for me in Overleaf. Have you modified the example in any way? – Thérèse Aug 30 '20 at 00:44
  • No, I doubt so. I only used calt, not salt. – Someone Aug 30 '20 at 00:52
  • @Someone Hmmm. If you post a MWE somewhere, I may be able to figure it out. – Thérèse Aug 30 '20 at 01:17
  • Is there a difference between alternate and substitution? – Weißer Kater Aug 26 '22 at 14:53
31

This here (an adaption of the example from the context list) works for me

Edit on February 2017

The syntax seems to have changed. data and type are no longer in a subtable and the explaining text does harm. The new code working for me (in a current TeXLive 2016 and in MiKTeX) is

\documentclass{article}
\usepackage{fontspec}
\directlua
{
 fonts.handlers.otf.addfeature 
  {
    name = "ktest",
    type = "kern",
    data = 
        {
            ["A"] = { ["V"] =  -200 },
        },
  }
 }
\setmainfont{Latin Modern Roman}[RawFeature=+ktest]
\setsansfont{Latin Modern Roman}

\begin{document} AV \sffamily AV \end{document}

Old version

\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
    name = "ktest",
    {
        type = "kern",
        data = {
            ["A"] = { ["V"] =  -200 },
        }
    },
    "extra kerns"
}
}
\setmainfont{Latin Modern Roman}[RawFeature=+ktest]
\setsansfont{Latin Modern Roman}

\begin{document} AV \sffamily AV \end{document}

enter image description here

But there are imho quite a number of open questions regarding the correct syntax (instead of ["A"] A alone seems to work too) and the values (what unit is -200)? How should such extra features be named? Do they all need a name? How can packages implement such features and avoid clashes with other packages?

Ulrike Fischer
  • 327,261
  • Thank you very much for solving the specific example from my question! The actual question however is, whether we can have a review of what is possible and how it can be done with fonts.handlers. The issue of the syntax not being final is minor, as an answer can always be updated later. – Henri Menke May 30 '16 at 08:17
  • 2
    BTW: In the feature file syntax -200 would correspond to -200/1000em. – Henri Menke May 30 '16 at 08:21
  • 6
    @HenriMenke: As you saw in the context list answer you can get quite fast working code from Hans to specific questions. What you seldom get it good documentation. It is even unclear if the interface is stable. So it is up to us to improve the situation. Imho we should try to extend this question and its answers to a definite "how to manipulate kernings" reference. And create more questions for other handlers. – Ulrike Fischer May 30 '16 at 08:37
  • 1
    I experimented a bit: The description string "extra kerns" seems to be optional (nothing happens when I leave it out). When I use name = "kern", the feature is automatically applied together with all other entries in the kern feature. This seems more convenient than having to declare an extra feature. So far, I haven't found out how to make vertical kerning work (a.k.a. positioning in the feature files), how to adjust kerning around a single character, and how to adjust kerning when the partner is a space (I can't choose 0x0020, because space in TeX is handled differently). – Henri Menke May 31 '16 at 09:07
  • I have checked again and the units of kerning are (as in the feature files) 1/1000em. – Henri Menke May 31 '16 at 09:13
  • Just noticed something very strange: if I try to adjust the kerning of a second pair of letters by adding the line ["A"] = { ["W"] = -200 }, after ["A"] = { ["V"] = -200 }, the adjustment to the pair “AV” vanishes. – Thérèse Jun 25 '16 at 20:05
  • 3
    @Thérèse: You should add the W-setting to the existing table for A. ["A"] = { ["V"] = -200 , ["W"] = -200 }, (but curiously the 200 leads to a much larger kerning now.) – Ulrike Fischer Jun 25 '16 at 20:12
  • @HenriMenke Simple question from an ignorant: is there any way to use glyph names instead of unicode like [0x0041] as argument of data = {...} ? – Paolo Polesana Oct 06 '16 at 14:45
  • 1
    @PaoloPolesana Yes, you can. For a simple example see this answer of mine (it is a ConTeXt answer but the Lua part will stay the same for LaTeX). – Henri Menke Oct 06 '16 at 19:19
  • @PaoloPolesana: My example use glyph names ("A"), so I don't understand the question. – Ulrike Fischer Oct 06 '16 at 19:27
  • @UlrikeFischer Defining a ligature, I found that the string ['Iacute'] = { "afii10026", "acutecmb"} does not apply. The glyph names are taken from the Adobe standard. After some trials I found that ['Iacute'] = { "И", 0x0301} works perfectly. So: some glyph names are accepted, while other not. Which is the standard? – Paolo Polesana Oct 07 '16 at 06:41
  • 1
    @HenriMenke Thank you: anyway I'm still confused... I see a lot of way to call the characters it these examples: "A", [0x0041], 'f_i' for ligatures, also 'iacute' from Adobe glyph names, "Q.alt01", "uni1E9E.smcp"... This is for me a complete mess! I need some reference to order my knowledge... – Paolo Polesana Oct 07 '16 at 06:50
  • 1
    @PaoloPolesana The problem is that the fonts are a mess here. Naming is highly inconsistent. – Henri Menke Oct 07 '16 at 07:35
  • @HenriMenke I also found that in some position of the string some names are consistent, while in other not: in defining a ligature ['Iacute'] = { "afii10026", "acutecmb"} does not apply. The glyph names are taken from the Adobe standard. After some trials I found that ['Iacute'] = { "И", 0x0301} works perfectly. Here I had to mix 'direct typing' (cyrillic И type) and this '0x0301' unicode standard... How to understand it? I didn't even know there was so many ways to call a type!!! – Paolo Polesana Oct 07 '16 at 07:40
  • I agree, the syntax is a bit confusing, regarding to glyph names. As to unit of "-200", I believe it is standard PS unit, that is 1 thousandth of em, and -200 is -20% type size – Yan Zhou Feb 28 '17 at 08:41
  • 2
    @Someone I approved the edit, but I would really prefer if you don't do such cosmetics edits which don't add anything useful to an four years old answer and cost only time to review. – Ulrike Fischer Aug 28 '20 at 15:25