anarchy.website
Toggle Dark Mode

Una Mono

A Monospace Font

By Una Ada, May 31, 2021

Preface

Welcome back to “Una Makes Fonts for Some Reason,” this is probably the third installment, which is cool. Today, we’re once again aiming to complete the styling on una-ada.github.io, particularly regarding code blocks and their need for a monospace font. I want to try to keep this consistent with Una Script stylistically, but with enough distinction that you can tell there’s a difference. Before I get to that, though, there’s some minor technical details I want to address regarding Una Script, but after that I’ll be making a whole new font. This time I might even try to be a bit more thorough in the design process… like, actually use the scanner I have access to.1

I. Technical Updates

I.1 “Una Script” Metrics

Something I’ve sort of been struggling with for a while now: what is normal for an EM square? Like, what’s the typical position of the baseline? Currently, Una Script has ascent and descent metrics at $500$ and em size at $1000$, which means the baseline is at $50%$ of the em square’s height! When sitting next to other fonts it looks absolutely terrible, and that needs to be fixed before moving on to this new font as they should similar metrics so as to mesh as well as possible.

I couldn’t find anything when searching for references on “typical” sizes here, so I’ve decided to go back to basics. First, returning to the Design with FontForge tutorial’s Font Info & Metadata page. I had high hopes for this one, honestly, but it’s only a brief coverage of how to edit the metadata of your font, which does include overall metrics but not any sort of guidelines for them. Similarly, The EM Square only goes over the various heights and a brief reference to the existence of Blue values. A bit more digging brought me around to another site, Font Development Best Practices, which has a section on metadata that has the design metrics guideline I’d been looking for.

It doesn’t give a “use these values for this style of font” or anything like that, only recommends comparing to similar (or competing) fonts, which is a good strategy here. There is some discussion on the UPM (units-per-em), which should be either $1000$ or $2048$, and what supports what best. Of great interest here is the section titled “Drawing outside the box” which answers a question I’ve been having while thinking about the metrics: can glyphs extend outside the em square so long ascenders and descenders don’t mean the rest of the glyph is really small? Yes! The article points out that “this is a design issue, not a technical one;” there won’t be any issues, it’s simply an indication that the font may be too “large.” This article about glyphs by David Turner also answers that question pretty succinctly:

“Note that glyphs can freely extend beyond the EM square if the font designer wants this. The EM is used as a convenience, and is a valuable convenience from traditional typography.”

What I’ve learned here is that the next step is to find other fonts that might have similar metrics to what I’m aiming for and see what those numbers look like. Then I resize the glyphs in Una Script, allowing the long descenders to pass beyond the descent ruler.

My first thought was that some of Google’s fonts (namely Noto as used here) likely have documentation on their metrics. This brought me to a fair bit of other documentation on the googlefonts/gf-docs repo that will be more useful in a later section, but not what I’m looking for at the moment. I did eventually find the FONT_CONTRIBUTION file for Noto, which lists the Noto UI font metrics, which are Roboto Regular’s metrics translated to a UPM of $1000$, and also notes Open Sans Regular’s metrics:

OS/2 Noto UI Open Sans
TypoAscent 1069 1056
TypoDescent -293 -271
TypoLinegap 0 0
WinAscent 1069 1056
WinDescent 293 271

Then I spent several more hours trying to find some other metrics to reference, mostly dead ends, but apparently the Liberation font collection’s source uses FontForge so the metrics are fairly easy to find by reading the project file code:

OS/2 Serif Sans Mono
TypoAscent 1420 1491 1255
TypoDescent -442 -431 -386
TypoLinegap 307 307 0
WinAscent 1825 1854 1705
WinDescent 443 434 615

While it’s best ignored, the “General” values for ascent and descent in these files are all $1638$ and $410$ respectively.

What am I going to be using then? I still have no clue, so I’m going to do some testing. I spent a whole night doing this research and I wanted to get this all done in a single day, but if running a whole bunch of tests is what it takes to do this right then that’s what’s going to have to happen. I still want someone to guide me here, but the Glyphs docs just say:

