Mark to base positioning

Tutorial
by Rainer Erich Scheichelbauer

12 December 2014 Published on 13 October 2012

Important: As of version 1.3.17, the mark and mkmk features are built automatically if there are combining marks with top and _top anchors present in the font. Glyphs 2 and later also auto-builds the ccmp feature. So you do not need to fiddle around with feature code anymore. However, if you do want to make your own feature coding, then note that, since version 2, dotlessi and dotlessj have been renamed to idotless and jdotless, respectively.

Tip: In the mekkablue Glyphs Scripts on GitHub, you will find a script called Combining Accent Maker in the Anchors subfolder. The script builds combining accents from your spacing marks.

Combining marks

You may have noticed the Unicode Block from U+0300 to U+036F, also known as Combining Diacritical Marks. For instance, you can encode an ñ (n with a tilde) simply as U+00F1 LATIN SMALL LETTER N WITH TILDE. This is called a precomposed character. Or, you can write U+006E LATIN SMALL LETTER N followed by the combining diacritical mark U+0303 COMBINING TILDE. The latter variation is called a decomposition. Both ways to encode are considered equivalent.

The fact that the encoding can be split into the base letter and the accent has a few advantages. You can, for instance, encode any combination of letters and accents: you just encode the letter and add the combining accent afterwards. You can even stack accents if you want to: just add more than one combining accent.

For combining accents, glyph rendering is suggested to be done with zero width (‘nonspacing’) and negative left sidebearing. That’s because they are supposed to combine with the preceding letter. But OpenType actually knows a better way to combine letters with accents: mark positioning.

Mark to base positioning

We can define an anchor in the base glyph and an anchor in the accent. The anchors can be used to combine letter and accent on the fly. This sounds pretty much like what we do for precomposed diacritics, without actually building them straight away.

I assume we already have base letters, like A to Z and a to z. So we start by creating the combining accents. As always, we simply create new glyphs with the appropriate names. To find out the right names, choose Glyph Info from the Window menu and type ‘comb’ in the search field:

Alright, choose Add Glyphs… from the Font menu and enter a few glyph names for combining accents. To keep it simple, I’ll limit this example to these:

grave=gravecomb
acute=acutecomb
circumflex=circumflexcomb

By preceding the acutecomb with acute=, you’ll create the acutecomb with an acute component. This way, you don’t need to copy and paste or redraw your accents. Unless you want to control the position of the mark, you do not need to set the width of your combining marks to zero. Glyphs will do that automatically at export:

Now, we can add our OpenType feature code. Since we will employ some bits of code that need to be outside of class and feature definitions, we’ll add a Prefix. In your Font Info (Cmd-I), go to the Features tab, click and hold the plus button in the bottom left corner and pick Prefix. Give it a better name than the default ‘xxxx’, for instance ‘Positioning’:

First, we’ll define a class called @MARK_TOP_CENTER, but we will do it in a weird way. Assuming our x-height is 500, we’ll type:

markClass [gravecomb acutecomb circumflexcomb] <anchor 0 500> @MARK_TOP_CENTER;

This defines a class of accents (‘marks’ in OpenType-speak) called @MARK_TOP_CENTER. The class consists of the three marks we listed above: gravecomb, acutecomb and circumflexcomb. It also defines a connecting anchor at x=0, y=500. So far, so good.

Now is a good time to add a feature called ccmp, which is the layout tag for Glyph Composition/Decomposition. It can substitute Glyphs with a version that is prepared for mark positioning. In our case, we should substitute i by dotlessi and j by dotlessj whenever a combining accent follows. In other words, we remove their dots so they can take other accents:

feature ccmp {
  # Glyph Composition/Decomposition
  sub i' @MARK_TOP_CENTER by dotlessi;
  sub j' @MARK_TOP_CENTER by dotlessj;
} ccmp;

Okay. Now comes the stick-em-together part. We add a feature called mark (Mark Positioning). For the sake of shortness, I’ll limit it to a few lowercase glyphs:

feature mark {
  # Mark to Base positioning
  pos base [a n] <anchor 310 500> mark @MARK_TOP_CENTER;
  pos base [c e g o] <anchor 290 500> mark @MARK_TOP_CENTER;
  pos base [dotlessi dotlessj] <anchor 130 500> mark @MARK_TOP_CENTER;
  pos base [b h l] <anchor 130 700> mark @MARK_TOP_CENTER;
} mark;

What each line does is define an anchor position for marks from the class @MARK_TOP_CENTER. That’s all we wanted, right? Theoretically, it should already work, right?

Naw, a few formalities still need to be done, sorry. We have to define all base glyphs as base glyphs and all mark glyphs as mark glyphs. We do this with a so-called GDEF (glyph definition) table:

@BASE = [ a n c e g o b h l dotlessi dotlessj ];
@MARKS = [ @MARK_TOP_CENTER ];

table GDEF {
  GlyphClassDef @BASE,,@MARKS,;
} GDEF;

