1 /*
2     showfont:  An example of using the SDL_ttf library with 2D graphics.
3     Copyright (C) 1997-2004 Sam Lantinga
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14 
15     You should have received a copy of the GNU Library General Public
16     License along with this library; if not, write to the Free
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 
23 /* $Id: showfont.c 2429 2006-05-14 21:03:44Z slouken $ */
24 
25 /* A simple program to test the text rendering feature of the TTF library */
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #ifdef HAVE_ICONV
32 #include <iconv.h>
33 #endif
34 
35 #include "SDL.h"
36 #include "SDL_ttf.h"
37 
38 #define DEFAULT_PTSIZE 18
39 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog"
40 #define NUM_COLORS      256
41 
42 static char *Usage =
43 "Usage: %s [-solid] [-utf8|-unicode] [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] <font>.ttf [ptsize] [text]\n";
44 
cleanup(int exitcode)45 static void cleanup(int exitcode)
46 {
47  TTF_Quit();
48  SDL_Quit();
49  exit(exitcode);
50 }
51 
main(int argc,char * argv[])52 int main(int argc, char *argv[])
53 {
54  char *argv0 = argv[0];
55  SDL_Surface *screen;
56  TTF_Font *font;
57  SDL_Surface *text, *temp;
58  int ptsize;
59  int i, done;
60  int rdiff, gdiff, bdiff;
61  SDL_Color colors[NUM_COLORS];
62  SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
63  SDL_Color black = { 0x00, 0x00, 0x00, 0 };
64  SDL_Color *forecol;
65  SDL_Color *backcol;
66  SDL_Rect dstrect;
67  SDL_Event event;
68  int rendersolid;
69  int renderstyle;
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  /* Default is black and white */
85  forecol = &black;
86  backcol = &white;
87  for ( i=1; argv[i] && argv[i][0] == '-'; ++i ) {
88    if ( strcmp(argv[i], "-solid") == 0 ) {
89      rendersolid = 1;
90    } else
91    if ( strcmp(argv[i], "-utf8") == 0 ) {
92      rendertype = RENDER_UTF8;
93    } else
94    if ( strcmp(argv[i], "-unicode") == 0 ) {
95      rendertype = RENDER_UNICODE;
96    } else
97    if ( strcmp(argv[i], "-b") == 0 ) {
98      renderstyle |= TTF_STYLE_BOLD;
99    } else
100    if ( strcmp(argv[i], "-i") == 0 ) {
101      renderstyle |= TTF_STYLE_ITALIC;
102    } else
103    if ( strcmp(argv[i], "-u") == 0 ) {
104      renderstyle |= TTF_STYLE_UNDERLINE;
105    } else
106    if ( strcmp(argv[i], "-dump") == 0 ) {
107      dump = 1;
108    } else
109    if ( strcmp(argv[i], "-fgcol") == 0 ) {
110      int r, g, b;
111      if ( sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3 ) {
112        fprintf(stderr, Usage, argv0);
113        return(1);
114      }
115      forecol->r = (Uint8)r;
116      forecol->g = (Uint8)g;
117      forecol->b = (Uint8)b;
118    } else
119    if ( strcmp(argv[i], "-bgcol") == 0 ) {
120      int r, g, b;
121      if ( sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3 ) {
122        fprintf(stderr, Usage, argv0);
123        return(1);
124      }
125      backcol->r = (Uint8)r;
126      backcol->g = (Uint8)g;
127      backcol->b = (Uint8)b;
128    } else {
129      fprintf(stderr, Usage, argv0);
130      return(1);
131    }
132  }
133  argv += i;
134  argc -= i;
135 
136  /* Check usage */
137  if ( ! argv[0] ) {
138    fprintf(stderr, Usage, argv0);
139    return(1);
140  }
141 
142  /* Initialize SDL */
143  if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
144    fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
145    return(2);
146  }
147 
148  /* Initialize the TTF library */
149  if ( TTF_Init() < 0 ) {
150    fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());
151    SDL_Quit();
152    return(2);
153  }
154 
155  /* Open the font file with the requested point size */
156  ptsize = 0;
157  if ( argc > 1 ) {
158    ptsize = atoi(argv[1]);
159  }
160  if ( ptsize == 0 ) {
161    i = 2;
162    ptsize = DEFAULT_PTSIZE;
163  } else {
164    i = 3;
165  }
166  font = TTF_OpenFont(argv[0], ptsize);
167  if ( font == NULL ) {
168    fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",
169          ptsize, argv[0], SDL_GetError());
170    cleanup(2);
171  }
172  TTF_SetFontStyle(font, renderstyle);
173 
174  if( dump ) {
175    for( i = 48; i < 123; i++ ) {
176      SDL_Surface* glyph = NULL;
177 
178      glyph = TTF_RenderGlyph_Shaded( font, i, *forecol, *backcol );
179 
180      if( glyph ) {
181        char outname[64];
182        sprintf( outname, "glyph-%d.bmp", i );
183        SDL_SaveBMP( glyph, outname );
184      }
185 
186    }
187    cleanup(0);
188  }
189 
190  /* Set a 640x480x8 video mode */
191  screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
192  if ( screen == NULL ) {
193    fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
194              SDL_GetError());
195    cleanup(2);
196  }
197 
198  /* Set a palette that is good for the foreground colored text */
199  rdiff = backcol->r - forecol->r;
200  gdiff = backcol->g - forecol->g;
201  bdiff = backcol->b - forecol->b;
202  for ( i=0; i<NUM_COLORS; ++i ) {
203    colors[i].r = forecol->r + (i*rdiff)/4;
204    colors[i].g = forecol->g + (i*gdiff)/4;
205    colors[i].b = forecol->b + (i*bdiff)/4;
206  }
207  SDL_SetColors(screen, colors, 0, NUM_COLORS);
208 
209  /* Clear the background to background color */
210  SDL_FillRect(screen, NULL,
211      SDL_MapRGB(screen->format, backcol->r, backcol->g, backcol->b));
212  SDL_UpdateRect(screen, 0, 0, 0, 0);
213 
214  /* Show which font file we're looking at */
215  sprintf(string, "Font file: %s", argv[0]);  /* possible overflow */
216  if ( rendersolid ) {
217    text = TTF_RenderText_Solid(font, string, *forecol);
218  } else {
219    text = TTF_RenderText_Shaded(font, string, *forecol, *backcol);
220  }
221  if ( text != NULL ) {
222    dstrect.x = 4;
223    dstrect.y = 4;
224    dstrect.w = text->w;
225    dstrect.h = text->h;
226    SDL_BlitSurface(text, NULL, screen, &dstrect);
227    SDL_FreeSurface(text);
228  }
229 
230  /* Render and center the message */
231  if ( argc > 2 ) {
232    message = argv[2];
233  } else {
234    message = DEFAULT_TEXT;
235  }
236  switch (rendertype) {
237      case RENDER_LATIN1:
238    if ( rendersolid ) {
239      text = TTF_RenderText_Solid(font,message,*forecol);
240    } else {
241      text = TTF_RenderText_Shaded(font,message,*forecol,*backcol);
242    }
243    break;
244 
245      case RENDER_UTF8:
246    if ( rendersolid ) {
247      text = TTF_RenderUTF8_Solid(font,message,*forecol);
248    } else {
249      text = TTF_RenderUTF8_Shaded(font,message,*forecol,*backcol);
250    }
251    break;
252 
253      case RENDER_UNICODE:
254    {
255      Uint16 unicode_text[BUFSIZ];
256      int index;
257 #ifdef HAVE_ICONV
258      /* Use iconv to convert the message into utf-16.
259       * "char" and "" are aliases for the local 8-bit encoding */
260      iconv_t cd;
261      /*ICONV_CONST*/ char *from_str = message;
262      char *to_str = (char*)unicode_text;
263      size_t from_sz = strlen(message) + 1;
264      size_t to_sz = sizeof(unicode_text);
265      size_t res;
266      int i;
267 
268      if ((cd = iconv_open("UTF-16", "char")) == (iconv_t)-1
269          && (cd = iconv_open("UTF-16", "")) == (iconv_t)-1) {
270        perror("Couldn't open iconv");
271        exit(1);
272      }
273 
274      res = iconv(cd, &from_str, &from_sz, &to_str, &to_sz);
275      if (res == -1) {
276        perror("Couldn't use iconv");
277        exit(1);
278      }
279 
280      iconv_close(cd);
281 #else
282      /* Convert the message from ascii into utf-16.
283       * This is unreliable as a test because it always
284       * gives the local ordering. */
285      for (index = 0; message[index]; index++) {
286        unicode_text[index] = message[index];
287      }
288      unicode_text[index] = 0;
289 #endif
290 
291      if ( rendersolid ) {
292        text = TTF_RenderUNICODE_Solid(font,
293          unicode_text, *forecol);
294      } else {
295        text = TTF_RenderUNICODE_Shaded(font,
296          unicode_text, *forecol, *backcol);
297      }
298    }
299    break;
300      default:
301    text = NULL; /* This shouldn't happen */
302    break;
303  }
304  if ( text == NULL ) {
305    fprintf(stderr, "Couldn't render text: %s\n", SDL_GetError());
306    TTF_CloseFont(font);
307    cleanup(2);
308  }
309  dstrect.x = (screen->w - text->w)/2;
310  dstrect.y = (screen->h - text->h)/2;
311  dstrect.w = text->w;
312  dstrect.h = text->h;
313  printf("Font is generally %d big, and string is %hd big\n",
314            TTF_FontHeight(font), text->h);
315 
316  /* Blit the text surface */
317  if ( SDL_BlitSurface(text, NULL, screen, &dstrect) < 0 ) {
318    fprintf(stderr, "Couldn't blit text to display: %s\n",
319                SDL_GetError());
320    TTF_CloseFont(font);
321    cleanup(2);
322  }
323  SDL_UpdateRect(screen, 0, 0, 0, 0);
324 
325  /* Set the text colorkey and convert to display format */
326  if ( SDL_SetColorKey(text, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0) < 0 ) {
327    fprintf(stderr, "Warning: Couldn't set text colorkey: %s\n",
328                SDL_GetError());
329  }
330  temp = SDL_DisplayFormat(text);
331  if ( temp != NULL ) {
332    SDL_FreeSurface(text);
333    text = temp;
334  }
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        dstrect.x = event.button.x - text->w/2;
348        dstrect.y = event.button.y - text->h/2;
349        dstrect.w = text->w;
350        dstrect.h = text->h;
351        if ( SDL_BlitSurface(text, NULL, screen,
352              &dstrect) == 0 ) {
353          SDL_UpdateRects(screen, 1, &dstrect);
354        } else {
355          fprintf(stderr,
356          "Couldn't blit text to display: %s\n",
357                SDL_GetError());
358        }
359        break;
360 
361      case SDL_KEYDOWN:
362      case SDL_QUIT:
363        done = 1;
364        break;
365      default:
366        break;
367    }
368  }
369  SDL_FreeSurface(text);
370  TTF_CloseFont(font);
371  cleanup(0);
372 
373  /* Not reached, but fixes compiler warnings */
374  return 0;
375 }
376