“Different type designers employ different strategies on how to find the best values for the vertical metrics. But beware: amongst font nerds, there are fierce disputes going on about what is the best strategy.”

and that doesn’t help me at all! There is some good stuff about setting up the values for webfonts. So I’ll try to use that methodology throughout my testing. I don’t want to use the actual descenders as a reference point here, since they are so long, so I’m going to start with things like the swash on the “Q,” which comes off as pretty extreme when you look at the current scaling which round to about $(330,\, -120)$ with the UPM at $1000$. On the other hand, the Blue values set based on the guidelines I used when initially sizing the letters but my cap/ascender height in the range $[360,\, 380]$. I’d say that sticking with the values being $(380,\, -120)$ gives a ratio of $3:1$ which is pretty similar to that of the previously discussed fonts!

Updating all the glyphs will require a bit more than simply setting new metrics, the outlines will also need to be adjusted in both size and position. Size is rather easy, it’s really just doubled here, but position is difficult as apparently not everything transforms correctly. The first error in this was me transforming from center rather from the left, so I needed to fix the bearings. Easy as that was, I tested the metrics and found that glyphs with long descenders were higher up than the rest, and checking the positions of those others showed that nothing was on the proper baseline… attempts to adjust everything at once didn’t seem to work for some reason, so I’m going to have to go through them all and make manual adjustments. Fun!

While I’m at it, I figure I’ll go through and make the font slightly more aligned to the BlueValues, do some simplification, and run some other checks to clean up the vectors. Again, for the new font and for additional glyphs to this one, I really want to figure out how to make sure this is all done before the vectors are even imported into FontForge (will discuss this later when working on exporting).

When I finally reached the lowercase letters, I did notice a small issue: my ascender height is absolutely higher than my cap height! I’m going to have to adjust the values here: $(980,\, -120)$. For reference, my current set of BlueValues is $[-20,30],\,[500,520],\,[720,760],\,[940,980]$. I will need to get to adding some values for the descenders and such, these are just baseline, x, cap, and ascender. I’m sure I’ll do that eventually, but for now I’ve updated the font metrics so Una Script v2021.05.29 is done and I have a good idea of the vertical metrics I should be using: $760$ for ascender and cap height, $500$ for x-height, $-240$ for descender height (long ascenders and descenders are $1000$ and $980$ respectively, with an absolute max-height of $1200$).

I.2 Repository Structure

The other little setup step I wanted to do before I really get started on this font has to do with file structures and repositories. Foolishly, I’d previously combined my two existing fonts into the same family (Una) and the same repo (una-fonts), this is bad! First off, font families are just a collection of “subfamilies” or styles, like bold, thin, regular, italic, et cetera. “Una” is not a font family but a collection of families (tho each family currently only has a “Regular”). This needs to be changed in the metadata, no big deal, just keep it in mind going forwards and update them as I get around to it.

The repository thing is really just a choice of how one wants their content organized, but keeping them in the same repo is a bit iffy when they’re not even the same family. So I’m going thru and undoing that whole complicated merge thing I did to combine the previously separate repos. But this brings about the question of how each of these repos should be structured.

Currently, there’s a /scans directory which contains the “scans” of the original designs, /src for the vectors produced from those, fontForge which just holds the FontForge project file, and finally /build for all the finished builds (in subdirectories by version). This isn’t too far off from what the Google Fonts docs state as the required repo structure:

.
├── AUTHORS.txt
├── CONTRIBUTORS.txt
├── OFL.txt
├── README.md
├── documentation
│   ├── DESCRIPTION.en_us.html
│   └── promo.png
├── fonts
│   ├── ttf
│   │   └── FontFamily-Regular.ttf
│   └── variable
│       └── FontFamily-[wdth,wght].ttf
├── sources
│   ├── FontFamily-sources.ext
│   └── build.sh
├── requirements.txt
└── .gitignore

This wouldn’t require a huge refactor or anything, just some moving and renaming of some files. This is a good thing to decide on here and now when I only have a couple repos with a few builds to comb through, and then try to keep to the structure for future projects (e.g. this one).

