The Birth Of Xiis — A Guide On Font Creation

A PDF version of this guide can be found at


  1. Introduction
  2. Softwares
  3. Designing Glyphs
  4. Importing Glyphs
    1. Create a new font
    2. About encoding and character sets
    3. Importing Glyphs
      1. Zero-width characters
      2. References
      3. About suffixes
  5. Lookup Tables
    1. Features
    2. Lookup tables
    3. Subtables
    4. Tables of Xiis
      1. Vowels
      2. Another approach for vowels
      3. Half-boxes
      4. Testing it
      5. Final consonants
  6. Exporting
  7. Other Approaches
    1. Composition
    2. Graphite
    3. Anchors
  8. Final Thoughts

1. Introduction

When I decided to make my own writing system (or a conscript, for short), I couldn’t tell how difficult it would be to actually develop a computer font for it. If I was designing a standard alphabet, none of these troubles would happen to me, but, inspired by Hangul, I followed a different way.

So, to help other people that might try to create similar systems, I’ll try to describe my journey in this endeavor.

This is not a tutorial, I would say, because it’s not (much) a step-by-step directions. It is a guide that will explain the general process I used to create Xiis and what each function do (specially about lookup tables, something I really suffered to understand how they work). It actually became longer than I originally intended, but I believe it has the right amount of detail.

To view the description of Xiis, itself, along with a link to font file, check the document at

2. Softwares

I used basically two softwares to create the font for Xiis: Inkscape, a vector graphics editor, and FontForge, an outline font editor. Both are free open source softwares, so you only have to spend your internet connection to download them. The only caveat is that FontForge is a pain to install under Windows, but I managed to do it.

* Edit: If I recall correctly, I used a pre-built installer package to install it on Windows. Such packages can be found at They may seem outdated, but there’s no actual more recent version of FontForge (unfortunately).

There’s also Graphite, a script language to help creating complex features in fonts. Even as sort of “programming language”, I found it easier to understand than the OpenType lookup tables, but it does have some bugs that annoyed me. I’ll tell about this approach later.

3. Designing Glyphs

glyph is “an image, often associated with one or several characters” according to the FontForge glossary. The first step is to design such images that will compose your font. About how to do this, there’s many information on the internet easily accessible. You can even use FontStruct to do it, depending of how simple are the glyphs.

The design for short i in Inkscape.

Picture 1: The design for short i in Inkscape.

In my case I used Inkscape. As it works directly with SVG (a vector graphics image format) and FontForge can import them directly too, it’s a natural process.

My recommendation is to create an image of 1000×1000 pixels (or 1024×1024 if you intend to create a TrueType font, as it requires the height to be a power of two, though FontForge is able to rescale it if you want). The width is not really important, because it’s defined per glyph, but the height is defined for the font (unless you have a vertical system) Create a base file with all the guides, specially the baseline, and use it as a start. Save each glyph as separate file.

When finished a glyph, select all the pieces, do an invert selection command and delete. This assures nothing extra is hanging around. Then, select the tool Edit paths by nodes (F2), hold shift and click on every piece until all is selected. Then click on Path > Union in menu bar to make it all a single path. FontForge requires that only a single path exists.

4. Importing Glyphs

4.1. Create a new font

Open FontForge and create a new file. It’ll show a bunch of rectangles with red Xs and characters on top of them. The Xs are where your glyphs will be and the characters are a reference to know the correct encoding.

You also have to set the baseline of the font. The baseline is the horizontal line in which letters sit. Everything below the baseline is a descender, like the stem on the letter p. In Xiis, all final consonants are drawn below the baseline.

To set that, go to Element > Font Info (Ctrl+Shift+F) > General. There you can set the Ascent (the size above the baseline) and the Descent (the size below the baseline). The Em Size change automatically to reflect the sum of the two and that should be the same height of your SVG files, to assure the glyphs will be in the same position when importing.

In the Font Info dialog, under the PS Names section, you can set the name of your font and also add a copyright notice.

4.2. About encoding and character sets

