TUGboat, Volume 38 (2017), No. 2 203

Variable instance, . The details might matter even more as they can now be exaggerated Hans Hagen when some transformation is applied. 1 Introduction There is currently (March 2017) not much in- formation about these fonts so what I say next may History shows the tendency to recycle ideas. Often be partially wrong or at least different from what is quite some effort is made by historians to figure intended. The perspective will be one from a TEX out what really happened, not just long ago, when user and coder. Whatever you think of them, these nothing was written down and we have to do with fonts will be out there and for sure there will be stories or pictures at most, but also in recent times. nice examples circulating soon. And so, when I ran Descriptions can be conflicting, puzzling, incomplete, into a few experimental fonts, with PostScript and partially lost, biased, . . . TrueType outlines, I decided to have a look at what Just as language was invented (or evolved) sev- is inside. After all, because it’s visual, it’s also fun eral times, so were scripts. The same might be true to play with. Let’s stress that at the moment of this for rendering scripts on a medium. Semaphores came writing I only have a few simple fonts available, fonts and went within decades and how many people know that are designed for testing and not usage. Some now that they existed and that encryption was in- recommended tables were missing and no complex volved? Are the old printing presses truly the old OpenType features are used in these fonts. ones, or are older examples simply gone? One of the nice aspects of the internet is that one can now more 2 The specification easily discover similar solutions for the same problem, but with a different (and independent) origin. I’m not that good at reading specifications, first of So, how about this “new big thing” in tech- all because I quickly fall asleep with such documents, nology: variable fonts. In this case, history shows but most of all because I prefer reading other stuff (I do have lots of books waiting to be read). I’m also that it’s not that new. For most TEX users the names METAFONT and MetaPost will ring bells. They someone who has to play with something in order to have a very well documented history so there is not understand it: trial and error is my modus operandi. much left to speculation. There are articles, books, Eventually it’s my intended usage that drives the pictures, examples, sources, and more around for interface and that is when everything comes together. decades. So, the ability to change the appearance Exploring this technology comes down to: locate of a glyph in a font depending on some parameters a font, get the OpenType 1.8 specification from the is not new. What probably is new is that creating website, and try to figure out what is in the variable fonts is done in the natural environment font. When I had a rough idea the next step was to where fonts are designed: an interactive program. get to the shapes and see if I could manipulate them. The METAFONT toolkit demands quite some insight Of course it helped that in ConTEXt we already can in programming shapes in such a way that one can load fonts and play with shapes (using MetaPost). change look and feel depending on parameters. There I didn’t have to install and learn other programs. are not that many meta fonts made and one reason is Once I could render them, in this case by creating a that making them requires a certain mind- and skill virtual font with inline PDF literals, a next step was set. On the other hand, faster computers, interactive to apply variation. Then came the first experiments programs, evolving web technologies, where real-time with a possible user interface. Seeing more variation rendering and therefore more or less real-time tweak- then drove the exploration of additional properties ing of fonts is a realistic option, all play a role in needed for typesetting, like features. acceptance. The main extension to the data packaged in a But do interactive font design programs make font file concerns the (to be discussed) axis along this easier? You still need to be able to translate which variable fonts operate and deltas to be applied ideas into usable beautiful fonts. Taking the common to coordinates. The gdef table has been extended shapes of glyphs, defining extremes and letting a and contains information that is used in gpos fea- program calculate some interpolations will not always tures. There are new hvar, vvar and mvar tables bring good results. It’s like morphing a picture of that influence the horizontal, vertical and general your baby’s face into yours of old age (or that of your font dimensions. The gvar table is used for TrueType grandparent): not all intermediate results will look variants, while the cff2 table replaces the cff table great. It’s good to notice that variable fonts are a for OpenType PostScript outlines. The avar and revival of existing techniques and ideas used in, for stat tables contain some meta-information about the axes of variations.

Variable fonts 204 TUGboat, Volume 38 (2017), No. 2