II. Design

I’m going to keep this one simple, just get the basics down for now at least, and only cover 0000 C0 Controls and Basic Latin. Doing something a bit different this time and using a template. Having this printed out makes it pretty easy to make sure the glyphs fit into the intended metrics (vertical metrics were previously discussed, horizontal were decided to be $420$ units wide as a compromise between half the em size and half the ascender height), but writing in them is pretty hard to keep looking natural. Some of this can be fixed “in post” a bit, but that just means I’m deferring issues to later steps already and I was trying to avoid that this time (like with the template thing)!

As for the concept of the design, I’m trying to maintain a consistent style with Una Script (my handwriting) while also adopting a few adjustments to make the letters fit more into the intended width. This doesn’t really show all that much beyond adding crossbars and serifs here and there, since I really just want it to be a metrically consistent alternative version… oh, there is the thing with how all the descenders are different, that one’s pretty obvious since the ones on Una Script are pretty long, lol.

III. Digitization

Continuing on with attempts to do things more “properly,” this time I’m going to actually use a scanner instead of just taking a picture. This should help with keeping the metrics all consistent… though, given that the template has guidelines for them, it wouldn’t be too absurd to correct them later, but again that would be deferring issues until later when they can be avoided now. Only saying this because of some technical issues with getting scanners to work, but managed to resolve that and now have the scan.

I did put in all this effort just to write out new glyphs, I realized along the way that I could just copy the vectors of Una Script and adjust them to the intended metrics for this new font… this is for stylistic consistency and not because I’m already tired of working on this. Other than that this follows the typical Una formula for tracing with vectors in Illustrator: draw points with the pen tool (P), curve the lines with the anchor point tool (⇧C),
direct selection tool (A) to fix up any curve lines and anchor points, rinse, repeat, on and on… it’s a very repetitive process. But I got through it eventually!

Then these vectors need to be cleaned up, which doesn’t require too much creativity or guessing this time around on account of the consistent metrics. I set up a new Illustrator document as 1000 x 1000 and put guidelines down for the baseline and x-height, calculated the amount I would have to scale the vectors up by dividing my UPM by the height of the scanned templates, and guessed the stroke width I could get away with here ($110$ which is less than the $180$ Una Script is now after the $200%$ upscale, but that’s fine). With all those initial steps out of the way, the rest is just moving each glyph to fit in the guides, I added some new guides $55$ (half the stroke) away from the ascender and descender lines, as well as from my horizontal metric guidelines, so I could just fit the objects to these and the stroked paths would fit within the intended guides.

Cool Illustrator Trick 1: Rather than using a transform on the whole layer of glyphs and making the layer fucking massive, I can use Object > Transform > Transform Each to resize each path or group without changing their position and thus keeping them more or less in reach for later editing!

Cool Illustrator Trick 2: These glyphs are all currently either simple paths or groups in the same layer, but later I will want to export them all using a script that exports separate layers.2 This means moving each and every one of them into its own layer, which can be a real drag. Since I already have all the layers I want the objects to be in, I can select the object in the editor, select the layer for it in Layers, then use Object > Arrange > Send to Current Layer.

This isn’t exactly normal for a monospace font, but along the way I decided that some glyphs, particularly capitals and similarly sized glyphs, would actually have their strokes meet the path guideline for the ascender. Essentially, making my cap height $55$ less than my ascender height. This reduces the amount of distortion on those glyphs a little and makes them look closer to the original Una Script ones without messing with the scale of the font too much. I didn’t set guidelines for the paths relative to the baseline, even tho the baseline should be the guideline for the strokes, because I wanted to be able to make some optical sizing decisions without struggling to circumvent the guideline snapping which is otherwise extremely useful.3

Cool Illustrator Trick 3: If you transform an object with something like a rotation, the bounding box will no longer be orthogonal to the grid, which is inconvenient for sizing relative to guidelines! There is a tool to fix this which you can access with Object > Transform > Reset Bounding Box.

After another grind through all 944 glyphs, I managed to survive this step as well. It is Monday already and I wanted this whole font done Saturday, so I’m not exactly happy with my progress!

