1 /*
2   showfont:  An example of using the SDL_ttf library with 2D graphics.
3   Copyright (C) 2001-2019 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 /* A simple program to test the text rendering feature of the TTF library */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #include "SDL.h"
29 #include "SDL_ttf.h"
30 
31 #define DEFAULT_PTSIZE  18
32 #define DEFAULT_TEXT    "The quick brown fox jumped over the lazy dog"
33 #define WIDTH   640
34 #define HEIGHT  480
35 
36 #define TTF_SHOWFONT_USAGE \
37 "Usage: %s [-solid] [-shaded] [-blended] [-utf8|-unicode] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-fgcol r,g,b,a] [-bgcol r,g,b,a] <font>.ttf [ptsize] [text]\n"
38 
39 typedef enum
40 {
41     TextRenderSolid,
42     TextRenderShaded,
43     TextRenderBlended
44 } TextRenderMethod;
45 
46 typedef struct {
47     SDL_Texture *caption;
48     SDL_Rect captionRect;
49     SDL_Texture *message;
50     SDL_Rect messageRect;
51 } Scene;
52 
draw_scene(SDL_Renderer * renderer,Scene * scene)53 static void draw_scene(SDL_Renderer *renderer, Scene *scene)
54 {
55     /* Clear the background to background color */
56     SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
57     SDL_RenderClear(renderer);
58 
59     SDL_RenderCopy(renderer, scene->caption, NULL, &scene->captionRect);
60     SDL_RenderCopy(renderer, scene->message, NULL, &scene->messageRect);
61     SDL_RenderPresent(renderer);
62 }
63 
cleanup(int exitcode)64 static void cleanup(int exitcode)
65 {
66     TTF_Quit();
67     SDL_Quit();
68     exit(exitcode);
69 }
70 
main(int argc,char * argv[])71 int main(int argc, char *argv[])
72 {
73     char *argv0 = argv[0];
74     SDL_Window *window;
75     SDL_Renderer *renderer;
76     TTF_Font *font;
77     SDL_Surface *text = NULL;
78     Scene scene;
79     int ptsize;
80     int i, done;
81     SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
82     SDL_Color black = { 0x00, 0x00, 0x00, 0 };
83     SDL_Color *forecol;
84     SDL_Color *backcol;
85     SDL_Event event;
86     TextRenderMethod rendermethod;
87     int renderstyle;
88     int outline;
89     int hinting;
90     int kerning;
91     int dump;
92     enum {
93         RENDER_LATIN1,
94         RENDER_UTF8,
95         RENDER_UNICODE
96     } rendertype;
97     char *message, string[128];
98 
99     /* Look for special execution mode */
100     dump = 0;
101     /* Look for special rendering types */
102     rendermethod = TextRenderShaded;
103     renderstyle = TTF_STYLE_NORMAL;
104     rendertype = RENDER_LATIN1;
105     outline = 0;
106     hinting = TTF_HINTING_NORMAL;
107     kerning = 1;
108     /* Default is black and white */
109     forecol = &black;
110     backcol = &white;
111     for (i=1; argv[i] && argv[i][0] == '-'; ++i) {
112         if (strcmp(argv[i], "-solid") == 0) {
113             rendermethod = TextRenderSolid;
114         } else
115         if (strcmp(argv[i], "-shaded") == 0) {
116             rendermethod = TextRenderShaded;
117         } else
118         if (strcmp(argv[i], "-blended") == 0) {
119             rendermethod = TextRenderBlended;
120         } else
121         if (strcmp(argv[i], "-utf8") == 0) {
122             rendertype = RENDER_UTF8;
123         } else
124         if (strcmp(argv[i], "-unicode") == 0) {
125             rendertype = RENDER_UNICODE;
126         } else
127         if (strcmp(argv[i], "-b") == 0) {
128             renderstyle |= TTF_STYLE_BOLD;
129         } else
130         if (strcmp(argv[i], "-i") == 0) {
131             renderstyle |= TTF_STYLE_ITALIC;
132         } else
133         if (strcmp(argv[i], "-u") == 0) {
134             renderstyle |= TTF_STYLE_UNDERLINE;
135         } else
136         if (strcmp(argv[i], "-s") == 0) {
137             renderstyle |= TTF_STYLE_STRIKETHROUGH;
138         } else
139         if (strcmp(argv[i], "-outline") == 0) {
140             if (sscanf (argv[++i], "%d", &outline) != 1) {
141                 fprintf(stderr, TTF_SHOWFONT_USAGE, argv0);
142                 return(1);
143             }
144         } else
145         if (strcmp(argv[i], "-hintlight") == 0) {
146             hinting = TTF_HINTING_LIGHT;
147         } else
148         if (strcmp(argv[i], "-hintmono") == 0) {
149             hinting = TTF_HINTING_MONO;
150         } else
151         if (strcmp(argv[i], "-hintnone") == 0) {
152             hinting = TTF_HINTING_NONE;
153         } else
154         if (strcmp(argv[i], "-nokerning") == 0) {
155             kerning = 0;
156         } else
157         if (strcmp(argv[i], "-dump") == 0) {
158             dump = 1;
159         } else
160         if (strcmp(argv[i], "-fgcol") == 0) {
161             int r, g, b, a = 0xFF;
162             if (sscanf (argv[++i], "%d,%d,%d,%d", &r, &g, &b, &a) < 3) {
163                 fprintf(stderr, TTF_SHOWFONT_USAGE, argv0);
164                 return(1);
165             }
166             forecol->r = (Uint8)r;
167             forecol->g = (Uint8)g;
168             forecol->b = (Uint8)b;
169             forecol->a = (Uint8)a;
170         } else
171         if (strcmp(argv[i], "-bgcol") == 0) {
172             int r, g, b, a = 0xFF;
173             if (sscanf (argv[++i], "%d,%d,%d,%d", &r, &g, &b, &a) < 3) {
174                 fprintf(stderr, TTF_SHOWFONT_USAGE, argv0);
175                 return(1);
176             }
177             backcol->r = (Uint8)r;
178             backcol->g = (Uint8)g;
179             backcol->b = (Uint8)b;
180             backcol->a = (Uint8)a;
181         } else {
182             fprintf(stderr, TTF_SHOWFONT_USAGE, argv0);
183             return(1);
184         }
185     }
186     argv += i;
187     argc -= i;
188 
189     /* Check usage */
190     if (!argv[0]) {
191         fprintf(stderr, TTF_SHOWFONT_USAGE, argv0);
192         return(1);
193     }
194 
195     /* Initialize the TTF library */
196     if (TTF_Init() < 0) {
197         fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());
198         SDL_Quit();
199         return(2);
200     }
201 
202     /* Open the font file with the requested point size */
203     ptsize = 0;
204     if (argc > 1) {
205         ptsize = atoi(argv[1]);
206     }
207     if (ptsize == 0) {
208         i = 2;
209         ptsize = DEFAULT_PTSIZE;
210     } else {
211         i = 3;
212     }
213     font = TTF_OpenFont(argv[0], ptsize);
214     if (font == NULL) {
215         fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",
216                     ptsize, argv[0], SDL_GetError());
217         cleanup(2);
218     }
219     TTF_SetFontStyle(font, renderstyle);
220     TTF_SetFontOutline(font, outline);
221     TTF_SetFontKerning(font, kerning);
222     TTF_SetFontHinting(font, hinting);
223 
224     if(dump) {
225         for(i = 48; i < 123; i++) {
226             SDL_Surface* glyph = NULL;
227 
228             glyph = TTF_RenderGlyph_Shaded(font, i, *forecol, *backcol);
229 
230             if(glyph) {
231                 char outname[64];
232                 SDL_snprintf(outname, sizeof(outname), "glyph-%d.bmp", i);
233                 SDL_SaveBMP(glyph, outname);
234             }
235 
236         }
237         cleanup(0);
238     }
239 
240     /* Create a window */
241     if (SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &renderer) < 0) {
242         fprintf(stderr, "SDL_CreateWindowAndRenderer() failed: %s\n", SDL_GetError());
243         cleanup(2);
244     }
245 
246     /* Show which font file we're looking at */
247     SDL_snprintf(string, sizeof(string), "Font file: %s", argv[0]);  /* possible overflow */
248     switch (rendermethod) {
249     case TextRenderSolid:
250         text = TTF_RenderText_Solid(font, string, *forecol);
251         break;
252     case TextRenderShaded:
253         text = TTF_RenderText_Shaded(font, string, *forecol, *backcol);
254         break;
255     case TextRenderBlended:
256         text = TTF_RenderText_Blended(font, string, *forecol);
257         break;
258     }
259     if (text != NULL) {
260         scene.captionRect.x = 4;
261         scene.captionRect.y = 4;
262         scene.captionRect.w = text->w;
263         scene.captionRect.h = text->h;
264         scene.caption = SDL_CreateTextureFromSurface(renderer, text);
265         SDL_FreeSurface(text);
266     }
267 
268     /* Render and center the message */
269     if (argc > 2) {
270         message = argv[2];
271     } else {
272         message = DEFAULT_TEXT;
273     }
274     switch (rendertype) {
275         case RENDER_LATIN1:
276             switch (rendermethod) {
277             case TextRenderSolid:
278                 text = TTF_RenderText_Solid(font, message, *forecol);
279                 break;
280             case TextRenderShaded:
281                 text = TTF_RenderText_Shaded(font, message, *forecol, *backcol);
282                 break;
283             case TextRenderBlended:
284                 text = TTF_RenderText_Blended(font, message, *forecol);
285                 break;
286             }
287             break;
288 
289         case RENDER_UTF8:
290             switch (rendermethod) {
291             case TextRenderSolid:
292                 text = TTF_RenderUTF8_Solid(font, message, *forecol);
293                 break;
294             case TextRenderShaded:
295                 text = TTF_RenderUTF8_Shaded(font, message, *forecol, *backcol);
296                 break;
297             case TextRenderBlended:
298                 text = TTF_RenderUTF8_Blended(font, message, *forecol);
299                 break;
300             }
301             break;
302 
303         case RENDER_UNICODE:
304         {
305             Uint16 *unicode_text = SDL_iconv_utf8_ucs2(message);
306             switch (rendermethod) {
307             case TextRenderSolid:
308                 text = TTF_RenderUNICODE_Solid(font, unicode_text, *forecol);
309                 break;
310             case TextRenderShaded:
311                 text = TTF_RenderUNICODE_Shaded(font, unicode_text, *forecol, *backcol);
312                 break;
313             case TextRenderBlended:
314                 text = TTF_RenderUNICODE_Blended(font, unicode_text, *forecol);
315                 break;
316             }
317             SDL_free(unicode_text);
318         }
319         break;
320     }
321     if (text == NULL) {
322         fprintf(stderr, "Couldn't render text: %s\n", SDL_GetError());
323         TTF_CloseFont(font);
324         cleanup(2);
325     }
326     scene.messageRect.x = (WIDTH - text->w)/2;
327     scene.messageRect.y = (HEIGHT - text->h)/2;
328     scene.messageRect.w = text->w;
329     scene.messageRect.h = text->h;
330     scene.message = SDL_CreateTextureFromSurface(renderer, text);
331     printf("Font is generally %d big, and string is %d big\n",
332                         TTF_FontHeight(font), text->h);
333 
334     draw_scene(renderer, &scene);
335 
336     /* Wait for a keystroke, and blit text on mouse press */
337     done = 0;
338     while (!done) {
339         if (SDL_WaitEvent(&event) < 0) {
340             fprintf(stderr, "SDL_PullEvent() error: %s\n",
341                                 SDL_GetError());
342             done = 1;
343             continue;
344         }
345         switch (event.type) {
346             case SDL_MOUSEBUTTONDOWN:
347                 scene.messageRect.x = event.button.x - text->w/2;
348                 scene.messageRect.y = event.button.y - text->h/2;
349                 scene.messageRect.w = text->w;
350                 scene.messageRect.h = text->h;
351                 draw_scene(renderer, &scene);
352                 break;
353 
354             case SDL_KEYDOWN:
355             case SDL_QUIT:
356                 done = 1;
357                 break;
358             default:
359                 break;
360         }
361     }
362     SDL_FreeSurface(text);
363     TTF_CloseFont(font);
364     SDL_DestroyTexture(scene.caption);
365     SDL_DestroyTexture(scene.message);
366     cleanup(0);
367 
368     /* Not reached, but fixes compiler warnings */
369     return 0;
370 }
371 
372 /* vi: set ts=4 sw=4 expandtab: */
373