The commas with nothing between them are important. Because GlyphClassDef defines base glyphs, ligature glyphs, mark glyphs and component glyphs, comma-separated and in that order. And since we only have base and mark glyphs in our example, we need to leave the second and fourth position free. I know it looks weird, but that’s how it works.

In any event, we ought to be good to go now. Let’s see, this is what we have so far:

markClass [gravecomb acutecomb circumflexcomb] <anchor 0 500> @MARK_TOP_CENTER;

feature ccmp {
  # Glyph Composition/Decomposition
  sub i' @MARK_TOP_CENTER by dotlessi;
  sub j' @MARK_TOP_CENTER by dotlessj;
} ccmp;

feature mark {
  # Mark to Base positioning
  pos base [a n] <anchor 310 500> mark @MARK_TOP_CENTER;
  pos base [c e g o] <anchor 290 500> mark @MARK_TOP_CENTER;
  pos base [dotlessi dotlessj] <anchor 130 500> mark @MARK_TOP_CENTER;
  pos base [b h l] <anchor 130 700> mark @MARK_TOP_CENTER;
} mark;

@BASE = [ a n c e g o b h l dotlessi dotlessj ];
@MARKS = [ @MARK_TOP_CENTER ];

table GDEF {
  GlyphClassDef @BASE,,@MARKS,;
} GDEF;

Let’s try it out: export into InDesign’s Fonts folder, switch to InDesign and type a letter plus a combining accent. But wait, how do we type a combining accent? You can use your OS X Character Viewer for this:

And it works. In InDesign we can, for instance, type an n with a circumflex. Since we use two different glyphs, we can even give the accent a different color:

Bottom accents

Wait, we still need to do this for bottom accents like cedilla. Okay, hit Cmd-Shift-G, paste cedilla=cedillacomb, andhit Generate (again, you do not need to set cedillacomb’s width to zero):

Then, go back to the OpenType features, add a markClass definition for bottom accents and call it @MARK_BOT_CENTER:

markClass cedillacomb <anchor 0 0> @MARK_BOT_CENTER;

Note that, unlike with the top accents above, I didn’t use brackets to define a class, since I only have a single bottom accent. (At least in this example.)

Extend the pos rules in the mark feature with the bottom accents:

feature mark {
  # Mark to Base positioning
  pos base [a n] <anchor 310 500> mark @MARK_TOP_CENTER
                 <anchor 310 0>   mark @MARK_BOT_CENTER;
  pos base [c e g o] <anchor 290 500> mark @MARK_TOP_CENTER
                     <anchor 290 0>   mark @MARK_BOT_CENTER;
  pos base [dotlessi dotlessj] <anchor 130 500> mark @MARK_TOP_CENTER
                               <anchor 130 0>   mark @MARK_BOT_CENTER;
  pos base [b h l] <anchor 130 700> mark @MARK_TOP_CENTER
                   <anchor 130 0>   mark @MARK_BOT_CENTER;
} mark;

Note the position of the semicolons. For clarity, I wrote the bottom anchor definition in separate lines, but you can just as well write them on single lines. OpenType treats all whitespace the same.

And let’s not forget our @MARKS class, which needs to be redefined like this:

@MARKS = [ @MARK_TOP_CENTER @MARK_BOT_CENTER ];

So, all in all, we have this code in our Prefix:

markClass [gravecomb acutecomb circumflexcomb] <anchor 0 500> @MARK_TOP_CENTER;
markClass cedillacomb <anchor 0 0> @MARK_BOT_CENTER;

feature ccmp {
  # Glyph Composition/Decomposition
  sub i' @MARK_TOP_CENTER by dotlessi;
  sub j' @MARK_TOP_CENTER by dotlessj;
} ccmp;

feature mark {
  # Mark to Base positioning
  pos base [a n] <anchor 310 500> mark @MARK_TOP_CENTER
                 <anchor 310 0>   mark @MARK_BOT_CENTER;
  pos base [c e g o] <anchor 290 500> mark @MARK_TOP_CENTER
                     <anchor 290 0>   mark @MARK_BOT_CENTER;
  pos base [dotlessi dotlessj] <anchor 130 500> mark @MARK_TOP_CENTER
                               <anchor 130 0>   mark @MARK_BOT_CENTER;
  pos base [b h l] <anchor 130 700> mark @MARK_TOP_CENTER
                   <anchor 130 0>   mark @MARK_BOT_CENTER;
} mark;

@BASE = [ a n c e g o b h l dotlessi dotlessj ];
@MARKS = [ @MARK_TOP_CENTER @MARK_BOT_CENTER ];

table GDEF {
  GlyphClassDef @BASE,,@MARKS,;
} GDEF;

Okay, export, bring up your Character Viewer, and woohoohooo we can do stuff like this:

And we can even combine top and bottom accents:

Cool. Stay tuned, there’s more to say about this subject.

Update 2014-12-12: Updated the note at the top.