That’s most of the design-oriented steps of the digitization done! Now I’m moving on to more technical parts. These glyphs are all paths at the moment, which theoretically could be imported into FontForge as is, then use the Expand Stroke facility in there. I’m considering switching my workflow over to this as it would allow for variations in font weight, theoretically, but that is an experiment for a later time. For now, I’m sticking to doing the expansions within Illustrator because I adjusted these glyphs based on the strokes they have now, removing the strokes and adding them back in later could lead to some deviations and errors. That said, I just need to unlock and unhide all my layers and apply Object > Expand... to every object.

Cool Illustrator Trick 4: Clicking on the visibility toggle and dragging down a long list of layers is annoying at best. If you just want to hide all layers except for one, then hold Alt/क when clicking on the toggle for the layer you want to work on and it will hide all the others!

Expanding does most of the work, but it does (sometimes) keep the original stroke and overlapping strokes will just be overlapping outlines now, so I need to do another pass through using the Unite function in the Pathfinder. I would love to just apply this to all layers at once, but having multiple glyphs selected when running this function would just unite them all into one object!

Cool Illustrator Trick 5: Is expanding your strokes not working? Are your nice, rounded caps defaulting to boring flat ends? Then you need Object > Flatten Transparency! This fun little function is significantly worse than expanding and will need to be cleaned up with a bit of Shape Builder Tool (⇧M) and Object > Path > Simplify, but it’ll still do the job!

Since this is completely routine, with the steps the exact same for each layer (toggle visibility, select all, unite, toggle visibility, repeat…) I would really like to just automate it, but I do not know how! Wll, since I’m probably going to be doing this a lot in the future, might as well put the effort in now.

Ok, detour time, automating this annoying thing. First off, this doesn’t seem possible to be done with actions, so it’s going to have to be a script. Also, this doesn’t seem super uncommon a thing to do, so there’s probably already one made for it. I found some blog post in my initial search, which seems to be just someone saving a reply from the Adobe Support Community, and it doesn’t work. Looking into why it doesn’t made it obvious that this weird single-line snippet was all lowercase? So I searched for the original thread and found not only the properly formatted reply, but another more complete script by the user zertle:

function MergeAllLayers() {
  // exit early if there are no files open
  if (!app.documents.length) return;
  var doc = app.activeDocument;
  // clear selection
  doc.selection = null;
  // loop through all layers
  var layers = doc.layers;
  for (var i = 0, ii = layers.length; i < ii; i++) {
    // select everything on the current layer
    layers.hasSelectedArtwork = true;
    app.executeMenuCommand("group");
    app.executeMenuCommand("Live Pathfinder Add");
    app.executeMenuCommand("expandStyle");
    // clear selection
    doc.selection = null;
  }
}
MergeAllLayers();

… and … it didn’t work! Let’s figure out why. First, strip this all down to just what’s inside the loop, replace variables with their definitions, and try that. Nothing. Line by line then, does the selection trick work? No. According to an answer to a similar problem, what actually needs to run is:

app.activeDocument.activeLayer.hasSelectedArtwork = true;

So, how do I change the active layer when looping? Or can I just select each layer from an array while looping? Reading into a thread on a similar topic implies that’s what I should do:

  for(var i = 0; i < layers.length; i++){
    // select everything on the current layer
    var layer = layers[i];
    layer.hasSelectedArtwork = true;
    // ...
  }

I’d also like to throw the expansion step into this script so I can avoid doing that one manually in the future as well (even though it’s trivial), but there’s a dialog for it so it would actually be worse to do it that way. There is a way to circumvent this, but it requires setting options for Actions, so it isn’t all handled in the script (I want to avoid doing that). Anyway, for safety, I’ll also throw in a little guard for locked layers:

    if(layer.locked) continue;

Now the script is all working! This will be excellent for future work, even though in this instance it probably took up more time to write and debug. 😅

