Official development blog

Full UI Upscaling, Part 4: Simpler Lightweight Fonts

So we’ve developed the theories, we’ve got mockups, we’ve got the necessary architecture… surely it’s time to start building the new UI layout, yeah? Not so fast!

It’s true we could start now, but on the horizon I could already see the increasing usefulness of another supporting feature, and decided it was a good opportunity to finally automate Cogmind’s font scaling.

Cogmind has always included many fonts available at many different sizes, all of these stored as bitmaps for pixel-perfect crispness. Each requires its own image file, and in the past I have always manually upscaled them to ensure availability at the appropriate higher resolutions, which means even more files.

Well with the advent of map zooming, which itself needs 2x upscale versions of all fonts within each set, and this whole UI upscale project, which unlocks an average 33% font size increase for everyone, we’re going to need quite a few more upscaled bitmap font files and going forward it doesn’t really make much sense to keep doing this manually.

REX, Again Again

Okay if anyone’s keeping count this will be the fourth time I’ve revisited the engine for a major update since starting map zoom and UI scaling work xD

Hi, REX.

I thought this would be a quick project, but it actually took several days to finally finish this feature because I ended up rewriting a lot of the engine’s font handling code, encountering a few challenging (hair-ripping) bugs along the way. The original system had made a lot of assumptions which would no longer hold true, and I wanted more features on top of the autoscaling as well, like only generating upscaled fonts once they’re actually needed (yay for faster startup), and having all font sets reusing the same source file share a single reference image in memory rather than having multiple copies of the same bitmap. Individually nothing too complex, just a lot of changes necessary to the original architecture to make these features possible.

Once again back in the good old REX testing environment, I set to testing two new syntax options for the font set configuration file:

  • “NewFontName [SourceFontName*2]” would create an entire new font set by upscaling an existing one, in this case by a factor of 2. (A font “set” means a collection of text, tiles, zoomed text and so forth, all categorized under a single name and selected as an option by the user.)
  • “<source_image_name*3>” is a sample of syntax usable in any single field for a bitmap font source image, instead taking another image and upscaling it by the specified factor.

A sample config file used during REX testing, in some cases with font sets purely loaded from files, and in others partially or fully generated based on existing sets or bitmaps.

This same format is used by anything else built on the engine, so both Cogmind and REXPaint can benefit from this, the latter of which I hope to also release a new version before long!


A quick autoscaling test back in Cogmind, here using a 2x scale of a 4×8 font, therefore turning it into a 8×16 font for a 960p window. (This 4×8 font is technically distributed with Cogmind, but since it’s too small to be reasonably considered by players, or needed at all, it is not available by default and must be activated manually.)

Cogmind Applications

Cogmind’s last public release, Beta 12, includes a total of 118 bitmaps font images, and that was before all the map zooming and Beta 13 work, so without this autoscaling feature that number would balloon significantly.

As of writing, Beta 13 has currently dropped that file count to 80, this despite the zooming, nine brand new font types, and supporting even more large options derived from smaller ones.

I had to spend a while going back through all those files to confirm which were original files and which were upscaled--in most cases there were records, but I had to be sure, and did find a few outliers to which I made further manual modifications to their upscaled versions, or sourced from multiple different sets. Those required special treatment, but otherwise it was really nice to cut down on the clutter.


Comparing Cogmind’s original font config file to the new one with automated upscaling enabled (and zoom support!).

As of the current Beta 13 prerelease, the current max font size included with Cogmind is 48, needed for 5K displays, but with the new upscaled UI the max needed for that resolution will be 64! Definitely about time to get automated scaling…

New font sizes aside, this also saves time when new tiles are added and need to be inserted throughout the images, since tiles themselves are also part of the font bitmaps. Tiles aren’t added very often, but a new batch is indeed being released gradually over the next several versions.

Since I was working with fonts anyway, I also took advantage of this opportunity to add brand new options! In classic terminal roguelike style, some people like to switch their display font after a while in order to freshen up the whole experience, so in addition to others who simply want more options from which to select their favorite for readability or stylistic preferences, that’s another good reason to make sure there is a good variety of styles available.

The main two new typefaces are Tamsyn and Cherry, available at several sizes.


Sample Cogmind screenshot using size 24 Tamsyn.



Sample Cogmind screenshot using size 14 Cherry Shadow,  for which I added a slight drop shadow I think looks pretty cool, especially on a light background like item labels.

While I was at it, I also made other font-related improvements, like having Cogmind’s options menu list fonts from largest to smallest to be able to more easily adjust style via the menu without changing map size. The original approach based purely on how they’re listed in the config file didn’t make sense, and I’m not sure why I left it that way for so long.


New sorting order for the font options menu!

Pixel Corruption

Shortly after releasing a build with autoscaled fonts to patrons, a wild bug appeared! Apparently some people were seeing artifacts on the display…


Screenshot excerpt showing visual oddities. (sample provided by Luigi; you’ll have to open it at full size to see some of the evidence)

At first we weren’t sure what it was, since it was only affecting a few people, and recent SDL DLL optimizations aimed at improving rendering speed had also been introduced as well. But bugs aren’t all that elusive if they only affect some people and a discernible, repeatable pattern emerges, which happens to be the case here. That these artifacts only appeared for players using very high resolutions suggested it might be an issue with font scaling, since all of the high-resolution fonts are upscales.

So I set up a bunch of tests to confirm, and eventually found that some large fonts ended up with these artifacts when scaled, and in all cases had a scaling multiplier of at least 3. How weird!

Anyway it’s now even more clear this has gotta be something with the scaling process, right, for which I had actually just plugged in SDL_gfx, a common companion library for doing this sort of thing. Cue stepping through its zoomSurface() function, specifically zoomSurfaceRGBA(), and while comparing how it handled a 2x vs a 3x scale operation, I noticed that there seems to be… a bug in the library?


This code truncates the result of floating point arithmetic, which under the right combination of variables causes the intended optimizations based on these values to generate artifacts.

I’m kinda surprised since this library has been in relatively wide use for over two decades, and even continues to be used alongside subsequent SDL versions, but that code remains the same. Maybe most people tend to use it with smoothing/antialiasing turned on (I had it off because I want crisp), or are using less tightly packed tilesets (or even separate files for their images), all of which may help conceal such an issue from discovery? Or maybe there’s something else at play.

I replaced that whole optimized method with my own brute force scaling solution and *poof* the problem indeed disappeared. It’s only rarely called anyway--as mentioned before fonts are only scaled when they’re first needed, not before or ever again afterward, so we don’t need to worry about performance. (And anyone who actually does need to worry about performance should probably avoid doing this in software mode in the first place :P --that’s probably where all the other potential bug finders went off to…)

This is the fourth in a multi-part series about building Cogmind’s fully upscaled semi-modal interface layout:

This entry was posted in Dev Series: Full UI Upscaling and tagged , , , , . Bookmark the permalink. Trackbacks are closed, but you can post a comment.

Post a Comment

Your email is never published nor shared. Only the anti-spam entry is required. See here for the privacy policy.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>