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