Now back to same old same old: using Tom Byrne’s MultiExporter.jsx to export all these layers as SVGs. When running this script, remember to deselect the “Trim Edges” option. I foolishly forgot to do this the first time around and it cuts all the exported SVGs down to just the size of the glyphs themselves rather than the whole em square!5 For organization, I’m creating a new directory, /sources/vectors in the repo, and putting everything here in a subdirectory for the Unicode block in case I want to expand the coverage of this font later on: /sources/vectors/0000.

That’s it for this section, I now have a folder containing all my vectorized glyphs, individually, properly positioned. 🎉

IV. Font

Finally, I get to open up FontForge. Yay! I don’t need to do anything to the settings on encoding opening the font, I’m only doing the ASCII characters here, so there isn’t really any need to change the character set from the default. Importing is straightforward with hotkeys: ⌘⇧I on each glyph. Selection for imports is pretty easy, since all the files are named after the glyph name, I really wish I could automate this, though. I swear I’m not going to detour for that this time.

It isn’t super important for the end product to set the ascent and descent values, but I need to do it so that the imports are properly positioned with a baseline at zero (and also so the previews look better). As previously mentioned, these values are $760$ and $240$ respectively.

Now that all the vectors are imported, it’s time for some cleanup! Just going to run Element > Validate to get a quick rundown of what might need to be fixed before probably just running through the motions I’m already used to… okay, so it kind of crashed when I did that. It’s to be expected that there would be some weird issues, this is my first time running this on a Mac. So let’s just do the basics then:

Then I’ll run a manual Element > Validate > Find Problems, and see what it comes up with. Which seems to be some “the paths that make up this glyph intersect one another,” and I need to remember how to fix that. A comment on GitHub recommends Element > Overlap > Remove Overlap (⌘⇧O), which seems to work.

I’m also getting a lot more missing extrema errors than I’d expect, and checking the glyphs doesn’t really show any obvious problems. According to a thread I found about this, it’s okay to ignore these in instances like this, or just in general apparently.

Calling it good for the vector issues at this point. Onto metrics! Luckily, since this is a monospace font, I don’t have to bother with kerning this time! I do still need to do a little bit of horizontal metrics, specifically with bearings and thus width. I’ve decided to keep similar to Una Script spacing where the default bearings are $20$, so all glyphs should be $460$ units wide, even the ones that do not take up the entire $420$ width. Applying this is a simple Metrics > Set Width (⌘⇧L) then Metrics > Center in Width, and that’s my horizontal metrics done!

Vertical metrics is where I actually have to start trying 😭. Starting with the basics, none of these should go past the em square so my typo, hhea, and win values should be the same as my ascent and descent. Easy. My capital height is $55$ less than the ascent (see previous section): $705$, and my x-height is $500$. The Glyphs docs page on vertical metrics had those strategies for calculating the line gaps, which for this instance would either be $0$ per the Adobe and Microsoft strategies or in the range of $[100, 200]$ per the Webfont strategy (the default in the dialog was $90$, for reference). I’ll be going with the Webfont strategy on this one, specifically choosing just $100$. Which wraps up the basic vertical metrics.

Then there’s the BlueValues and BlueScale properties in the PS Private table… the automated guess for these was $[-15,2],\,[498,504],\,[703,707],\, [760,760]$ which is about my baseline, x, cap, and ascender. The last one isn’t really necessary because it has a height of zero (all my ascenders were put directly on the line), but this seems to otherwise cover everything.6 My “n” was a bit outside it, but I’d rather just move the control points since they were weird anyway. The scale is probably fine by default, but I’ll run a validation check just in case anyway7… well, that’s done then.

All that’s left here is to set the rest of the metadata: the PS Names table. Sticking to a better format for this stuff this time, the Family Name is “Una Mono,” the Fontname then is UnaMono-Regular, but still naming the versions by the date (2021.05.31). Now there’s only one more step for this section!

Time to export the font with File > Generate Fonts... (⌘⇧G)! From here on, I will only be generating the TrueType (.ttf) files in FontForge, to keep with the simplest repo structure. I’m selecting both “Apple” and “OpenType” formats in the options, since that seems to be the best way to do it, and just leaving everything else as default. This gets exported8 into a new directory, /old/[version], and then copied to the /font directory. Et voila, font done! 🔥

