SDL2 SDL2_TTF ugly rendering of accents and other alphabets

Hi,
(and thanks for all the work you’ve done with SDL)

My problem

I’m using SDL2 and SDL2_TTF to try to render the two following strings with the following fonts:

“Un ?uf ?trange” (with an accent and an ‘?’) rendered with Liberation Serif

'15#1” with Arundina Serif (available on most Linux distributions)

As you can see on the following screenshot, the rendered text is quite ugly and doesn’t look very natural:

[Image: http://oi44.tinypic.com/35b5beo.jpg ]
On the left is the SDL window, on the right is the way the text is displayed on LibreOffice with the same fonts and the same sizes.

I remember running in this problem in the past but I didn’t pay much attention. Now I’m wondering about what might cause this problem.
For the rendering, I have used

TTF_RenderUTF8_Blended

I have also tried with TTF_RenderText_Blended, _Shaded and _Solid but to no avail.

I’m running Fedora 20 but I had the same problem with Fedora 19, Ubuntu…

[b]The code[b]

Code:

#include<assert.h>
#include<locale.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<SDL2/SDL.h>
#include<SDL2/SDL_ttf.h>

static SDL_Renderer *s_renderer;
static SDL_Window *s_window;

static bool start_sdl(void) {
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
fprintf(stderr," Couldn’t initialize SDL2!\n=>\t%s\n", SDL_GetError());
return false;
}

if(TTF_Init() != 0) {
	fprintf(stderr, "Couldn't initialize SDL2 ttf!\n=>\t%s\n", TTF_GetError());
	return false;
}

return true;

}

static bool create_window(int width, int height) {
SDL_WindowFlags flags = 0;

s_window = SDL_CreateWindow("No title",
	SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
	width, height, flags);

if(!s_window) {
	fprintf(stderr, "Couldn't create a %dx%d window!\n=>\t%s\n", width, height, SDL_GetError()); 
	return false;
}

Uint32 renderer_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;

s_renderer = SDL_CreateRenderer(s_window, -1, renderer_flags);
if(!s_renderer) {
	fprintf(stderr, "Couldn't create a renderer for %dx%d window!\n=>\t%s\n", width, height, SDL_GetError());
	return false;
}

return true;

}

static void stop_sdl(void) {
assert(s_window != NULL);
assert(s_renderer != NULL);

SDL_DestroyRenderer(s_renderer); s_renderer = NULL;
SDL_DestroyWindow(s_window); s_window = NULL;

/*
 * quit SDL_ttf and SDL
 */

TTF_Quit();
SDL_Quit();

}

int main(void) {
start_sdl();
create_window(800, 600);

TTF_Font *font_standard = TTF_OpenFont("LiberationSerif-Regular.ttf", 52);
if(!font_standard) {
	fprintf(stderr, "Couldn't open font! %s\n", TTF_GetError());
	exit(EXIT_FAILURE);
}

TTF_Font *font_thai = TTF_OpenFont("ArundinaSerif.ttf", 32);
if(!font_thai) {
	fprintf(stderr, "Couldn't open font! %s\n", TTF_GetError());
	exit(EXIT_FAILURE);
}

SDL_Color font_color = {
	0, 0, 0, 0
};

char *text_standard = "Un ?uf ?trange", *text_thai = "*'1*5#1";

SDL_Surface *surface_standard = TTF_RenderUTF8_Blended(font_standard, text_standard, font_color);
SDL_Surface *surface_thai = TTF_RenderUTF8_Blended(font_thai, text_thai, font_color);

SDL_Texture *texture_standard = SDL_CreateTextureFromSurface(s_renderer, surface_standard);
SDL_Texture *texture_thai = SDL_CreateTextureFromSurface(s_renderer, surface_thai);

SDL_Rect dst_standard = { .x = 50, .y = 50 };
SDL_Rect dst_thai = { .x = 50, .y = 200 };

TTF_SizeText(font_standard, text_standard, &dst_standard.w, &dst_standard.h);
TTF_SizeText(font_thai, text_thai, &dst_thai.w, &dst_thai.h);

SDL_SetRenderDrawColor(s_renderer, 255, 255, 255, 0);

SDL_RenderClear(s_renderer);

SDL_RenderCopy(s_renderer, texture_standard, NULL, &dst_standard);
SDL_RenderCopy(s_renderer, texture_thai, NULL, &dst_thai);

SDL_Event event;
bool leave = false;

while(!leave) {
	while(SDL_PollEvent(&event)) {
		if(
			(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE) ||
			event.type == SDL_QUIT
		) {
			leave = true;
			break;
		}
	}

	SDL_RenderPresent(s_renderer);

	SDL_Delay(1000 / 30);
}

SDL_DestroyTexture(texture_standard);
SDL_DestroyTexture(texture_thai);

SDL_FreeSurface(surface_standard);
SDL_FreeSurface(surface_thai);

TTF_CloseFont(font_standard);
TTF_CloseFont(font_thai);

stop_sdl();

return EXIT_SUCCESS;

}

Do you have any idea of what is going on?
Thanks in advance.

I forgot one thing: if I remove the accents from the first string (“un oeuf etrange”) then this string just renders fine.

[Image: http://oi43.tinypic.com/9b9cua.jpg ]

'15#1 :slight_smile:

I noticed that you use TTF_SizeText() with TTF_RenderUTF8_Blended(). Given that you’re using UTF8 strings, I think TTF_SizeUTF8() is more suitable. I guess the TTF_SizeText return the size that’s too wide on the height side, as TTF_SizeText expects the input to be ANSI string, so the texture is stretched on the height side.

I tried the code on Windows, slightly modified to use the UNICODE variant, and the output looks great.

After take another look at the screenshot, the text surface are stretched in both width and height sides. It obvious that the dest rect is wrong.

You could instead use SDL_QueryTexture to get the w and h of the texture. I think it’s faster than calling TTF_SizeText() (as there would be no size/bounding recalculation), and it might be more accurate.

I noticed that you use TTF_SizeText() with TTF_RenderUTF8_Blended(). Given that you’re using UTF8 strings, I think TTF_SizeUTF8() is more suitable. I guess the TTF_SizeText return the size that’s too wide on the height side, as TTF_SizeText expects the input to be ANSI string, so the texture is stretched on the height side.

I tried the code on Windows, slightly modified to use the UNICODE variant, and the output looks great.

After take another look at the screenshot, the text surface are stretched in both width and height sides. It obvious that the dest rect is wrong.

You could instead use SDL_QueryTexture to get the w and h of the texture. I think it’s faster than calling TTF_SizeText() (as there would be no size/bounding recalculation), and it might be more accurate.

You’re completely right! I tried with TTF_SizeUTF8 and SDL_QueryTexture and both worked fine. So the problem is solved. Thanks!

-8#1 [Wink]