It must be said that because this is new tech- kern, scaled from general dimensions to the current nology the information in the standard is not always size of the font. easy to understand. The fact that we have two ren- When the outlines of glyphs are needed in Meta- dering techniques, PostScript cff and TrueType ttf, fun the font is also converted from its binary form also means that we have different information and to something in Lua, but this time we filter the perspectives. But this situation is not much different shapes. For a cff this comes down to interpreting from OpenType standards a few years ago: it takes the charstrings and reducing the complexity to time but in the end I will get there. And, after all, moveto, lineto and curveto operators. In the pro- users also complain about the lack of documentation cess subroutines are inlined. The result is something for ConTEXt, so who am I to complain? In fact, it will that MetaPost is happy with but that also can be be those ConTEXt users who will provide feedback turned into a piece of a PDF. and make the implementation better in the end. We now come to what a variable font actually is: a basic design which is transformed along one or 3 Loading more axes. A simple example is wider shapes: Before we discuss some details, it will be useful to summarize what the font loader does when a user requests a font at a certain size and with specific features enabled. When a font is used the first time, We can also go taller and retain the width: its binary format is converted into a form that makes it suitable for use within ConTEXt and therefore Lua- TEX. This conversion involves collecting properties of the font as a whole (official names, general di- mensions like x-height and em-width, etc.), of glyphs Here we have a linear scaling but glyphs are not (dimensions, Unicode properties, optional math prop- normally done that way. There are font collections erties), and all kinds of information that relates to out there with lots of intermediate variants (say from (contextual) replacements of glyphs (small caps, old- light to heavy) and it’s more profitable to sell each style, scripts like Arabic) and positioning (kerning, variant independently. However, there is often some anchoring marks, etc.). In the ConTEXt font loader logic behind it, probably supported by programs that this conversion is done in Lua. designers use, so why not build that logic into the font The result is stored in a condensed format in a and have one file that represents many intermediate cache and the next time the font is needed it loads in forms. In fact, once we have multiple axes, even when an instant. In the cached version the dimensions are the designer has clear ideas of the intended usage, untouched, so a font at different sizes has just one nothing will prevent users from tinkering with the copy in the cache. Often a font is needed at several axis properties in ways that will fulfil their demands sizes and for each size we create a copy with scaled but hurt the designers’ eyes. We will not discuss that glyph dimensions. The feature-related dimensions dilemma here. (kerning, anchoring, etc.) are shared and scaled when When a variable font follows the route described needed. This happens when sequences of characters above, we face a problem. When you load a TrueType in the node list get converted into sequences of glyphs. font it will just work. The glyphs are packaged in We could do the same with glyph dimensions but the same format as static fonts. However, a variable one reason for having a scaled copy is that this copy font has axes and on each axis a value can be set. can also contain virtual glyphs and these have to be Each axis has a minimum, maximum and default. scaled beforehand. In practice there are several layers It can be that the default instance also assumes of caching in order to keep the memory footprint some transformations are applied. The standard within reasonable bounds.1 recommends adding tables to describe these things When the font is actually used, interaction be- but the fonts that I played with each lacked such tween characters is resolved using the feature-related tables. So that leaves some guesswork. But still, just information. When for instance two characters need loading a TrueType font gives some sort of outcome, to be kerned, a lookup results in the injection of a although the dimensions (widths) might be weird due to lack of a (default) axis being applied. 1 In retrospect one can wonder if that makes sense; just An OpenType font with PostScript outlines is look at how much memory a browser uses when it has been different: the internal cff format has been upgraded open for some time. In the beginning of LuaTEX users won- dered about caching fonts, but again, just look at how much to cff2 which on the one hand is less complicated browsers cache. but on the other hand has a few new operators —

