]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/font.cpp
clean up fullscreen code; fill/plug in gr_toggle_fullscreen
[taylor/freespace2.git] / src / graphics / font.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Graphics/Font.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * source file for font stuff
16  *
17  * $Log$
18  * Revision 1.10  2004/06/11 00:55:25  tigital
19  * byte-swapping changes for bigendian systems
20  *
21  * Revision 1.9  2003/08/03 15:51:58  taylor
22  * fix issue with FS1 fonts
23  *
24  * Revision 1.8  2003/06/19 11:51:41  taylor
25  * adjustments to memory leak fixes
26  *
27  * Revision 1.7  2003/06/11 18:30:32  taylor
28  * plug memory leaks
29  *
30  * Revision 1.6  2003/05/25 02:30:42  taylor
31  * Freespace 1 support
32  *
33  * Revision 1.5  2002/07/13 06:46:47  theoddone33
34  * Warning cleanups
35  *
36  * Revision 1.4  2002/06/09 04:41:17  relnev
37  * added copyright header
38  *
39  * Revision 1.3  2002/06/05 08:05:29  relnev
40  * stub/warning removal.
41  *
42  * reworked the sound code.
43  *
44  * Revision 1.2  2002/05/07 03:16:45  theoddone33
45  * The Great Newline Fix
46  *
47  * Revision 1.1.1.1  2002/05/03 03:28:09  root
48  * Initial import.
49  *
50  * 
51  * 9     7/09/99 10:32p Dave
52  * Command brief and red alert screens.
53  * 
54  * 8     12/14/98 9:21a Dan
55  * Put gr8_string() back in
56  * 
57  * 7     12/02/98 5:47p Dave
58  * Put in interface xstr code. Converted barracks screen to new format.
59  * 
60  * 6     11/30/98 1:07p Dave
61  * 16 bit conversion, first run.
62  * 
63  * 5     11/05/98 4:18p Dave
64  * First run nebula support. Beefed up localization a bit. Removed all
65  * conditional compiles for foreign versions. Modified mission file
66  * format.
67  * 
68  * 4     10/13/98 9:28a Dave
69  * Started neatening up freespace.h. Many variables renamed and
70  * reorganized. Added AlphaColors.[h,cpp]
71  * 
72  * 3     10/13/98 9:19a Andsager
73  * Add localization support to cfile.  Optional parameter with cfopen that
74  * looks for localized files.
75  * 
76  * 2     10/07/98 10:52a Dave
77  * Initial checkin.
78  * 
79  * 1     10/07/98 10:49a Dave
80  * 
81  * 49    7/02/98 3:41p Allender
82  * fix nasty assembler bug where pushf wasn't accompanied by corresponding
83  * pop in certain clipping conditions -- manifested only in software and
84  * usually on the PXO chat screen.
85  * 
86  * 48    6/18/98 10:10a Allender
87  * fixed compiler warnings
88  * 
89  * 47    6/13/98 10:48p Lawrance
90  * Changed code to utilize proper fixed-space 1 character.
91  * 
92  * 46    6/13/98 3:18p Hoffoss
93  * NOX()ed out a bunch of strings that shouldn't be translated.
94  * 
95  * 45    5/25/98 10:32a John
96  * Took out redundant code for font bitmap offsets that converted to a
97  * float, then later on converted back to an integer.  Quite unnecessary.
98  * 
99  * 44    5/12/98 11:45a John
100  * Fixed a bug with the length of string being passed to
101  * gr_get_string_size.  The bug occurred if you had two or more'\n'''s in
102  * a row.
103  * 
104  * 43    3/10/98 4:18p John
105  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
106  * & Glide have popups and print screen.  Took out all >8bpp software
107  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
108  * support Fred.  Made zbuffering key off of functions rather than one
109  * global variable.
110  * 
111  * 42    3/09/98 6:06p John
112  * Restructured font stuff to avoid duplicate code in Direct3D and Glide.
113  * Restructured Glide to avoid redundent state setting.
114  * 
115  * 41    3/02/98 10:33a John
116  * Fixed bug where Y clip was using X value.
117  * 
118  * 40    2/19/98 9:04a John
119  * Fixed fonts with glide
120  * 
121  * 39    2/17/98 7:27p John
122  * Got fonts and texturing working in Direct3D
123  * 
124  * 38    2/05/98 9:21p John
125  * Some new Direct3D code.   Added code to monitor a ton of stuff in the
126  * game.
127  * 
128  * 37    1/20/98 2:25p Hoffoss
129  * Fixed bug where timestamp printing incorrectly increments an hour at 6
130  * minutes.
131  * 
132  * 36    1/19/98 6:15p John
133  * Fixed all my Optimized Build compiler warnings
134  * 
135  * 35    11/30/97 12:18p John
136  * added more 24 & 32-bpp primitives
137  * 
138  * 34    11/29/97 2:24p John
139  * fixed warnings
140  * 
141  * 33    11/29/97 2:06p John
142  * added mode 16-bpp support
143  * 
144  * 32    11/10/97 2:35p Hoffoss
145  * Changed timestamp printing code to utilize new fixed-space '1'
146  * character.
147  * 
148  * 31    11/06/97 5:42p Hoffoss
149  * Added support for fixed size timstamp rendering.
150  * 
151  * 30    11/03/97 10:08p Hoffoss
152  * Changed gr_get_string_size to utilize an optional length specifier, if
153  * you want to use non-null terminated strings.
154  * 
155  * 29    11/03/97 10:59a John
156  * added support for more than one font.
157  * 
158  * 28    10/24/97 12:13p Hoffoss
159  * Added gr_force_fit_string().
160  * 
161  * 27    10/19/97 12:55p John
162  * new code to lock / unlock surfaces for smooth directx integration.
163  * 
164  * 26    10/14/97 4:50p John
165  * more 16 bpp stuff.
166  * 
167  * 25    10/14/97 8:08a John
168  * added a bunch more 16 bit support
169  * 
170  * 24    10/09/97 5:23p John
171  * Added support for more 16-bpp functions
172  * 
173  * 23    9/23/97 10:53a Hoffoss
174  * Fixed bug in assumptions made half the time, and not the other half.
175  * 
176  * 22    9/09/97 3:39p Sandeep
177  * warning level 4 bugs
178  * 
179  * 21    8/19/97 5:46p Hoffoss
180  * Changed font used in Fred, and added display to show current eye
181  * position.
182  * 
183  * 20    6/25/97 2:35p John
184  * added some functions to use the windows font for Fred.
185  * 
186  * 19    6/17/97 12:03p John
187  * Moved color/alphacolor functions into their own module.  Made all color
188  * functions be part of the low-level graphics drivers, not just the
189  * grsoft.
190  * 
191  * 18    6/13/97 2:37p John
192  * fixed a string bug that printed weird characters sometimes.
193  * 
194  * 17    6/11/97 6:00p John
195  * sped up alpha matching a bit.
196  * 
197  * 16    6/11/97 5:49p John
198  * Changed palette code to only recalculate alphacolors when needed, not
199  * when palette changes.
200  * 
201  * 15    6/11/97 5:01p John
202  * Fixed mission log text.  Added fast clipped font drawer.  
203  * 
204  * 14    6/11/97 4:11p John
205  * addec function to get font height
206  * 
207  * 13    6/11/97 1:12p John
208  * Started fixing all the text colors in the game.
209  * 
210  * 12    6/09/97 9:24a John
211  * Changed the way fonts are set.
212  * 
213  * 11    6/06/97 4:41p John
214  * Fixed alpha colors to be smoothly integrated into gr_set_color_fast
215  * code.
216  * 
217  * 10    6/06/97 2:40p John
218  * Made all the radar dim in/out
219  * 
220  * 9     6/05/97 4:53p John
221  * First rev of new antialiased font stuff.
222  * 
223  * 8     5/12/97 12:27p John
224  * Restructured Graphics Library to add support for multiple renderers.
225  * 
226  * 7     4/24/97 11:28a Hoffoss
227  * added code to handle gr_String being called before gr_init_font ever
228  * was called
229  * 
230  * 6     4/23/97 5:26p John
231  * First rev of new debug console stuff.
232  * 
233  * 5     4/22/97 12:20p John
234  * fixed more resource leaks
235  * 
236  * 4     4/22/97 10:33a John
237  * fixed the 2d resource leaks that Alan found.
238  * 
239  * 3     4/04/97 11:21a Hoffoss
240  * JOHN: Fixed invalid param that caused a trap in BoundsChecker.    
241  * 
242  * 2     4/01/97 9:26a Allender
243  * added support for descent style fonts although they are not used in the
244  * game yet
245  * 
246  * 1     3/31/97 9:42a Allender
247  *
248  * $NoKeywords: $
249  */
250
251 #ifndef PLAT_UNIX
252 #include <windows.h>
253 #include <windowsx.h>
254 #endif
255 #include <stdio.h>
256 #include <stdarg.h>
257 #include "grinternal.h"
258 #include "2d.h"
259 #include "cfile.h"
260 #include "font.h"
261 #include "palman.h"
262 #include "key.h"
263 #include "bmpman.h"
264 #include "localize.h"
265
266 int Num_fonts = 0;
267 font Fonts[MAX_FONTS];
268 font *Current_font = NULL;
269
270
271 // crops a string if required to force it to not exceed max_width pixels when printed.
272 // Does this by dropping characters at the end of the string and adding '...' to the end.
273 //    str = string to crop.  Modifies this string directly
274 //    max_str = max characters allowed in str
275 //    max_width = number of pixels to limit string to (less than or equal to).
276 //    Returns: returns same pointer passed in for str.
277 char *gr_force_fit_string(char *str, int max_str, int max_width)
278 {
279         int w;
280
281         gr_get_string_size(&w, NULL, str);
282         if (w > max_width) {
283                 if ((int) strlen(str) > max_str - 3) {
284                         SDL_assert(max_str >= 3);
285                         str[max_str - 3] = 0;
286                 }
287
288                 strcpy(str + strlen(str) - 1, "...");
289                 gr_get_string_size(&w, NULL, str);
290                 while (w > max_width) {
291                         SDL_assert(strlen(str) >= 4);  // if this is hit, a bad max_width was passed in and the calling function needs fixing.
292                         strcpy(str + strlen(str) - 4, "...");
293                         gr_get_string_size(&w, NULL, str);
294                 }
295         }
296
297         return str;
298 }
299
300 //takes the character BEFORE being offset into current font
301 // Returns the letter code
302 int get_char_width(ubyte c1,ubyte c2,int *width,int *spacing)
303 {
304         int i, letter;
305
306         SDL_assert ( Current_font != NULL );
307         letter = c1-Current_font->first_ascii;
308
309         if (letter<0 || letter>=Current_font->num_chars) {                              //not in font, draw as space
310                 *width=0;
311                 *spacing = Current_font->w;
312                 return -1;
313         }
314
315         *width = Current_font->char_data[letter].byte_width;
316         *spacing = Current_font->char_data[letter].spacing;
317
318         i = Current_font->char_data[letter].kerning_entry;
319         if ( i > -1)  {
320                 if (!(c2==0 || c2=='\n')) {
321                         int letter2;
322
323                         letter2 = c2-Current_font->first_ascii;
324
325 #ifndef MAKE_FS1
326                         if ((letter2>=0) && (letter2<Current_font->num_chars) ) {                               //not in font, draw as space
327 #else
328                         // umm, not sure about this, issue with FS1 fonts that's no longer handled apparently
329                         if ((letter2>=0) && (letter2<Current_font->num_chars) && (Current_font->num_kern_pairs != 159) ) {      //not in font, draw as space
330 #endif
331                                 font_kernpair   *k = &Current_font->kern_data[i];
332                                 while( (k->c1 == letter) && (k->c2<letter2) && (i<Current_font->num_kern_pairs) )       {
333                                         i++;
334                                         k++;
335                                 }
336                                 if ( k->c2 == letter2 ) {
337                                         *spacing += k->offset;
338                                 }
339                         }
340                 }
341         }
342         return letter;
343 }
344
345 int get_centered_x(const char *s)
346 {
347         int w,w2,s2;
348
349         for (w=0;*s!=0 && *s!='\n';s++) {
350                 get_char_width(s[0],s[1],&w2,&s2);
351                 w += s2;
352         }
353
354         return ((gr_screen.clip_width - w) / 2);
355 }
356
357 // draws a character centered on x
358 void gr_char_centered(int x, int y, char chr)
359 {
360         char str[2];
361         int w, sc;
362
363         sc = Lcl_special_chars;
364         if (chr == '1')
365                 chr = (char)(sc + 1);
366
367         str[0] = chr;
368         str[1] = 0;
369         gr_get_string_size(&w, NULL, str);
370         gr_string(x - w / 2, y, str);
371 }
372
373 void gr_print_timestamp(int x, int y, int timestamp)
374 {
375         char h[2], m[3], s[3];
376         int w, c;
377
378         // format the time information into strings
379         sprintf(h, "%.1d", (timestamp / 3600000) % 10);
380         sprintf(m, "%.2d", (timestamp / 60000) % 60);
381         sprintf(s, "%.2d", (timestamp / 1000) % 60);
382
383         gr_get_string_size(&w, NULL, "0");
384         gr_get_string_size(&c, NULL, ":");
385
386         gr_string(x + w, y, ":");
387         gr_string(x + w * 3 + c, y, ":");
388
389         x += w / 2;
390         gr_char_centered(x, y, h[0]);
391         x += w + c;
392         gr_char_centered(x, y, m[0]);
393         x += w;
394         gr_char_centered(x, y, m[1]);
395         x += w + c;
396         gr_char_centered(x, y, s[0]);
397         x += w;
398         gr_char_centered(x, y, s[1]);
399 }
400
401 int gr_get_font_height()
402 {
403         if (Current_font)       {
404                 return Current_font->h;
405         } else {
406                 return 16;
407         }
408 }
409
410 void gr_get_string_size(int *w1, int *h1, const char *text, int len)
411 {
412         int longest_width;
413         int width,spacing;
414         int w, h;
415
416         if (!Current_font)      {
417                 if ( w1)
418                         *w1 = 16;
419
420                 if ( h1 )
421                         *h1 = 16;
422
423                 return;
424         }       
425
426         w = 0;
427         h = 0;
428         longest_width = 0;
429
430         if (text != NULL ) {
431                 h += Current_font->h;
432                 while (*text && (len>0) ) {
433
434                         // Process one or more 
435                         while ((*text == '\n') && (len>0) ) {
436                                 text++;
437                                 len--;
438                                 if ( *text )    {
439                                         h += Current_font->h;
440                                 }
441                                 w = 0;
442                         }
443
444                         if (*text == 0) {
445                                 break;
446                         }
447
448                         get_char_width(text[0], text[1], &width, &spacing);
449                         w += spacing;
450                         if (w > longest_width)
451                                 longest_width = w;
452
453                         text++;
454                         len--;
455                 }
456         }
457
458         if ( h1 )
459                 *h1 = h;
460
461         if ( w1 )
462                 *w1 = longest_width;
463 }
464
465
466 MONITOR( FontChars );   
467
468
469 #ifndef PLAT_UNIX
470 HFONT MyhFont = NULL;
471 extern HDC hDibDC;
472 #endif
473
474 void gr_string_win(int x, int y, const char *s)
475 {
476 #ifdef PLAT_UNIX
477 //      STUB_FUNCTION;
478 #else
479         char *ptr;
480         SIZE size;
481
482         if ( MyhFont==NULL )    {
483                 MyhFont = CreateFont(14, 0, 0, 0,                               // height,width,?,?
484                                 700,
485                                 FALSE,
486                                 FALSE,
487                                 FALSE,                                                                                  // strikeout?
488                                 ANSI_CHARSET,                                                                   // character set
489                                 OUT_DEVICE_PRECIS,
490                                 CLIP_DEFAULT_PRECIS,
491                                 DEFAULT_QUALITY,
492                                 DEFAULT_PITCH | FF_DONTCARE,
493 //                              NULL );
494 //                              "Times New Roman" );
495 //XSTR:OFF
496                                 "Ariel" );
497 //XSTR:ON
498         }
499
500         SelectObject( hDibDC, MyhFont );
501
502         if ( gr_screen.bits_per_pixel==8 )
503                 SetTextColor(hDibDC, PALETTEINDEX(gr_screen.current_color.raw8));
504         else
505                 SetTextColor(hDibDC, RGB(gr_screen.current_color.red,gr_screen.current_color.green,gr_screen.current_color.blue));
506
507         SetBkMode(hDibDC,TRANSPARENT);
508
509
510         HRGN hclip;
511         hclip = CreateRectRgn( gr_screen.offset_x, 
512                                                                   gr_screen.offset_y, 
513                                                                   gr_screen.offset_x+gr_screen.clip_width-1, 
514                                                                   gr_screen.offset_y+gr_screen.clip_height-1 );
515
516         SelectClipRgn(hDibDC, hclip );
517         x += gr_screen.offset_x;
518         y += gr_screen.offset_y;
519         //ptr = strchr(s,'\n);
520         while ((ptr = strchr(s, '\n'))!=NULL) {
521                 TextOut(hDibDC, x, y, s, ptr - s);
522                 GetTextExtentPoint32(hDibDC, s, ptr - s, &size);
523                 y += size.cy;
524                 s = ptr + 1;
525         }
526
527         TextOut(hDibDC, x, y, s, strlen(s));
528         SelectClipRgn(hDibDC, NULL);
529         DeleteObject(hclip);
530 #endif
531 }
532
533 void gr_get_string_size_win(int *w, int *h, const char *text)
534 {
535 #ifdef PLAT_UNIX
536 //      STUB_FUNCTION;
537 #else
538         char *ptr;
539         SIZE size;
540
541         ptr = strchr(text, '\n');
542
543         if (MyhFont==NULL)      {
544                 if (w) *w = 0;
545                 if (h) *h = 0;
546                 return;
547         }
548
549         SelectObject( hDibDC, MyhFont );
550
551         if (!ptr)       {
552                 GetTextExtentPoint32( hDibDC, text, strlen(text), &size);
553                 if (w) *w = size.cx;
554                 if (h) *h = size.cy;
555                 return;
556         }
557
558         GetTextExtentPoint32(hDibDC, text, ptr - text, &size);
559         gr_get_string_size_win(w, h, ptr+1);
560         if (w && (size.cx > *w) )
561                 *w = size.cx;
562
563         if (h)
564                 *h += size.cy;
565 #endif
566 }
567
568 char grx_printf_text[2048];     
569
570 void __cdecl gr_printf( int x, int y, const char * format, ... )
571 {
572         va_list args;
573
574         if ( !Current_font ) return;
575         
576         va_start(args, format);
577         vsprintf(grx_printf_text,format,args);
578         va_end(args);
579
580         gr_string(x,y,grx_printf_text);
581 }
582
583 void gr_font_close()
584 {
585         font *fnt;
586         int i;
587
588         fnt = Fonts;
589
590         for (i=0; i<Num_fonts; i++) {
591                 if (fnt->kern_data) {
592                         free(fnt->kern_data);
593                         fnt->kern_data = NULL;
594                 }
595
596                 if (fnt->char_data) {
597                         free(fnt->char_data);
598                         fnt->char_data = NULL;
599                 }
600
601                 if (fnt->pixel_data) {
602                         free(fnt->pixel_data);
603                         fnt->pixel_data = NULL;
604                 }
605
606                 if (fnt->bm_data) {
607                         free(fnt->bm_data);
608                         fnt->bm_data = NULL;
609                 }
610
611
612                 if (fnt->bm_u) {
613                         free(fnt->bm_u);
614                         fnt->bm_u = NULL;
615                 }
616
617                 if (fnt->bm_v) {
618                         free(fnt->bm_v);
619                         fnt->bm_v = NULL;
620                 }
621
622                 fnt++;
623         }
624 }
625
626 // Returns -1 if couldn't init font, otherwise returns the
627 // font id number.
628 int gr_create_font(const char * typeface)
629 {
630         CFILE *fp;
631         font *fnt;
632         int n, fontnum;
633
634         fnt = Fonts;
635         n = -1;
636         for (fontnum=0; fontnum<Num_fonts; fontnum++ )  {
637                 if (fnt->id != 0 )      {
638                         if ( !SDL_strncasecmp( fnt->filename, typeface, MAX_FILENAME_LEN ) )    {
639                                 return fontnum;
640                         }
641                 } else {
642                         if ( n < 0 )    {
643                                 n = fontnum;
644                         }                               
645                 }
646                 fnt++;
647         }
648
649         if ( fontnum==MAX_FONTS )       {
650                 Error( LOCATION, "Too many fonts!\nSee John, or change MAX_FONTS in Graphics\\Font.h\n" );
651         }
652
653         if ( fontnum == Num_fonts )     {
654                 Num_fonts++;
655         }
656         
657         bool localize = true;
658
659         fp = cfopen( typeface, "rb", CFILE_NORMAL, CF_TYPE_ANY, localize );
660         if ( fp == NULL ) return -1;
661
662         strncpy( fnt->filename, typeface, MAX_FILENAME_LEN );
663         cfread( &fnt->id, 4, 1, fp );
664         cfread( &fnt->version, sizeof(int), 1, fp );
665         cfread( &fnt->num_chars, sizeof(int), 1, fp );
666         cfread( &fnt->first_ascii, sizeof(int), 1, fp );
667         cfread( &fnt->w, sizeof(int), 1, fp );
668         cfread( &fnt->h, sizeof(int), 1, fp );
669         cfread( &fnt->num_kern_pairs, sizeof(int), 1, fp );
670         cfread( &fnt->kern_data_size, sizeof(int), 1, fp );
671         cfread( &fnt->char_data_size, sizeof(int), 1, fp );
672         cfread( &fnt->pixel_data_size, sizeof(int), 1, fp );
673
674     fnt->id = INTEL_SHORT( fnt->id );
675     fnt->version = INTEL_INT( fnt->version );
676     fnt->num_chars = INTEL_INT( fnt->num_chars );
677     fnt->first_ascii = INTEL_INT( fnt->first_ascii );
678     fnt->w = INTEL_INT( fnt->w );
679     fnt->h = INTEL_INT( fnt->h );
680     fnt->num_kern_pairs = INTEL_INT( fnt->num_kern_pairs );
681     fnt->kern_data_size = INTEL_INT( fnt->kern_data_size );
682     fnt->char_data_size = INTEL_INT( fnt->char_data_size );
683     fnt->pixel_data_size = INTEL_INT( fnt->pixel_data_size );
684
685         if ( fnt->kern_data_size )      {
686                 fnt->kern_data = (font_kernpair *)malloc( fnt->kern_data_size );
687                 SDL_assert(fnt->kern_data!=NULL);
688                 cfread( fnt->kern_data, fnt->kern_data_size, 1, fp );
689         } else {
690                 fnt->kern_data = NULL;
691         }
692         if ( fnt->char_data_size )      {
693                 fnt->char_data = (font_char *)malloc( fnt->char_data_size );
694                 SDL_assert( fnt->char_data != NULL );
695                 cfread( fnt->char_data, fnt->char_data_size, 1, fp );
696         for ( int i=0; i<fnt->num_chars; i++){
697             fnt->char_data[i].spacing = INTEL_INT( fnt->char_data[i].spacing );
698             fnt->char_data[i].byte_width = INTEL_INT( fnt->char_data[i].byte_width );
699             fnt->char_data[i].offset = INTEL_INT( fnt->char_data[i].offset );
700             fnt->char_data[i].kerning_entry = INTEL_SHORT( fnt->char_data[i].kerning_entry );
701             fnt->char_data[i].user_data = INTEL_SHORT( fnt->char_data[i].user_data );
702         }
703         } else {
704                 fnt->char_data = NULL;
705         }
706         if ( fnt->pixel_data_size )     {
707                 fnt->pixel_data = (ubyte *)malloc( fnt->pixel_data_size );
708                 SDL_assert(fnt->pixel_data!=NULL);
709                 cfread( fnt->pixel_data, fnt->pixel_data_size, 1, fp );
710         } else {
711                 fnt->pixel_data = NULL;
712         }
713         cfclose(fp);
714
715         // Create a bitmap for hardware cards.
716         // JAS:  Try to squeeze this into the smallest square power of two texture.
717         // This should probably be done at font generation time, not here.
718         int w, h;
719         if ( fnt->pixel_data_size < 64*64 )     {
720                 w = h = 64;
721         } else if ( fnt->pixel_data_size < 128*128 )    {
722                 w = h = 128;
723         } else {
724                 w = h = 256;
725         }
726
727         fnt->bm_w = w;
728         fnt->bm_h = h;
729         fnt->bm_data = (ubyte *)malloc(fnt->bm_w*fnt->bm_h);
730         fnt->bm_u = (int *)malloc(sizeof(int)*fnt->num_chars);
731         fnt->bm_v = (int *)malloc(sizeof(int)*fnt->num_chars);
732
733         memset(fnt->bm_data, 0, fnt->bm_w * fnt->bm_h);
734         memset(fnt->bm_u, 0, sizeof(int) * fnt->num_chars);
735         memset(fnt->bm_v, 0, sizeof(int) * fnt->num_chars);
736
737         int i,x,y;
738         x = y = 0;
739         for (i=0; i<fnt->num_chars; i++ )       {
740                 ubyte * fp;
741                 int x1, y1;
742                 fp = &fnt->pixel_data[fnt->char_data[i].offset];
743                 if ( x + fnt->char_data[i].byte_width >= fnt->bm_w )    {
744                         x = 0;
745                         y += fnt->h;
746                         if ( y+fnt->h > fnt->bm_h ) {
747                                 Error( LOCATION, "Font too big!\n" );
748                         }
749                 }
750                 fnt->bm_u[i] = x;
751                 fnt->bm_v[i] = y;
752
753                 for( y1=0; y1<fnt->h; y1++ )    {
754                         for (x1=0; x1<fnt->char_data[i].byte_width; x1++ )      {
755                                 uint c = *fp++;
756                                 if ( c > 14 ) c = 14;
757                                 fnt->bm_data[(x+x1)+(y+y1)*fnt->bm_w] = (unsigned char)(c);     
758                         }
759                 }
760                 x += fnt->char_data[i].byte_width;
761         }
762
763         fnt->bitmap_id = bm_create( 8, fnt->bm_w, fnt->bm_h, fnt->bm_data, BMP_AABITMAP );
764
765         return fontnum;
766 }
767
768 void gr_set_font(int fontnum)
769 {
770         if ( fontnum < 0 ) {
771                 Current_font = NULL;
772                 return;
773         }
774
775         if ( fontnum >= 0 ) {
776                 Current_font = &Fonts[fontnum];
777         }
778 }
779
780 void gr_font_init()
781 {
782         gr_init_font( NOX("font01.vf") );
783         gr_init_font( NOX("font02.vf") );
784 #ifndef MAKE_FS1
785         gr_init_font( NOX("font03.vf") );
786 #endif
787 }
788
789 // Returns -1 if couldn't init font, otherwise returns the
790 // font id number.
791 int gr_init_font(const char * typeface)
792 {
793         int Loaded_fontnum;
794
795         Loaded_fontnum = gr_create_font(typeface);
796
797         SDL_assert( Loaded_fontnum > -1 );
798
799         gr_set_font( Loaded_fontnum );
800
801         return Loaded_fontnum;
802 }
803