SDL_ttf renders dull text

Hey all, I’m writing a program with a good deal of text in the GUI, and hitting a roadblock with the quality I’m getting out of SDL_ttf.

The problem seems to be that that TTF_RenderUTF8_Blended (and related functions, and the Shaded ones as well), render with a blurring edge size that doesn’t scale down adequately as the font size decreases. At 72pt it looks good enough, but at 12, text that should be white is more of a middle grey and very blurry.

I’m not scaling the text at all, the TTF file itself is fine – elsewhere it renders sharp, bright, and clear.

Is there just a limit to the quality achievable with SDL_ttf?

The attached screenshot compares the quality in my test program (all of which is below) to a TTF file preview provided by macos’s “font book.” Note that the text in my program should be pure white.

#include <stdio.h>
#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"

#define OPEN_SANS "/Users/charlievolow/Downloads/open-sans/OpenSans-Regular.ttf"

int main()
{
    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();

    SDL_Window *win = SDL_CreateWindow("TTF Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE);
    SDL_Renderer *rend = NULL;
    Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
    rend = SDL_CreateRenderer(win, -1, render_flags);


    TTF_Font *fonts[8];
    fonts[0] = TTF_OpenFont(OPEN_SANS, 12);
    fonts[1] = TTF_OpenFont(OPEN_SANS, 14);
    fonts[2] = TTF_OpenFont(OPEN_SANS, 16); 
    fonts[3] = TTF_OpenFont(OPEN_SANS, 20);
    fonts[4] = TTF_OpenFont(OPEN_SANS, 24);
    fonts[5] = TTF_OpenFont(OPEN_SANS, 30);
    fonts[6] = TTF_OpenFont(OPEN_SANS, 36);
    fonts[7] = TTF_OpenFont(OPEN_SANS, 42);
    SDL_Color white = {255, 255, 255, 255};
    SDL_Color grey = {40, 40, 40, 255};

    int quit = 0;
    while (!quit) {
        SDL_Event e;
        while (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                quit = 1;
            }
        }

        SDL_SetRenderDrawColor(rend, grey.r, grey.g, grey.b, 255);
        SDL_RenderClear(rend);

        SDL_Rect txt_box = {10, 10, 0, 0};
        for (int i=0; i<8; i++) {
            SDL_Surface *surface = TTF_RenderUTF8_Shaded(fonts[i], "I look meh.", white, grey);
            SDL_Texture *texture = SDL_CreateTextureFromSurface(rend, surface);
            SDL_QueryTexture(texture, NULL, NULL, &(txt_box.w), &(txt_box.h));
            SDL_RenderCopy(rend, texture, NULL, &txt_box);
            txt_box.y += txt_box.h + 5;
        }

        SDL_RenderPresent(rend);
        SDL_Delay(10);
    }
}

Shouldn’t the window be made with SDL_WINDOW_ALLOW_HIGHDPI flag to make full use of the native pixel density?

1 Like

Probably! I tried, and it certainly is a drastic improvement. Is there a standard “easy” way to handle the resulting scaling issues that also preserves the quality improvement (SDL_RenderSetScale gets me back where I started quality-wise), or does it all just need to be handled manually? Seems like a lot of extra work, though probably worth it for this quality improvement.

What happens if you render it to a smaller dstrect, does that make it sharper and solve the problem?

That would be an extremely convenient hack but unfortunately no, rendering to a dstrect whose dimensions differ (in either direction) from the surface dimensions seems to result in weird artifacts and overall quality degradation.

I ran the code on my machine and it looks perfect to me. (This is a screenshot of a screenshot, so you can see the individual pixels if you try.)

Well, perhaps I’m picky :slightly_smiling_face: but yes, that’s what mine looks like too, and I don’t consider it usable for a GUI in the year 2023. There’s a really conspicuous gulf between the quality of that text and other GUIs, at least on my display — see night and day comparison of 12pt in attached screenshot.

Piotr’s suggestion gets me the quality I’m looking for, and will also improve some curves I’m drawing, so I think it’s worth the lift of scaling everything appropriately.

What “resultant scaling issues”? As far as I remember, the only significant change I had to make to my app to handle the HIGHDPI situation was to use SDL_GL_GetDrawableSize(), which always returns the window dimensions in pixels. rather than SDL_GetWindowSize().

Great to know about that function, thank you. I have some fixed dimensions scattered throughout my program that I need to scale programmatically, and I’ll need to select a font size dependent on whether or not there’s scaling (TTF_OpenFont([path], 12) opens a font that renders at 6pt on a high dpi display, but will be true 12pt otherwise). I was daunted when I saw my program newly confined to the upper left corner of the window, but it’s not as bad as I had thought.