Hans Hagen TUGboat, Volume 38 (2017), No. 2 205 which results in programs that have not been adapted 4 Shapes complaining or simply quitting on them. For OpenType PostScript shapes we always have One could argue that a font is just a resource to do a dummy rendering in order to get the right and that one only has to pass it along but that’s bounding box information. For TrueType this in- not what works well in practice. Take LuaTEX. We formation is already present but not when we use a can of course load the font and apply axis values so variable instance, so I had to do a bit of coding for that we can process the document as we normally that. Here we face a problem. For TEX we need the do. But at some point we have to create a PDF. We width, height and depth of a glyph. Consider the can simply embed the TrueType files but no axis following case: values are applied. This is because, even if we add the relevant information, there is no way in current PDF formats to deal with it. For that, we should be able to pass all relevant axis-related information as well as specify what values to use along these axes. And for TrueType fonts this information is not part of the shape description so then we in fact The shape has a bounding box that fits the need to filter and pass more. An OpenType Post- shape. However, its left corner is not at the origin. Script font is much cleaner because there we have the So, when we calculate a tight bounding box, we information needed to transform the shape mostly cannot use it for actually positioning the glyph. We in the glyph description. There we only need to do use it (for horizontal scripts) to get the height and carry some extra information on how to apply these depth but for the width we depend on an explicit so-called blend values. The region/axis model used value. In OpenType PostScript we have the width there only demands passing a relatively simple table available and how the shape is positioned relative to (stripped down to what we need). But, as said above, the origin doesn’t much matter. In a TrueType shape cff2 is not backward-compatible so a viewer will a bounding box is part of the specification, as is the (currently) simply not show anything. width, but for a variable font one has to use so-called Recalling how we load fonts, how does that trans- phantom points to recalculate the width and the test late with variable changes? If we have two characters fonts I had were not suitable for investigating this. with glyphs that get transformed and that have a At any rate, once I could generate documents kern between them, the kern may or may not trans- with typeset text using variable fonts it became time form. So, when we choose values on an axis, then not to start thinking about a user interface. A variable only glyph properties change but also relations. We font can have predefined instances but of course a no longer can share positional information and scale user also wants to mess with axis values. Take one afterwards because each instance can have different of the test fonts: Adobe Variable Font Prototype. It values to start with. We could carry all that infor- has several instances: mation around and apply it at runtime but because extralight It looks like this! weight=0 contrast=0 we’re typesetting documents with a static design it’s light It looks like this! weight=150 contrast=0 regular It looks like this! weight=394 contrast=0 more convenient to just apply it once and create an semibold It looks like this! weight=600 contrast=0 instance. We can use the same caching as mentioned bold It looks like this! weight=824 contrast=0 black high contrast It looks like this! weight=1000 contrast=100 before but each chosen instance (provided by the black medium contrast It looks like this! weight=1000 contrast=50 font or made up by user specifications) is kept in the black It looks like this! weight=1000 contrast=0 cache. As a consequence, using a variable font has no overhead, apart from initial caching. Such an instance is accessed with: So, having dealt with that, how do we proceed? \definefont[MyLightFont] Processing a font is not different from what we al- [name:adobevariablefontprototypelight*default] ready had. However, I would not be surprised if users The Avenir Next variable demo font (currently) are not always satisfied with, for instance, kerning, provides: because in such fonts a lot of care has to be given to this by the designer. Of course I can imagine that regular It looks like this! weight=400 width=100 medium It looks like this! weight=500 width=100 programs used to create fonts deal with this, but bold It looks like this! weight=700 width=100 even then, there is a visual aspect to it too. The heavy It looks like this! weight=900 width=100 good news is that in ConT Xt we can manipulate condensed It looks like this! weight=400 width=75 E medium condensed It looks like this! weight=500 width=75 features so in theory one can create a so-called font bold condensed It looks like this! weight=700 width=75 goodie file for a specific instance. heavy condensed It looks like this! weight=900 width=75

Variable fonts 206 TUGboat, Volume 38 (2017), No. 2

