Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render text in SDL2?

Tags:

c

sdl-2

I'm using an SDL_Window and SDL_Renderer.

Is it possible to use SDL_TTF with SDL_Render/SDL_Window? If so, how?

like image 596
Ethan Webster Avatar asked Apr 05 '14 20:04

Ethan Webster


People also ask

What is SDL_ttf?

SDL_ttf is an extension library that allows you to generate surfaces from true type fonts. You can get SDL_ttf from here. To install SDL_ttf just follow the extension library tutorial. Installing SDL_ttf is done pretty much the way SDL_image is, so just replace where you see SDL_image with SDL_ttf.

What is SDL renderer?

SDL_Renderer is a struct that handles all rendering. It is tied to a SDL_Window so it can only render within that SDL_Window . It also keeps track the settings related to the rendering. There are several important functions tied to the SDL_Renderer.

What is an SDL surface?

An SDL surface is just an image data type that contains the pixels of an image along with all data needed to render it. SDL surfaces use software rendering which means it uses the CPU to render. It is possible to render hardware images but it's a bit more difficult so we're going to learn it the easy way first.


2 Answers

Yep, it is possible, given that you have a renderer and a window plus you don't really have any thoughts on dabbling with surfaces then you might want to mind on creating texture, here is a sample code

//this opens a font style and sets a size TTF_Font* Sans = TTF_OpenFont("Sans.ttf", 24);  // this is the color in rgb format, // maxing out all would give you the color white, // and it will be your text's color SDL_Color White = {255, 255, 255};  // as TTF_RenderText_Solid could only be used on // SDL_Surface then you have to create the surface first SDL_Surface* surfaceMessage =     TTF_RenderText_Solid(Sans, "put your text here", White);   // now you can convert it into a texture SDL_Texture* Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);  SDL_Rect Message_rect; //create a rect Message_rect.x = 0;  //controls the rect's x coordinate  Message_rect.y = 0; // controls the rect's y coordinte Message_rect.w = 100; // controls the width of the rect Message_rect.h = 100; // controls the height of the rect  // (0,0) is on the top left of the window/screen, // think a rect as the text's box, // that way it would be very simple to understand  // Now since it's a texture, you have to put RenderCopy // in your game loop area, the area where the whole code executes  // you put the renderer's name first, the Message, // the crop size (you can ignore this if you don't want // to dabble with cropping), and the rect which is the size // and coordinate of your texture SDL_RenderCopy(renderer, Message, NULL, &Message_rect);  // Don't forget to free your surface and texture SDL_FreeSurface(surfaceMessage); SDL_DestroyTexture(Message); 

I tried to explain the code line by line, you don't see any window right there since I already assumed that you knew how to initialize a renderer which would give me an idea that you also know how to initialize a window, then all you need is the idea on how to initialize a texture.

Minor questions here, did your window open? was it colored black? if so then my thoughts were right, if not, then you can just ask me and I could change this code to implement the whole section which consists of a renderer and a window.

like image 172
kdyz Avatar answered Oct 02 '22 09:10

kdyz


SDL_ttf minimal runnable example

enter image description here

Not super efficient, but easy to integrate. For efficiency see: How to render fonts and text with SDL2 efficiently?

Kept in a separate repo than the main SDL source, but hosted on the same official server, so should be fine: http://hg.libsdl.org/SDL_ttf/

Newlines won't work. You have to work with line heights.

Compile and run:

sudo apt-get install -y libsdl2-dev gcc -lSDL2 -lSDL2_ttf -o ttf ttf.c ./ttf /usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf 

You must pass the path of a TTF font file to the program.

ttf.c

#include <stdlib.h>  #include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h>  #define WINDOW_WIDTH 300 #define WINDOW_HEIGHT (WINDOW_WIDTH)  /* - x, y: upper left corner. - texture, rect: outputs. */ void get_text_and_rect(SDL_Renderer *renderer, int x, int y, char *text,         TTF_Font *font, SDL_Texture **texture, SDL_Rect *rect) {     int text_width;     int text_height;     SDL_Surface *surface;     SDL_Color textColor = {255, 255, 255, 0};      surface = TTF_RenderText_Solid(font, text, textColor);     *texture = SDL_CreateTextureFromSurface(renderer, surface);     text_width = surface->w;     text_height = surface->h;     SDL_FreeSurface(surface);     rect->x = x;     rect->y = y;     rect->w = text_width;     rect->h = text_height; }  int main(int argc, char **argv) {     SDL_Event event;     SDL_Rect rect1, rect2;     SDL_Renderer *renderer;     SDL_Texture *texture1, *texture2;     SDL_Window *window;     char *font_path;     int quit;      if (argc == 1) {         font_path = "FreeSans.ttf";     } else if (argc == 2) {         font_path = argv[1];     } else {         fprintf(stderr, "error: too many arguments\n");         exit(EXIT_FAILURE);     }      /* Inint TTF. */     SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);     SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_WIDTH, 0, &window, &renderer);     TTF_Init();     TTF_Font *font = TTF_OpenFont(font_path, 24);     if (font == NULL) {         fprintf(stderr, "error: font not found\n");         exit(EXIT_FAILURE);     }     get_text_and_rect(renderer, 0, 0, "hello", font, &texture1, &rect1);     get_text_and_rect(renderer, 0, rect1.y + rect1.h, "world", font, &texture2, &rect2);      quit = 0;     while (!quit) {         while (SDL_PollEvent(&event) == 1) {             if (event.type == SDL_QUIT) {                 quit = 1;             }         }         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);         SDL_RenderClear(renderer);          /* Use TTF textures. */         SDL_RenderCopy(renderer, texture1, NULL, &rect1);         SDL_RenderCopy(renderer, texture2, NULL, &rect2);          SDL_RenderPresent(renderer);     }      /* Deinit TTF. */     SDL_DestroyTexture(texture1);     SDL_DestroyTexture(texture2);     TTF_Quit();      SDL_DestroyRenderer(renderer);     SDL_DestroyWindow(window);     SDL_Quit();     return EXIT_SUCCESS; } 

GitHub upstream.

Tested in Ubuntu 16.04, SDL 2.0.4.