character set is, well, a set of characters. The encoding is what tell which bytes represents each character of a set. Unicode is an example of a character set, as a collection of characters and a standard numeric order for them. In order for the computer to understand which character to use, an encoding is necessary, such as UTF-8, which maps a byte (or a sequence of bytes) to the numeric order in the set.

Every character in a set must have a numeric id, but the encoding doesn’t really need to map all of the characters. For example, a long s might be used when an s occurs in initial or medial position, but it doesn’t have to be mapped to any byte, as it’ll use the same as s does. To the computer, they’re the same, just the representation is different.

So, when creating variations of characters, you don’t have to specify the encoding for all of them, but just for the base form.

For Xiis, I used some of very special characters of Unicode, like ṕ (p with acute) and ẽ (e with tilde), so I used the full BMP (Basic Multilingual Plane). To do that in FontForge, click on the menu Encoding > Reencode > ISO-10646-1 (Unicode, BMP). This will bring a lot of characters to the FontForge screen. For easier navigation, the View > Goto (Ctrl+Shift+>) command can be used.

4.3. Importing glyphs

Now you have to import the glyphs under the character you want to use when typing. Just the base forms should be imported this way, as alternative forms don’t need to have an encoding. In the case of Xiis, those are the initial consonants, the vowels in their standard position, the numbers, and the punctuation marks.

The import dialog

Picture 2: The import dialog.

If you click twice in any red X, it opens the glyph edit window. FontForge provides tools to design the glyphs inside it, but I find Inkscape much more powerful and friendly. To import a file, go to File > Import (Ctrl+Shift+I). Select the format as SVG, and find the file with the corresponding glyph.

If you set the Em Size correctly, the glyph should already be in the right position. If not, select all and move it around. The keyboard arrow keys can be used to move pixel by pixel. With <Alt> pressed, it moves in ten pixels per step.

After adding all the base forms, click on Encoding > Compact. This will make only the non-empty characters appear. This make it easier to navigate, specially if you used some special characters far in the list. Just remember to uncheck it before exporting, or the encode will turn out messed up in the font. The other reason to compact is that the extra glyphs will be at the end of the list, which is very far if you’re using the BMP (though you can just press the <End> key).

Now, you have to rename your glyphs to something meaningful. These names are useful when building the lookup tables later. You can use the standard names, which are already set, or change to something more specific. To do that, select a glyph and click on Element > Glyph Info (Ctrl+Alt+Shift+I). Go to the section Unicode and change (if you want) the Glyph Name field. You can use the Prev and Next buttons to navigate, just be sure to click OK after finish editing, because if you Cancel it, all the changes will be canceled, not just the current glyph.

For the alternative glyphs, you need to create new slots. Click on Encoding > Add Encoding Slots. Select the needed amount of slots and click OK. Then you can import the glyphs for alternative forms into the new slots.

4.3.1 Zero-width characters

What happens to the vowels in Xiis is that they don’t require any special feature to be placed correctly. I just used an evil trick: zero-width characters.

I placed the vowels before the origin, just in their position inside a initial consonant. Then I moved the line at the end to the same point of the origin. It’s also possible to use the Metrics > Set Width (Ctrl+Shift+L) command to do that. With zero-width, the cursor won’t move forward when typing this character. And since the glyph is before the start line, it’ll be drawn before the cursor.

If you use mark positioning (usually done with diacritics), you would also want to make them zero-width, otherwise some unwanted extra space may be generated.

4.3.2 References

You may want to use the same glyph for the same character in a different position. It happens in Xiis, when you use two vowels in a syllable, as they change position but keep the same form. You can copy and paste and them just adjust the position of the alternative form, which is possible. However, if you want to change the form, you have to copy and paste and adjust everything again.

That’s when references come into play. Instead of copying a glyph, you can just copy a reference to it. Then if you change the original, all references will be updated.

To do that, click with the right button in the source glyph and click Copy Reference. Then you can paste it unto another and only the reference will be copied. You can notice that it’s not possible to edit the pasted reference, you can only change its position. Be aware, though, if you change the position of the original glyph, all references will reflect the relative movement.

