Here we go again: Mac vs Win font rendering

Hey guys,
here we go again with the never-ending story of Mac vs Win fonts rendering. I still can’t figure why custom fonts looks so ugly on windows. Here’s an example

Mac:

Win:

As you can see, on Windows the font height and vertical alignment is wrong and looks kinda stretched. The font also looks thinner.

What I’m doing is:

  1. On my LAF, I have:
static Typeface::Ptr getTypefacePlain()
{
    static Typeface::Ptr typeface = Typeface::createSystemTypefaceFor(BinaryData::PTS55F_ttf, BinaryData::PTS55F_ttfSize);
    return typeface;
}

static Typeface::Ptr getTypefaceBold()
{
    static Typeface::Ptr typeface = Typeface::createSystemTypefaceFor(BinaryData::PTS75F_ttf, BinaryData::PTS75F_ttfSize);
    return typeface;
}
  1. On the Editor I have:
const Font labelFont = Font(laf.getTypefacePlain()).withHeight(12.0).withExtraKerningFactor(0.1f);
anyLabelOnScreen.setFont(labelFont);

I tried with both DirectWrite enabled and disabled. Nothing changes

Any hint would be greatly appreciated.

Thanks!

This may be relevant:

1 Like

Thanks Ben. I found an error on what I were doing (using Height instead of PointHeight) and fixed the clipping of the top part of my labels, but still the fonts render differently.

I read the thread you posted and found another thread by @matt with is works on D2D implementation. I’ll try his fork and see if the font rendering improves. In the meantime, I made some tests with a 4k monitor on my windows machine. With W10 default 150% scaling, the rendered fonts are blurry; totally pixellated with 200% scaling and nice (still thin) with 100% scaling.

Despite the scale value, Ableton Live 11 GUI was always perfect looking. So the problem looks JUCE related.

Is everything pixelated, or just fonts? Have you disabled “Auto-scale plugin window”? You can do this by right-clicking the plugin before adding it.

Edit: it was just the fonts and disabling “Auto-scale plugin window” does the trick. Thanks @reuk
Fonts are still rendered differently and looks thin on windows, but I guess this is related the post Ben linked earlier.

For what it’s worth, I didn’t see a big difference using DirectWrite + the JUCE software renderer. I did see a significant difference using the Direct2D renderer (which always uses DirectWrite).

Matt

image

JUCE (Windows DirectWrite fonts) vs ‘native’ DirectWrite rendering)

The main difference I notice between JUCE software renderer and native is the sub-pixel anti-aliasing (the colored fringes). You can also see that the center bars of the ‘A’ and ‘E’ are snaped to the pixel grid in native Direct-2D, a trick that increases clarity at the expense of distorting the font a little.
Judging by the uneven ‘brightness’ across words, I would also hazard a guess that JUCE is using screen-color-space antialiasing (sRBG) rather than the more accurate linear color-space anti-aliasing.

So the difference is pretty subtle. JUCE is doing a pretty good job, but native renderers are very sophisticated at wringing that last little bit of clarity out of a font.

4 Likes

I tried with both DirectWrite and JUCE_DIRECT2D enabled, but I haven’t seen a huge difference. I haven’t tried your fork yet since I’m still on 6.0.8

If you do try my fork, make sure you select the Direct2D renderer in your window constructor.

getPeer()->setCurrentRenderingEngine(1);

Matt

Hi Matt,
I tested your Direct2D renderer. It is very nice :+1:.

But I have a problem:
For me it seems like all juce popup menus are not rendered with this renderer.
They do not show any color-space anti-aliasing.

Do you have a hint how I could fix this?
Have I missed something?

The renderer of the popup menu window shown by

getPeer()->getCurrentRenderingEngine();

is already 1.

In case I add

getPeer()->setCurrentRenderingEngine(1);

to the popup menu window the window is shown empty (no menu entries and no borders).

Steffi

Hi Steffi-

Make sure that HWNDComponentPeer is set up to use Direct2D by default.

Specifically, look in juce_win32_Windowing.cpp, and check that the constructor for HWNDComponentPeer looks like this:

    HWNDComponentPeer (Component& comp, int windowStyleFlags, HWND parent, bool nonRepainting)
        : ComponentPeer (comp, windowStyleFlags),
          dontRepaint (nonRepainting),
          parentToAddTo (parent),
#if JUCE_DIRECT2D
          currentRenderingEngine (direct2DRenderingEngine)
#else
          currentRenderingEngine (softwareRenderingEngine)
#endif

Matt

Hi Matt,

thank you for looking into this issue.

I found a workaround: The popup menu window needs to be opaque. Then after addToDesktop creates the peer I need to force the rendering engine again with:

getPeer()->setCurrentRenderingEngine(1);

Now the popup menus show the same nice color-space anti-aliasing.

Steffi

1 Like

Hi Matt,

I recognized that setting the popup menu window opague is enough to have the new renderer working.

I wonder if the technique for text rendering could be used to render svg icons in the same way, so that they could have the same nice color-space anti-aliasing.

Steffi

Quite possibly, but I don’t think I can help there. The JUCE renderers really just perform low-level operations.

Matt