Profile Picture

Garmin Watch Faces: Custom Fonts

December 18th, 2020
Garmin Watch Faces: Custom Fonts

I recently spent some time developing a custom watch face for my Garmin Forerunner 245. Because I was mimicking the Apple Watch Nike+ watchface, I needed to import a custom font face for the numbers. Unfortunately, Garmin doesn’t make importing fonts easy, especially on Macs. Here’s how I worked around Garmin’s limitations to build my watch face!


Garmin watches don’t support TrueType, OpenType, or any other modern standards. Instead, they only support .fnt files, an archaic bitmap font format. Garmin recommends BMFont which can convert TTFs to FNTs. Unfortunately, BMFont has some limitations:

  • It doesn’t support OTF files, and TTF->OTF converters don’t always work well
  • BMFont doesn’t support Macs

Enter (custom) FontBuilder

FontBuilder is a multiplatform bitmap font generator that supports both TTF and OTF files. It seemed perfect for my needs! Unfortunately, vanilla FontBuilder isn’t quite compatible with Garmin watches. Since FontBuilder doesn’t seem to be actively maintained, I forked FontBuilder with the following changes to add support for Garmin watches:

  • Fixed Homebrew support by adding /usr/local/lib to the list of libraries in the QT project file.
  • Added chars count=NUM_CHARS to the output FNT file.
  • Antialiased by setting RGB values instead of using the alpha channel (which Garmin watches don’t understand). For example, if a pixel should be 75% transparent, I set its ARGB value to 0xFFC0C0C0 instead of 0xC0FFFFFF.

Custom font workflow

Here’s how to use a custom font in your Garmin watch face:

  1. Export a FNT file using my FontBuilder fork

  2. Add the font to your watch face’s resources: <font id="my_font" filename="my_filename.fnt" antialias="true" />

    • Make sure to set antialias="true" or your font will look silly
    • If you know which glyphs you need for your watch face, you can use the filter attribute: <font id="demo" filter="0123456789:" ... />
  3. Load your resource in onLayout():

font = Toybox.WatchUi.loadResource(Rez.Fonts.id_my_font)
  1. Use your font in onUpdate() by calling dc.drawText(x, y, font, ...):
  2. Rebuild your project for the simulator
  3. If all goes well, you should see your custom font appear in the simulator!


Enjoyed this post? Follow me on Twitter for more content like this. Or, subscribe to my email newsletter to get new articles delivered straight to your inbox!

Related Posts

The Buck Stops With You
Infrastructure & Business Monitoring
63 Tips for Better Workplace Communication for Software Engineers
Scroll to top