4.3.3 About suffixes

When placing alternative forms of characters, you want them to have the same name as the base form, which makes sense. But the names must be unique. And that’s when suffixes made themselves useful. When you change the name of the new form, place the name of the character, add a dot (.) and then type a meaningful suffix.

Using the same suffix for multiple characters help automatizing the creation of substitution tables later, as FontForge can find all terms with a certain suffix. You can also chain the suffix, tough the software automation only happens with the last one.

In Xiis, I created variations with different position for when a vowel is the first in a syllable and when it is the second. Both are different from the base form, which is centralized. So I used the suffixes “first” and “second” for that. When I created the substitution table, I could load everything with the same suffix, which was very helpful, specially after I added new vowels. There’s also the half-box version of the initial consonants, all carrying the “half” suffix. As the finals are variations of the initials, they also have the same name, but with a “final” suffix.

5. Lookup Tables

This is the main engine that made Xiis font possible. A lookup table is a set of commands that informs the software rendering the font how to make the correct transformations. The tables have to be associated with features, which are standard identification for such transformations.

Those features are part of the OpenType standard, maintained by Microsoft and Adobe. Apple fonts work differently and follows another standard, though they are usually compatible with OpenType and FontForge knows how to deal with them, so it shouldn’t be a problem.

5.1 Features

In OpenType standard, features are identified with a four letter code. For example, the ligature feature (the one that joins certain combinations of characters like fi) is identified by “liga”. There are a great variety of features, though some only work with specific languages.

The trouble with features is that, as powerful as they could be, each software implements them differently. There’s no guarantee that they’ll work (or that they’ll work the right way). But that’s all we got, so we have to live with that.

Of course, Graphite is another possibility. However, even if it is more constant, it’s only supported by a handful of softwares. And, for my experience, you have to choose between Graphite and OpenType features, as they don’t work together.

For Xiis, I only used the Contextual Alternate (calt) feature, though I used it in multiple tables.

