4

I've been programming a small text adventure game using SDL2 recently and have come across an issue with line wrapping. I am using TTF_RenderText_Blended_Wrapped() to render my strings, and this gives me some nicely wrapped lines. But The line height is an issue, the lines seem squished together, and letters like 'jqg' overlap with letters like 'tli'.

Does anyone know if there is a way to change the line height? TTF_RenderText_Blended_Wrapped() still isn't even in the documentation for SDL_ttf. Should I just write my own text wrapping function?

The font size is 16pt, styling is TTF_STYLE_BOLD, and the font can be found here. The code below should reproduce the error, there is almost no error checking though, use at your own risk. Here is the output of the code:

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

int main(int argc, char *argv[]) {
    SDL_Window *gui;
    SDL_Surface *screen, *text;
    SDL_Event ev;
    TTF_Font *font;
    int running = 1;

    const char *SAMPLETEXT = "This is an example of my problem, for most lines it works fine, albeit it looks a bit tight. But for any letters that \"hang\" below the line, there is a chance of overlapping with the letters below. This isn\'t the end of the world, but I think it makes for rather cluttered text.\n\nNotice the p and k on line 1/2, and the g/t on 2/3 and 3/4.";

    // init SDL/TTF
    SDL_Init(SDL_INIT_EVERYTHING);  
    TTF_Init();

    // Open and set up font
    font = TTF_OpenFont("Anonymous.ttf", 16);
    if(font == NULL) {
        fprintf(stderr, "Error: font could not be opened.\n"); 
        return 0; 
    }
    TTF_SetFontStyle(font, TTF_STYLE_BOLD);


    // Create GUI
    gui = SDL_CreateWindow("Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 
            640, 480, SDL_WINDOW_SHOWN);
    // Grab GUI surface
    screen = SDL_GetWindowSurface(gui); 

    // Clear screen black
    SDL_FillRect(screen, NULL, 0);
    // Draw some text to screen
    SDL_Color color = {0xff, 0xff, 0xff, 0xff};
    text = TTF_RenderText_Blended_Wrapped(font, SAMPLETEXT, color, screen->w);
    SDL_BlitSurface(text, NULL, screen, NULL);

    while(running) { // Main loop
        while(SDL_PollEvent(&ev)) {
            switch(ev.type){
                case SDL_QUIT:
                    running = 0;
                    break;
            }
        }

        SDL_UpdateWindowSurface(gui); // Refresh window
        SDL_Delay(20); // Delay loop
    }

    // Destroy resources and quit
    TTF_CloseFont(font);
    TTF_Quit();

    SDL_FreeSurface(text);
    SDL_DestroyWindow(gui);
    SDL_Quit();

    return 0;
}
Jacob H
  • 864
  • 1
  • 10
  • 25
  • I don't see that there is any way to control line-spacing. [Here is a link to the source code](https://fossies.org/dox/SDL2_ttf-2.0.14/SDL__ttf_8c_source.html#l01876). Have you tried a different font? Have you compared the values returned by `TTF_FontHeight()` and `TTF_FontLineSkip()`? – ad absurdum Jun 22 '17 at 15:34
  • Thanks for the link. The line skip is greater than the height, and I have tried a couple fonts. I'm sure there is a font somewhere that will work, but I would rather not go searching. – Jacob H Jun 22 '17 at 15:48
  • Can you post the font you are using? I tried with a few fonts on my system and was unable to reproduce the issue. – Tim Jun 22 '17 at 21:06
  • [This is the font](https://www.fontsquirrel.com/fonts/Anonymous), I tried a couple others, but if you aren't having problems I should probably test a few more. – Jacob H Jun 22 '17 at 21:09
  • Can you post an image of the incorrectly rendered text? Also, what font size and styling are you using? – Tim Jun 22 '17 at 21:52
  • Font size 16, bold text, although I tested it with plain formatting. I've added an image as well as some code to my post. – Jacob H Jun 22 '17 at 22:20

1 Answers1

4

The easiest solution is to find a font that doesn't have that issue. The FreeMono font has more spacing:

using the FreeMono.ttf

From looking at the source code for TTF_RenderUTF8_Blended_Wrapped, which is called by TTF_RenderText_Blended_Wrapped, there is no configurable way to set the spacing between the lines. See const int lineSpace = 2; on line 1893.

However, even though lineSpace is set to 2, it is not being used when computing the address of each pixel to render. This is effectively setting the line spacing to 0. I reported this as a bug in the SDL_ttf library: https://bugzilla.libsdl.org/show_bug.cgi?id=3679

I was able to fix the issue in SDL_ttf 2.0.14 with the following change:

--- a/SDL_ttf.c Fri Jan 27 17:54:34 2017 -0800
+++ b/SDL_ttf.c Thu Jun 22 16:54:38 2017 -0700
@@ -1996,7 +1996,7 @@
         return(NULL);
     }

-    rowSize = textbuf->pitch/4 * height;
+    rowSize = textbuf->pitch/4 * (height + lineSpace);

     /* Adding bound checking to avoid all kinds of memory corruption errors
      that may occur. */

With the above patch applied, your example program shows the correct line spacing with the Anonymous font:

correct line spacing with patched SDL_ttf

Tim
  • 4,790
  • 4
  • 33
  • 41