Before we continue I will show a few examples of variable shapes. Here we use some Metafun magic. Just take these definitions for granted. \startMPcode draw outlinetext.b ("\definedfont [name:adobevariablefontprototypeextralight]% Figure 1: Four variants foo@bar") (withcolor "gray") (withcolor red withpen pencircle scaled 1/10) ten the information about axis values from the font xsized .45TextWidth ; means that the font handler has to be adapted to \stopMPcode keep caching correct. Another definition is: \startMPcode draw outlinetext.b ("\definedfont \definefontfeature[lightdefault] [name:adobevariablefontprototypelight]% [default] foo@bar") [axis={weight:230,contrast:50}] (withcolor "gray") \definefont[MyLightFont] (withcolor red withpen pencircle scaled 1/10) [name:adobevariablefontprototype*lightdefault] xsized .45TextWidth ; Here the complication is that where normally \stopMPcode features are dealt with after loading, the axis feature \startMPcode is part of the preparation (and caching). If you want draw outlinetext.b ("\definedfont the virtual font solution you can do this: [name:adobevariablefontprototypebold]% \definefontfeature[inlinelightdefault] foo@bar") [default] (withcolor "gray") [axis={weight:230,contrast:50}, (withcolor red withpen pencircle scaled 1/10) variableshapes=yes] xsized .45TextWidth ; \definefont[MyLightFont] \stopMPcode [name:adobevariablefontprototype \startMPcode *inlinelightdefault] draw outlinetext.b When playing with these fonts it was hard to see ("\definefontfeature[whatever]% [axis={weight:350}]% if loading was done right. For instance not all values \definedfont make sense. It is beyond the scope of this article, but [name:adobevariablefontprototype*whatever]% axes like weight, width, contrast and italic values get foo@bar") applied differently to so-called regions (subspaces). (withcolor "gray") So say that we have an x coordinate with value (withcolor red withpen pencircle scaled 1/10) 50. This value can be adapted in, for instance, four xsized .45TextWidth ; subspaces (regions), so we actually get: \stopMPcode x0 = x + s × x + s × x + s × x + s × x The results are shown in figure 1. What we see 1 1 2 2 3 3 4 4 here is that as long as we fill the shape everything The (here) four scale factors sn are determined will look as expected but using an outline only won’t. by the axis value. Each axis has some rules about The crucial (control) points are moved to different how to map the values 230 for weight and 50 for locations and as a result they can end up inside the contrast to such a factor. And each region has its shape. Giving up outlines is the price we evidently own translation from axis values to these factors. need to pay. Of course this is not unique for variable The deltas x1, . . . , x4 are provided by the font. For fonts although in practice static fonts behave better. a PostScript-based font we find sequences like: To some extent we’re back to where we were with 1 hsetvstorei METAFONT and (for instance) Computer Modern: 120 [10 -30 40 -60] 1 hblendi ... hoperatori because these originate in bitmaps (and probably 100 120 [10 -30 40 -60] [30 -10 -30 20] use similar design logic) we also can have overlap 2 hblendi ... hoperatori and bits and pieces pasted together and no one will A store refers to a region specification. From notice that. The first outline variants of Computer there the factors are calculated using the chosen Modern also had such artifacts while in the static values on the axis. The deltas are part of the glyph Latin Modern successors, outlines were cleaned up. specification. Officially there can be multiple region The fact that we need to preprocess an instance specifications, but how likely it is that they will be but only know how to do that when we have got- used in real fonts is an open question.

Hans Hagen TUGboat, Volume 38 (2017), No. 2 207