A list of all the features can be found at the OpenType specification ( And there’s a great article about features that can be found at

5.2 Lookup tables

A lookup table is actually what instructs the transformations. There are two types of them: substitution (GSUB) and positioning (GPOS).

The substitution table changes a glyph for another. It also can change many glyphs to just one, or change on for multiple glyphs. A positioning table change the place of glyph based on a certain context (kerning is one example of that).

What it’s not immediately clear is that you can use many features with a certain table and sometimes you don’t need to specify a feature for such table as you’ll use somewhere else. For example, if you want to change a glyph based on context, first you need a Single Substitution table to describe such changes, than you need a Contextual Substitution to describe the context which the change should occur. Only that second table need to be associated to a feature.

5.3 Subtables

A lookup table actually only contains metadata about the transformations. The real description of how they should occur are placed under subtables.

The format of those subtables varies depending on the lookup, and you can check the documentation of FontForge to understand how the dialog works. I’ll focus in the ones that I actually used

5.4 Tables of Xiis

There are three transformations in Xiis: the half-box, the vowels and the final version. The first thing is to understand when such changes happen. The half-box version happens when a initial consonant is followed by two vowels. The vowels change positions when there are two in a syllable, the first is backed a little and the second is nudged forward. The final version occurs when a consonant is preceded by a vowel.

5.4.1 Vowels

New lookup table with 'calt' feature.

Picture 3: New lookup table with ‘calt’ feature.

Let’s handle the vowels first. What I did was creating glyphs with the variations for first and second position and used a table to handle. It was also possible (though I didn’t knew how by that time) to create a positioning lookup table to nudge them.

First, create a new lookup table under Element > Font Info (Ctrl+Shift+F) > Lookups Add Lookup and select the Single Substitution type. There’s no feature needed for this one. Name it (I used “First vowel” as a name) and click OK. Next, select it and click Add Subtable. You can use the default name.

That’s when suffixes come to use. Since I named all first versions with the same name plus a “first” suffix, it’s possible to use the Default Using Suffix button. Just fill the field near it with “first” then click the button. The list will be filled automatically (though you may want to check if it’s all there, which is possible if you misspelled something). To understand this subtable, the first column is the original glyph, and the second column is the glyph which will take the place of the original. This table will not make any actual change in the way it is, because the lookup is not associated to any feature.

Then, make another lookup and subtable similar to these, but this time using “second” as suffix.

Now, make yet another lookup, with the type Contextual Substitution. In the feature column, notice there’s a small rectangle after the <New> word. Click on it and a list of features will show up, then select Contextual Alternates. A “calt” feature will be added. In the “Scripts & Languages column you can select inwhich scripts this feature should be applied. “DFLT” is short for “default” and should be set for conscripts. Between the curly brackets is a list of languages to apply the feature. Usually, “dflt” (default) is enough. Click OK to save the lookup (I used the name “’calt’ Vowel places”, as is default to start the name with the feature it uses, though not required).

It’s possible to use a Contextual Chaining Substitution. The main difference to a Contextual Substitution is that it separate the glyph(s) you’re going to change from its context. That lookup allows you to create three sections: before the glyph(s) (called backtracking), the glyph(s) and after the glyph(s) (calledlookahead). This format is more general, and it’s only needed if you want the word processor to treat the changed part differently (which makes more sense in positioning tables).

Add a subtable to it and use the default name. A prompt then shows up, asking if you want to edit By GlyphsBy Classes or By Coverage. With the first, you have to define the context rule glyph by glyph. In the case of Xiis, it means adding every combination of vowels (and order matters). If you use classes, you can make lists of glyphs (classes) and create rules for a position that matches any of the glyphs inside such classes. The coverage format lets you create a separate list of glyphs for each of the glyph positions. The type of dialog can be Simple or Complex. I prefer the Simple format and you can do the same thing in both of them (the Complex format is just more verbose).

And by “positions” here I mean the positions of a glyph in a sequence of glyphs. In this case, I’m thinking in a sequence of vowels. This determine the context in which to apply the transformations. You make this context with rules. Each subtable can contain many rules, but, according to FontForge documentation, “OpenType interpreters do not seem to support multiple rules within a single subtable”. If needed, multiple subtables can be created.

Contextual substitution subtable by classes.

Picture 4: Contextual substitution subtable by classes.

Moving on, select By Classes and Simple (the default) and click on Next. First, we’ll define classes in the Match Classes section. A special class name “All_Other” is already there and cannot be deleted. It means “everything that is not defined in a class”, which can be useful in some sort of “everything except” rule.

Click on <New> under the name column and change the name to “vowel”. In the second column, put all the glyphs that are vowels separated by spaces. When you start typing, a list of possibilities will show up. You can select it with up and down arrow keys and use the right arrow key to insert the selected.

Then create a rule by clicking on <New> under Matching Rules section. Type “vowel” (it’ll probably auto-complete, you can press right arrow key to accept it). Next, click on the Add Lookup button and select First vowel in the list, which is the first lookup table we made. Then type “vowel” again and add a lookup again, but this time select “Second vowel” (or any name you gave to the second lookup table). The result will be similar to picture 4.

What this rule means is: if any of the glyphs present in vowel class is followed by any the glyphs present in vowel class, apply the lookup First vowel to the first glyph and apply the lookup Second vowel to the second glyph. Any space on the rule is ignored. If you want to match the space glyph, use its name (“space”), though in this case you need to put it in a class.

5.4.2 Another approach for vowels

Since the only difference between a vowel and it’s first and second versions is the horizontal position, it’s possible to avoid the creation of the extra glyphs and, instead, use a positioning lookup table. I’ll describe this approach here.

First, create a GPOS lookup of the type Single Position. You may think of creating a Pair Position(kerning) in this case, because there are a pair of glyphs (two vowels), but that can only change the position of the second glyph and we want to change the position of both. So we make two lookups of the typeSingle Position, one for the first vowel and another for the second, with a single subtable for each of the lookups.

The first vowel must be backed by 150 units in the horizontal axis, so we change the Δx column to “-150” (notice it is negative, so it means 150 units to the left). In the base glyph column, add the name of the first vowel, then click in <New> as many times needed until all the vowels has its place. It’s good to change the position first, because the new lines will use that as default.

For the subtable of the second lookup you do the same, only changing the Δx to “325”, which is the difference to a second vowel.

The only caveat here is that long vowels are placed naturally on the position where the first vowel would sit in diphthong. So, for them, the first Δx would be “0” and the second would be “475”. It’s possible to not even list them in the first table, which can save some work.

After that, a Contextual Position lookup is needed, with the Horizontal Kerning (kern) feature. The approach here is the same as the Contextual Substitution, using a class of all the vowels and a rule like “vowel @<First vowel> vowel @<Second vowel>”. This position two consecutive vowels according to the lookups we made before.

5.4.3 Half-boxes

The half-box version of a initial consonant should be used when it’s followed by two vowels. To do that, we need to specify such context, which would be consonant vowel vowel. However, I’ll use a neat trick to simplify that.

First things first, we need a lookup table that handle the substitution. So, create another lookup with the type Single Substitution and name it “Half box”. Add a subtable with the default name and use the Default Using Suffix with the “half” suffix. This will fill the table, and you can press OK.

Create another Contextual Substitution lookup and add the Contextual Alternates (calt) feature. Name it “’calt’ Half boxes” and click OK. Add a subtable to it with the default name.

Now comes the trick. Since every two vowels will be replaced by a first version and second version, instead of checking if there are two vowels after the consonant, the table can check if the consonant is followed by any first vowel. To do that, create a class with all the consonants (let’s call it “consonant”) and another with all the vowels with the suffix “first” (call it “first”). Them, add rule like: “consonant @<Half box> first”. This means: in any glyph in consonant class followed by any vowel in first class will be applied the Half box lookup. Which in this case means a consonant will be traded by its half version when followed by a first vowel (notice that this trick is not possible if you use the positioning approach for vowels, in such case you could use the consonant vowel vowel rule to match this case).

From that you can perceive two things. First, you have to consider previous transformations. If you forget them, it’ll not work as intended. For example, if I type the combination “m a e”, which is a consonant followed by to vowels, I have to remember that they it will be changed to “m a.first e.second” and if I don’t explicitly specify those in the classes, it’ll not match. So the glyph “a” inside a class will not match “a.first” nor “a.second”. If you want those, you have to add them to the class.

Second, the order of the lookups matter. If you put the “’calt’ Half boxes” lookup before the “’calt’ Vowel places”, this trick will not work, because it’ll be looking for a consonant followed by a first, and the vowel wasn’t yet changed to a first. You could use this order if you wanted to avoid the trick, so you could specify a single class of vowels and match “consonant vowel vowel”, without having to worry that they would became first and second, because that would only happen later.

Metrics for "m a e" sequence.

Picture 5: Metrics for “m a e” sequence.

5.4.4 Testing it

You probably wants to know if the thing is working as expected. That can be done by clicking on Window > New Metrics Window (Ctrl+K). In the text field at the top you can type anything and it’ll be rendered in the middle of the window.

Info about the glyphs can be found at the bottom, so you can view that the glyphs are being really substituted. You can also select different scripts and languages in the left field.

The New Lookup Subtable may only create positioning tables and not substitution ones.

5.4.5 Final consonants

The final consonants are variants of initial ones (at least for typing). They change to final form when preceded by a vowel. This way, it’s not possible to type two finals in a row, and that’s what I want.

Following the same process, create a Single Substitution lookup called “To final”, add a subtable and fill it using the suffix “final”. Then add a Contextual Substitution lookup and a subtable to it.

The thing to remember when defining the classes is that the vowels may be in their second version, so you have to add them to the list (it’s not possible that they are in the first form, because it only happens when they are followed directly by another vowel, so there wouldn’t be any consonant between the two).

So, there’s a class of “finals” and another for “vowels” (which include the seconds). And the rule is “vowels finals @<To final>”. This means final that it’s preceded by a vowel will be transformed according to the “To final” lookup.

And that completes everything.


First, it’s good to validate the font and see if there are any problems. FontForge can still export the font if any of such problems occurs, but it can also fix some of them if you want, like “Missing Extrema” and “Non-integral Coordinates”. Some of the errors go away if you fix others.

To do that, click on Element > Validation > Validate. A dialog showing all the errors will appear and if you double click in one of them the glyph will open and a message will show up explaining the error. It’s possible that such message box has a Fix button, which fix it and move to the next error.

FontForge saves the files in its own format (.sfd). To generate a font file that can be installed, click File > Generate Fonts (Ctrl+Shift+G). There you can select the format (there are plenty) and the place and name to save it. The most common formats would be OpenType (CFF) and TrueType, as both of these support the lookup tables and works on many platforms.

7.Other Approaches

7.1. Composition

One possibility for Xiis that I consider is to pre-compose all possible syllables and create substitution tables for the sequences. While this task may seem daunting, I could do with a script program. FontForge accepts scripts in its own language and also in Python. If you are a programmer like me, this is a possibility not-so-daunting.

For that, a Ligature Substitution lookup may be used. This kind of lookup replaces a sequence of glyphs with a single glyph. It’s called that by the Latin ligatures (like “fi”). Instead of using the Standard Ligatures (liga) feature, in this case it’s proper to use the Glyph Composition / Decomposition (ccmp).

If this interests you, the FontForge website has the API documentation to the scripting library both in Python and in its own language.

* Edit: I gave up on that approach for Xiis. While possible, there’s so many combinations for compositions that the font file ended up very larger than the original. Just note that you can mix compositions with the lookup tables magic that I described in this article (Hangul fonts do a bit of that too, AFAIK).

7.2. Graphite

Graphite is a system made specially to deal with complexities of lesser-known languages. It was created by the Summer Institute of Linguistics (which also provides many other linguistic related tools that can be used in the conlanging universe). You can’t design the glyphs of a font with it—that should be made elsewhere—only the extra features can be made (like position and substitution).

There are two main problems with Graphite: it is supported only by a handful of programs (while OpenType is widely supported) and it requires to be written like a programming language, which might not be for everyone (though it is somewhat simple to understand, at least not harder than lookup subtables and features).

The rules in Graphite are made in a different way than OpenType lookup tables. It makes them more general and a little simpler, while still allowing powerful possibilities.

Depending of your affinity with a programming language and the complexity of your writing system, it might be even easier to follow this approach instead of the lookup tables. And notice that the two systems cannot be used together, because the graphite compiler wipe the tables of the font and I’m sure the same occurs in the opposite direction.

7.3. Anchors

While substitution and kerning worked fine for Xiis, other systems might want to make use of mark positioning. This is probably the best way for diacritics combinations and abujidas.

The general idea is that you place an anchor on the base character, another anchor of the same class in the diacritic and when combined that anchors will be put together like a pin. This way you can have many base glyphs and many diacritics without having to create a lot of alternate glyphs.

A general step-by-step tutorial on how to do that is described in the following link:

8.Final Thoughts

These advanced typographical topics are really hard to learn and there little documentation about these. It’s already hard to find a cheap program to make a simple font, much more to a complex one. Luckily, FontForge is there and works well.

If your budget is large, other applications may be used to design the font with all the features, like Fontographer and Glyphs (if you own a Mac). They have an easier approach on the lookup tables, AFAIK.

Anyway, this was really longer than I wanted, but I hope people can understand the general procedure to make the lookups and features. It’s hard to make a one-fits-all kind of tutorial and there are many possibilities I didn’t tested myself. For me, it was hard to understand how it worked but once I did, the rest was easy. If you can also understand that, I’m sure you can do pretty much anything you want (just don’t come here talking about non-linear writing systems).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.