Is there a way to look into the fonts?

Is there a way to "look" into the fonts? Either by reading the cft files in the SDK (listing their content about which characters it contains, the size of the characters, etc) or by displaying them (and I hope you won't tell me to look at them by displaying text in the devices in the simulator)

Also: how much the cft fonts used by the simulator can be "trusted" to make decisions regarding the real devices' fonts?

  • YEAH....

    I also thought about that automated "do a step, take a screenshot" even before getting to this problem, just for the very general goal of tests and taking screenshots on every device. Of course no way doing it (except the even hackier windows thing but I don't even have a windows in the last 30 or so years...)

    The thing is that the effort some of us waste on these things * many devs who waste this time would take the Garmin ecosystem so far forward would Garmin just care a bit. We're doing all kinds of hacks for the most legitimate goals to get small pieces of information that should've been automatically generated and released by Garmin years ago.

    Anyway, yesterday I even found bugs in how SimpleDataField works, but of course I don't even know if it's a real one or in the simulator only. But the biggest problem with all these ideas, that even if they would all work and be pixel perfect on the simulator, they would still be buggy because the simulator itself doesn't simulate perfectly (that's the known issue about the fonts, and then I still haven't spoke about bugs, or just wrong data in the devices json files in the SDK - which again should be generated automatically, so I don't understand how can be there such mistakes like missing layouts: or

    So maybe we, pixel perfect devs should not waste no time on these things and just create crap apps...

  • The problem is, there is no way to do it programmatically

    Not sure if you didn't notice my solution (posted upthread), or if you're saying there's something wrong with it (if so, what?).

    Basically, that's exactly what it does. At least, it programmatically tells you what the simulator would do - which I accept isn't always what the device would do.

  • Of course no way doing it

    I'm pretty sure there is a way to do this on the Mac.

    For example if you wrote an Electron app to automate the build/run, it has built in capabilities that let it do screen captures, including other windows - providing you explicitly grant the app suitable permissions.

    There are probably many other ways to do it. Eg you could probably use AppleScript to control the ScreenShot utility - in which case you could probably do it all from a bash script (or python, or whatever).

  • Well my use case is that I'd like to find the biggest font I can use that fits the field's size

    That's pretty much what I use the font analyzer for. I do exactly that computation, but I do it offline. Of course, you can only do that if you know what the text is going to be, but for data fields, typically you do - or at least, you know the range. I also use it to determine whether I need to switch between hh:mm:ss and hh:mm for any given sized field, and similarly whether I can report 1 or 2 decimal places for numeric fields.

  • I'm pretty sure I've used your tool in the past and it does indeed extract all the font metrics.  However, I don't think it tells you the actual rendered height of a given font because it just returns the same info that the SDK returns.  So there will be space reserved above and below characters for accents, etc.

    Definitely correct me if I'm wrong here, because it would be awesome if this really does give you the rendered height of, say, a "Z" or "z" character.  That's what I'd really like to get, and I don't think there's any way to do it without drawing the text and counting the pixels.

  • However, I don't think it tells you the actual rendered height of a given font because it just returns the same info that the SDK returns

    As I said above, not quite. It also tells you the internalLeading, which is a pretty big clue as to what's going on above the characters. But as I also said above, it's not well defined.

    It's usually what you expect it to mean (and I've not found any exceptions in the Garmin fonts), but it's literally up to the font designer how it's defined. They can put 10 pixels of space above every single character, including ones with diacriticals, and say that internalLeading is 0. Or they could have some "normal" characters extend all the way to the top, and set internalLeading to 10.

    That said, a font designer should be trying to specify these things so that programs that use the font attributes in their intended sense get good looking results.

  • I agree with marksilbert that it would be great to have the internalLeading per char and not only per font. Imagine you have an app on github and people are contributing translations in all kind of languages. Now you compile your app but you don't really know much about the characteristics of the texts even though you do know all the texts.

  • Ok - I already knew roughly where the glyph data was stored, so it was just a case of unpacking it, and counting the blank lines at the top and bottom.

    The latest version (v1.1.47) includes glyphAscent and glyphDescent for each character.

    That makes it so verbose that if you ask it for the data for '*.cft' it falls over because it tries to generate a string longer than javascript can handle (I think thats 4G). So I added a "--chars" option that lets you specify a list of characters that you want information about.

    The following only produces about 200k of output:

    % npx cft-font-info "*.cft" --chars="0"

  • cool!

    BTW I see it's not trivial, but looking at the data, basically most of the file are the json keys, so maybe if you can come up with some kind of representation in a csv file it probably will be able to shrink it a bit

  • basically most of the file are the json keys

    I've added a --char-info-as-array option, which changes the charInfo array elements to arrays, and adds a per font charInfoNames array, telling you what each element of the subarray is. So now you can do:

    % npx cft-font-info "FNT_ROBOTO_11B.cft" --chars="0" --char-info-as-array | jq .
      "FNT_ROBOTO_11B": {
        "height": 18,
        "ascent": 14,
        "internalLeading": 2,
        "charInfo": [
        "charInfoNames": [
      "devices": {}

    Obviously, if you're only getting one character (as above), it doesn't help. But for fonts with 20000+ characters, it saves repeating those field names 20000 times.

    I also rewrote the way it generates the output, so it streams one font at a time, so there's no longer a limit (and you start getting data immediately, rather than having to wait until the end). It turns out the string length limit was more like 512MB - so it wasn't quite as bad as I thought. Even without the --char-info-as-array option, listing all fonts with all characters only produces about 600M.