For TrueType fonts the deltas are not in the effect of having a converter for both outline types glyph specification but in a dedicated gvar table. meant that it was trivial to create a virtual font apply x deltas [10 -30 40 -60] to x 120 at runtime. This option will stay in ConTEXt as apply y deltas [30 -10 -30 20] to y 100 pseudo-feature variableshapes. Here the deltas come from tables outside the When trying to support variable fonts I tried to glyph specification and their application is triggered limit the impact on the backend code. Also, process- by a combination of axis values and regions. ing features and such was not touched. The inclusion The following two examples use Avenir Next of the right shapes is done via a callback that re- Variable and demonstrate that kerning is adapted to quests the blob to be injected in the cff or glyf the variant. table. When implementing this I actually found out that the LuaTEX backend also does some juggling \definefontfeature[default:shaped][default] of charstrings, to serve the purpose of inlining sub- [axis={width:10}] routines. In retrospect I could have learned a few \definefont[SomeFont] [file:avenirnextvariable*default:shaped] tricks faster by looking at that code but I never re- -0.144 -0.072 alized that it was there. Looking at the code again, Coming back to the use of in electronic publishing: many of the new -0.072 -0.072 -0.120 -0.072 typographers receive their knowledge and information about the rules of typogra- it strikes me that the whole inclusion could be done -0.072 -0.072 -0.072 phy from books, from computer magazines or the instruction manuals which they with Lua code and some day I will give that a try. -0.072 -0.144 -0.072 -0.072 -0.072 get with the purchase of a PC or software. There is not so much basic instruction, -0.432 -0.072 -0.144 -0.072 as of now, as there was in the old days, showing the differences between good and 6 Conclusion -0.072 -0.072 -0.120 -0.432 -0.072 bad typographic design. Many people are just fascinated by their PC’s tricks, and -0.120 -0.072 -0.072 -0.072 -0.072 -0.144 think that a widely-praised program, called up on the screen, will make everything When I first heard about variable fonts I was confi- -0.120 -0.072 -0.144 automatic from now on. Hermann Zapf dent that when they showed up they could be sup- ported. Of course a specimen was needed to prove \definefontfeature[default:shaped][default] this. A first implementation demonstrates that in- [axis={width:100}] deed it’s no big deal to let ConTEXt with LuaTEX \definefont[SomeFont] handle such fonts. At the conference Adam Twar- [file:avenirnextvariable*default:shaped] doch demonstrated the website axis-praxis.org, -0.144 -0.216 Coming back to the use of typefaces in electronic publishing: -0.144 -0.216 and we currently can support most of the fonts there many of the new typographers receive their knowledge and in- -0.120 -0.144 -0.216 -0.072 -0.216 formation about the rules of typography from books, from com- quite well. puter magazines or the instruction manuals which they get with Of course we need to fill in some gaps which can -0.216 -0.144 -0.216 -0.216 -0.216 the purchase of a PC or software. There is not so much basic in- be done once we have complete fonts. And then of -0.432 -0.216 struction, as of now, as there was in the old days, showing the -0.216 -0.216 -0.144 course users will demand more control. In the mean- differences between good and bad typographic design. Many -0.216 -0.120 -0.576 -0.072 -0.120 people are just fascinated by their PC’s tricks, and think that time the helper script that deals with identifying -0.144 -0.216 -0.144 -0.216 -0.216 a widely--praised program, called up on the screen, will make fonts by name has been extended and the relevant -0.120 -0.216 -0.144 everything automatic from now on. Hermann Zapf code has been added to the distribution. At some point the ConTEXt Garden will provide the LuaTEX 5 Embedding binary that has the callback. Once we’re done typesetting and a PDF file has to I end with a warning. On the one hand this tech- be created there are three possible routes: nology looks promising but on the other hand one can easily get lost. Probably most such fonts operate over • We can embed the shapes as PDF images (inline a well-defined domain of values but even then one literal) using virtual font technology. We cannot should be aware of complex interactions with features use so-called xforms here because we want to like positioning or replacements. Not all combina- support color selectively in text. tions can be tested. It’s probably best to stick to • We can wait till the PDF format supports such fonts that have all the relevant tables and don’t de- fonts, which might happen but even then we pend on properties of a specific rendering technology. might be stuck for years with viewers getting Although support is now present in the core there. Also documents need to get printed, and of ConTEXt the official release will happen at the when printer support might arrive is another ConTEXt meeting in 2017. By then I hope to have unknown. tested more fonts. Maybe the interface has also been • We can embed a regular font with shapes that extended by then because after all, TEX is about match the chosen values on the axis. This solu- control. tion is way more efficient than the first.  Hans Hagen Once I could interpret the right information in Pragma ADE the font, the first route was the way to go. A side http://pragma-ade.com

Variable fonts