Search code examples
c++sdl-2sdl-ttf

My SDL_ttf rendered text ends up streched. How do I avoid that?


Here is a minimal example of how I render my SDL text:

#include <SDL_ttf.h>

void runttf()
{
  constexpr auto SCREEN_WIDTH{300};
  constexpr auto SCREEN_HEIGHT{300};
  constexpr auto font_path = "/usr/share/fonts/truetype/fonts-beng-extra/MuktiNarrow.ttf"; //any font on your system
  constexpr SDL_Rect destination = {10,10,200,80};
  constexpr SDL_Color text_color={0,0,0};

  SDL_Init( SDL_INIT_VIDEO );
  TTF_Init();

  auto window = SDL_CreateWindow( "SDL TTF demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
  auto renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
  auto font = TTF_OpenFont( font_path, 28 );
  auto textSurface = TTF_RenderText_Solid( font, "I wish I this would not stretch", text_color );
  auto textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

  SDL_Event e;
  auto run = true;
  while(run) {
    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    SDL_RenderClear(renderer);
    SDL_RenderCopy(renderer, textTexture, NULL, &destination);
    SDL_RenderPresent(renderer);
    while (SDL_PollEvent(&e) != 0)  if (e.type == SDL_QUIT) run = false;
  }

  SDL_DestroyTexture(textTexture);
  SDL_FreeSurface( textSurface );
  TTF_CloseFont(font);
  SDL_DestroyRenderer( renderer );
  SDL_DestroyWindow( window );
  TTF_Quit();
  SDL_Quit();

}

When I render the text I end up with something like this

the program execution

You can see how the way I draw the text makes it stretch across the selected area I want to draw the text in. I would rather have the text show cropped off or something like that - anything but stretched.

Am I using functions incorrectly? Do I need to do more math on rendering and placement of my text? What is the canonical sdl ttf way of rendering non stretched text?


Solution

  • You are setting your destination rectangle to be different than the text that was rendered to the surface so it will stretch.
    You should also free up the surface before your main loop.
    So the code I think you are looking for:

    #include <SDL_ttf.h>
    
    void runttf()
    {
        constexpr auto SCREEN_WIDTH{ 300 };
        constexpr auto SCREEN_HEIGHT{ 300 };
        constexpr auto font_path = "/usr/share/fonts/truetype/fonts-beng-extra/MuktiNarrow.ttf"; //any font on your system
        constexpr SDL_Color text_color = { 0,0,0 };
    
        SDL_Init(SDL_INIT_VIDEO);
        TTF_Init();
    
        auto window = SDL_CreateWindow("SDL TTF demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
        auto font = TTF_OpenFont(font_path, 28);
        auto textSurface = TTF_RenderText_Solid(font, "I wish I this would not stretch", text_color);
        auto textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
        SDL_Rect destination;
        destination.w = textSurface->w;
        destination.h = textSurface->h;
        destination.x = 0;
        destination.y = 0;
        SDL_FreeSurface(textSurface);
    
        SDL_Event e;
        auto run = true;
        while (run) {
            SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, textTexture, NULL, &destination);
            SDL_RenderPresent(renderer);
            while (SDL_PollEvent(&e) != 0)  if (e.type == SDL_QUIT) run = false;
        }
    
        SDL_DestroyTexture(textTexture);
        TTF_CloseFont(font);
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        TTF_Quit();
        SDL_Quit();
    }
    

    Otherwise I think the code looks good. If you don't care about performance as much as the looks, you can use TTF_RenderText_Blended instead of TTF_RenderText_Solid.