1 /*
2 showfont: An example of using the SDL_ttf library with 2D graphics.
3 Copyright (C) 2001-2012 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 #ifdef HAVE_ICONV
29 #include <iconv.h>
30 #endif
31
32 #include "SDL.h"
33 #include "SDL_ttf.h"
34
35 #define DEFAULT_PTSIZE 18
36 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog"
37 #define NUM_COLORS 256
38
39 static char *Usage =
40 "Usage: %s [-solid] [-utf8|-unicode] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-fgcol r,g,b] [-bgcol r,g,b] <font>.ttf [ptsize] [text]\n";
41
cleanup(int exitcode)42 static void cleanup(int exitcode)
43 {
44 TTF_Quit();
45 SDL_Quit();
46 exit(exitcode);
47 }
48
main(int argc,char * argv[])49 int main(int argc, char *argv[])
50 {
51 char *argv0 = argv[0];
52 SDL_Surface *screen;
53 TTF_Font *font;
54 SDL_Surface *text, *temp;
55 int ptsize;
56 int i, done;
57 int rdiff, gdiff, bdiff;
58 SDL_Color colors[NUM_COLORS];
59 SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
60 SDL_Color black = { 0x00, 0x00, 0x00, 0 };
61 SDL_Color *forecol;
62 SDL_Color *backcol;
63 SDL_Rect dstrect;
64 SDL_Event event;
65 int rendersolid;
66 int renderstyle;
67 int outline;
68 int hinting;
69 int kerning;
70 int dump;
71 enum {
72 RENDER_LATIN1,
73 RENDER_UTF8,
74 RENDER_UNICODE
75 } rendertype;
76 char *message, string[128];
77
78 /* Look for special execution mode */
79 dump = 0;
80 /* Look for special rendering types */
81 rendersolid = 0;
82 renderstyle = TTF_STYLE_NORMAL;
83 rendertype = RENDER_LATIN1;
84 outline = 0;
85 hinting = TTF_HINTING_NORMAL;
86 kerning = 1;
87 /* Default is black and white */
88 forecol = &black;
89 backcol = &white;
90 for ( i=1; argv[i] && argv[i][0] == '-'; ++i ) {
91 if ( strcmp(argv[i], "-solid") == 0 ) {
92 rendersolid = 1;
93 } else
94 if ( strcmp(argv[i], "-utf8") == 0 ) {
95 rendertype = RENDER_UTF8;
96 } else
97 if ( strcmp(argv[i], "-unicode") == 0 ) {
98 rendertype = RENDER_UNICODE;
99 } else
100 if ( strcmp(argv[i], "-b") == 0 ) {
101 renderstyle |= TTF_STYLE_BOLD;
102 } else
103 if ( strcmp(argv[i], "-i") == 0 ) {
104 renderstyle |= TTF_STYLE_ITALIC;
105 } else
106 if ( strcmp(argv[i], "-u") == 0 ) {
107 renderstyle |= TTF_STYLE_UNDERLINE;
108 } else
109 if ( strcmp(argv[i], "-s") == 0 ) {
110 renderstyle |= TTF_STYLE_STRIKETHROUGH;
111 } else
112 if ( strcmp(argv[i], "-outline") == 0 ) {
113 if ( sscanf (argv[++i], "%d", &outline) != 1 ) {
114 fprintf(stderr, Usage, argv0);
115 return(1);
116 }
117 } else
118 if ( strcmp(argv[i], "-hintlight") == 0 ) {
119 hinting = TTF_HINTING_LIGHT;
120 } else
121 if ( strcmp(argv[i], "-hintmono") == 0 ) {
122 hinting = TTF_HINTING_MONO;
123 } else
124 if ( strcmp(argv[i], "-hintnone") == 0 ) {
125 hinting = TTF_HINTING_NONE;
126 } else
127 if ( strcmp(argv[i], "-nokerning") == 0 ) {
128 kerning = 0;
129 } else
130 if ( strcmp(argv[i], "-dump") == 0 ) {
131 dump = 1;
132 } else
133 if ( strcmp(argv[i], "-fgcol") == 0 ) {
134 int r, g, b;
135 if ( sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3 ) {
136 fprintf(stderr, Usage, argv0);
137 return(1);
138 }
139 forecol->r = (Uint8)r;
140 forecol->g = (Uint8)g;
141 forecol->b = (Uint8)b;
142 } else
143 if ( strcmp(argv[i], "-bgcol") == 0 ) {
144 int r, g, b;
145 if ( sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3 ) {
146 fprintf(stderr, Usage, argv0);
147 return(1);
148 }
149 backcol->r = (Uint8)r;
150 backcol->g = (Uint8)g;
151 backcol->b = (Uint8)b;
152 } else {
153 fprintf(stderr, Usage, argv0);
154 return(1);
155 }
156 }
157 argv += i;
158 argc -= i;
159
160 /* Check usage */
161 if ( ! argv[0] ) {
162 fprintf(stderr, Usage, argv0);
163 return(1);
164 }
165
166 /* Initialize SDL */
167 if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
168 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
169 return(2);
170 }
171
172 /* Initialize the TTF library */
173 if ( TTF_Init() < 0 ) {
174 fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());
175 SDL_Quit();
176 return(2);
177 }
178
179 /* Open the font file with the requested point size */
180 ptsize = 0;
181 if ( argc > 1 ) {
182 ptsize = atoi(argv[1]);
183 }
184 if ( ptsize == 0 ) {
185 i = 2;
186 ptsize = DEFAULT_PTSIZE;
187 } else {
188 i = 3;
189 }
190 font = TTF_OpenFont(argv[0], ptsize);
191 if ( font == NULL ) {
192 fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",
193 ptsize, argv[0], SDL_GetError());
194 cleanup(2);
195 }
196 TTF_SetFontStyle(font, renderstyle);
197 TTF_SetFontOutline(font, outline);
198 TTF_SetFontKerning(font, kerning);
199 TTF_SetFontHinting(font, hinting);
200
201 if( dump ) {
202 for( i = 48; i < 123; i++ ) {
203 SDL_Surface* glyph = NULL;
204
205 glyph = TTF_RenderGlyph_Shaded( font, i, *forecol, *backcol );
206
207 if( glyph ) {
208 char outname[64];
209 sprintf( outname, "glyph-%d.bmp", i );
210 SDL_SaveBMP( glyph, outname );
211 }
212
213 }
214 cleanup(0);
215 }
216
217 /* Set a 640x480x8 video mode */
218 screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
219 if ( screen == NULL ) {
220 fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
221 SDL_GetError());
222 cleanup(2);
223 }
224
225 /* Set a palette that is good for the foreground colored text */
226 rdiff = backcol->r - forecol->r;
227 gdiff = backcol->g - forecol->g;
228 bdiff = backcol->b - forecol->b;
229 for ( i=0; i<NUM_COLORS; ++i ) {
230 colors[i].r = forecol->r + (i*rdiff)/4;
231 colors[i].g = forecol->g + (i*gdiff)/4;
232 colors[i].b = forecol->b + (i*bdiff)/4;
233 }
234 SDL_SetColors(screen, colors, 0, NUM_COLORS);
235
236 /* Clear the background to background color */
237 SDL_FillRect(screen, NULL,
238 SDL_MapRGB(screen->format, backcol->r, backcol->g, backcol->b));
239 SDL_UpdateRect(screen, 0, 0, 0, 0);
240
241 /* Show which font file we're looking at */
242 sprintf(string, "Font file: %s", argv[0]); /* possible overflow */
243 if ( rendersolid ) {
244 text = TTF_RenderText_Solid(font, string, *forecol);
245 } else {
246 text = TTF_RenderText_Shaded(font, string, *forecol, *backcol);
247 }
248 if ( text != NULL ) {
249 dstrect.x = 4;
250 dstrect.y = 4;
251 dstrect.w = text->w;
252 dstrect.h = text->h;
253 SDL_BlitSurface(text, NULL, screen, &dstrect);
254 SDL_FreeSurface(text);
255 }
256
257 /* Render and center the message */
258 if ( argc > 2 ) {
259 message = argv[2];
260 } else {
261 message = DEFAULT_TEXT;
262 }
263 switch (rendertype) {
264 case RENDER_LATIN1:
265 if ( rendersolid ) {
266 text = TTF_RenderText_Solid(font,message,*forecol);
267 } else {
268 text = TTF_RenderText_Shaded(font,message,*forecol,*backcol);
269 }
270 break;
271
272 case RENDER_UTF8:
273 if ( rendersolid ) {
274 text = TTF_RenderUTF8_Solid(font,message,*forecol);
275 } else {
276 text = TTF_RenderUTF8_Shaded(font,message,*forecol,*backcol);
277 }
278 break;
279
280 case RENDER_UNICODE:
281 {
282 Uint16 unicode_text[BUFSIZ];
283 int index;
284 #ifdef HAVE_ICONV
285 /* Use iconv to convert the message into utf-16.
286 * "char" and "" are aliases for the local 8-bit encoding */
287 iconv_t cd;
288 /*ICONV_CONST*/ char *from_str = message;
289 char *to_str = (char*)unicode_text;
290 size_t from_sz = strlen(message) + 1;
291 size_t to_sz = sizeof(unicode_text);
292 size_t res;
293 int i;
294
295 if ((cd = iconv_open("UTF-16", "char")) == (iconv_t)-1
296 && (cd = iconv_open("UTF-16", "")) == (iconv_t)-1) {
297 perror("Couldn't open iconv");
298 exit(1);
299 }
300
301 res = iconv(cd, &from_str, &from_sz, &to_str, &to_sz);
302 if (res == -1) {
303 perror("Couldn't use iconv");
304 exit(1);
305 }
306
307 iconv_close(cd);
308 #else
309 /* Convert the message from ascii into utf-16.
310 * This is unreliable as a test because it always
311 * gives the local ordering. */
312 for (index = 0; message[index]; index++) {
313 unicode_text[index] = message[index];
314 }
315 unicode_text[index] = 0;
316 #endif
317
318 if ( rendersolid ) {
319 text = TTF_RenderUNICODE_Solid(font,
320 unicode_text, *forecol);
321 } else {
322 text = TTF_RenderUNICODE_Shaded(font,
323 unicode_text, *forecol, *backcol);
324 }
325 }
326 break;
327 default:
328 text = NULL; /* This shouldn't happen */
329 break;
330 }
331 if ( text == NULL ) {
332 fprintf(stderr, "Couldn't render text: %s\n", SDL_GetError());
333 TTF_CloseFont(font);
334 cleanup(2);
335 }
336 dstrect.x = (screen->w - text->w)/2;
337 dstrect.y = (screen->h - text->h)/2;
338 dstrect.w = text->w;
339 dstrect.h = text->h;
340 printf("Font is generally %d big, and string is %hd big\n",
341 TTF_FontHeight(font), text->h);
342
343 /* Blit the text surface */
344 if ( SDL_BlitSurface(text, NULL, screen, &dstrect) < 0 ) {
345 fprintf(stderr, "Couldn't blit text to display: %s\n",
346 SDL_GetError());
347 TTF_CloseFont(font);
348 cleanup(2);
349 }
350 SDL_UpdateRect(screen, 0, 0, 0, 0);
351
352 /* Set the text colorkey and convert to display format */
353 if ( SDL_SetColorKey(text, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0) < 0 ) {
354 fprintf(stderr, "Warning: Couldn't set text colorkey: %s\n",
355 SDL_GetError());
356 }
357 temp = SDL_DisplayFormat(text);
358 if ( temp != NULL ) {
359 SDL_FreeSurface(text);
360 text = temp;
361 }
362
363 /* Wait for a keystroke, and blit text on mouse press */
364 done = 0;
365 while ( ! done ) {
366 if ( SDL_WaitEvent(&event) < 0 ) {
367 fprintf(stderr, "SDL_PullEvent() error: %s\n",
368 SDL_GetError());
369 done = 1;
370 continue;
371 }
372 switch (event.type) {
373 case SDL_MOUSEBUTTONDOWN:
374 dstrect.x = event.button.x - text->w/2;
375 dstrect.y = event.button.y - text->h/2;
376 dstrect.w = text->w;
377 dstrect.h = text->h;
378 if ( SDL_BlitSurface(text, NULL, screen,
379 &dstrect) == 0 ) {
380 SDL_UpdateRects(screen, 1, &dstrect);
381 } else {
382 fprintf(stderr,
383 "Couldn't blit text to display: %s\n",
384 SDL_GetError());
385 }
386 break;
387
388 case SDL_KEYDOWN:
389 case SDL_QUIT:
390 done = 1;
391 break;
392 default:
393 break;
394 }
395 }
396 SDL_FreeSurface(text);
397 TTF_CloseFont(font);
398 cleanup(0);
399
400 /* Not reached, but fixes compiler warnings */
401 return 0;
402 }
403