Default font on macOS extremely dated - Proposal to update

JUCE 6 still uses Lucida Grande as the default font face on macOS. This hasn’t been the default system font for over 7 years and 7 major OS releases (as of OS X Yosemite, 2014). This is, of course, not a big deal, but it does mean that anything built without explicitly overriding the defaults looks very dated, and this happens to apply to many JUCE-based plugins and applications on the market. Beyond the issue of 3rd party products, this also applies to JUCE itself, for instance, the Projucer is still using this dated font as well.

An update to the current system typeface would mean that new applications developed with JUCE would automatically look more current and modern, and fit in better with the look and feel of the operating system.

https://developer.apple.com/fonts/

5 Likes

There’s now a workaround for this issue on the juce8 branch. The default platform typeface can now be found with Typeface::findSystemTypeface(). This works for all platforms, not just macOS.

We haven’t updated the default fonts because the platform fonts are generally not metrically compatible with the old default fonts. Replacing the default font for existing apps would break text layouts in those projects.

To opt-in to using system fonts, you can call LookAndFeel::setDefaultSansSerifTypeface(), passing the result of Typeface::findSystemTypeface(). After opting in, it’s a good idea to make sure you specify sizes for system fonts in points, rather than in ‘JUCE font height’ units. Point sizes for the platform fonts are more likely to be portable (render at a similar size) across platforms.

We’ve made some related changes to make it easier to work with point sizes here:

4 Likes

This is awesome!

Just to clarify, does this mean use the new portable metrics with FontOptions?

The Font and FontOptions constructors that take a ‘size’ will use that size to set the height of the ascender + descender of the font. However, most non-JUCE applications will set font sizes in points, where the point size is the number of points that will fit into one “em unit”. The sum of ascender and descender is often different to the “em size” of the font.

The new functions Font::setPointHeight and FontOptions::withPointHeight specify the size at which one em-unit should be drawn, which is more compatible with how rendering works in non-JUCE apps.

This is different to the distinction between legacy/portable metrics, which specify how the font metrics should be determined. Fonts may specify typographic metrics in several different ways, depending on the font format, and each OS uses slightly different methods to extract metrics from font data. The ‘legacy’ font metrics mode will use the platform’s built-in metrics functions, which may mean that ascender/descender sizes are computed differently for the same font data, depending on the platform. The ‘portable’ mode computes metrics in exactly the same way on all platforms, meaning that a given font file will have the same metrics on all platforms.

2 Likes

Ah, thanks for the clarification. So this casually adds css-like metrics, where one specifies the size of 1 em in logical pixels? If so, that’s an awesome leap forward, as all prior juce font “heights” have traditionally been hard to translate between other programs…

Replacing the default font for existing apps would break text layouts in those projects.

I do wish JUCE felt confident to go ahead and make things like this a breaking change, providing a workaround to stay on legacy. This way around means every new app will have to “remember” to apply the workaround otherwise (perhaps unknowingly) have legacy behavior…

Unfortunately, the old-style JUCE sizing causes the Windows and macOS platform fonts to render at significantly different sizes. On Windows, Segoe UI renders quite a bit smaller than Verdana, the old default, when using “JUCE units” instead of points.

If we’d made the platform font the default, then lots of text in our demos, examples, and the Projucer would have been uncomfortably small on Windows. To fix this, we would have needed to either opt-out every project bundled with JUCE, or update every demo project to specify fonts sizes in points. These are both big jobs, especially the latter. Opting-out all of the demo projects isn’t a great solution, because it means that users can’t easily check the “right way” to do things. It might even cause users to think that opting-out is preferable, if they copy-paste directly from the examples.

Consider also that some of the font sizes that would need to change are in JUCE LookAndFeel classes, or created ad-hoc in JUCE components. Using the platform fonts requires specifying font sizes in points, but updating all the LnF classes to use points will break layouts in existing apps. It’s not straightforward to provide a simple “opt-out” toggle, because users may need to reinstate each of the old font sizes in JUCE units. I can’t think of a great solution to this problem. I think we’d probably end up needing to write a LnF_V5 class, updating font sizes in every function that draws text. Again, this is likely to be a big job.

In short, making this the default in a way that is easy to opt-out of is surprisingly tricky, and has the potential to create a lot of work that’s difficult to justify at the moment. Having this change be opt-in has no risk of breaking existing projects.

1 Like

Thanks, as always, for the considered detail!

or update every demo project to specify fonts sizes in points

I appreciate that it’s non-trivial. But if using FontOptions and specifying system font sizes in points is the new way forward, ideally the demos, tutorials and brand new apps would align and (eventually) reflect this. Personally, I’d settle to never again see Lucida Grande or drawFittedText when I start a new app :see_no_evil: but for now I’ll pop the workaround in pamplejuce…

Now we’re talking! Sign me up. JUCE could spend $500-1000 on a real UI designer and together we could make something modern looking :slight_smile:

2 Likes