V. Tests

Theoretically, this font works just fine, I did check the metrics in FontForge after all. However, how does it feel in context? How does it look in the “real world?” Time to find out! First, this was meant for code, so here’s some typical sort of code:

Single line code test

Single line code test

So far, this looks fine, not a huge fan of how the = and > align, but I can live with it until I decide something bigger needs to be changed. But code is usually multiple lines, and the point of monospace fonts is to be consistently wide so characters line up, how does that look? Here:

Multiple line code test

Multiple line code test

Okay, so it looks alright on its own, how about next to another font? Specifically, how does it look with Una Script?

Pairing test with Una Script

Pairing test with Una Script

First thing to note here: the sizes are similar enough to not really complain about! This would have been a huge problem if not for the work I did in Section I, so hooray for that. Other than that, the weight has a huge contrast, and this was noted when I was discussing the stroke widths in Section III; heavier would not work at all with the font, so if I want them to be the same weight, that will be something to work on for Una Script.

Again, the issues here are mostly Script’s fault, not this font, but there is also the x-height inconsistency to note. It looks like Script has much taller lowercase letters here, because they tend to be higher up while also being very inconsistent between glyphs. I don’t know if I want to go through and change this, but it’s a big consideration with respect to future work on that font.

What if we use Una Mono alongside another font like Noto Sans? Then we see a better consistency in size, but there is still a slight difference in weight between “Regular” fonts:

Pairing test with Noto Sans Regular

Pairing test with Noto Sans Regular

However, in this case we can reduce that contrast significantly by choosing a different weight for Noto Sans, such as SemiBold:

Pairing test with Noto Sans SemiBold

Pairing test with Noto Sans SemiBold

It’s safe to say, from these tests, that Una Mono Regular is actually more of a SemiBold weight; though, as far as I know, there is no standard for what each font weight looks like. I may consider for future work, on both Una Mono and Script, adding variable weights, and aiming to create more consistent styling across them in that regard.

That was everything I wanted to test, at least with the design itself, I’ll save the work of using it as a web font on una-ada.github.io for a later time.9 Cheers all around, patting myself on the back, go me! See you next time on “Una Makes Fonts for Some Reason” when I’ll “probably” continue to try to make better things in better ways (I’ll at least try)!

Footnotes

  1. In the process of writing out this paragraph, I got distracted by attempting to fix my VS Code settings to add word wrap to Markdown language files. Here’s a useful link about that. ↩︎

  2. Note about my methodology with this, I decided back when working on Una Script that the exported vectors should all be named as their Unicode character name in camel case. This makes it easier to find them later when importing into FontForge. ↩︎

  3. It was at this point that I once again started caring about how VS Code works. Specifically, I ended up having to correct a lot of typos, so I wanted some sort of spellchecker. Looking for one in the marketplace, I came across Code Spell Checker by Street Side Software which not only will do spellchecking for articles like this one, but also can handle camelCase words in code! Big fan! ↩︎

  4. But there’s 95 characters in U0000! Well, one of those is the space, which doesn’t have any vectors and will be constructed entirely out of bearings in FontForge. ↩︎

  5. Not only can this be a huge pain in the ass when it comes time to import the vectors to FontForge, it also slows the script way down as it has to determine the trim sizes for nearly a hundred layers and it tends to stop if you click away from the window unlike when it’s deselected. ↩︎

  6. This was more complicated in previous fonts because they weren’t designed to be as metrically consistent, whereas the glyphs in this instance were meant to stay around the guidelines. ↩︎

  7. It crashed again! Last time I ran the validation check it didn’t, so I was hoping I could get away with it again. Whatever, I’d probably just ignore the errors at this point anyway, lol. ↩︎

  8. Validation ran just fine on the exporter. Confusingly, a few new issues popped up: new non-integer values and a self-intersecting glyph. Those were pretty easy fixes, but still weird to see at this point. ↩︎

  9. Probably later tonight, if I’m being honest. ↩︎