I'm using an SDL_Window
and SDL_Renderer
.
Is it possible to use SDL_TTF
with SDL_Render/SDL_Window
? If so, how?
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.
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.
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.
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.
SDL_ttf minimal runnable example
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With