]> icculus.org git repositories - taylor/freespace2.git/blob - src/fonttool/fontkern.cpp
various files ported needed for fonttool. There is a bug where on exit it segfaults...
[taylor/freespace2.git] / src / fonttool / fontkern.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/Fonttool/FontKern.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Tool for interactively kerning fonts
16  *
17  * $Log$
18  * Revision 1.3  2003/01/30 20:03:48  relnev
19  * various files ported needed for fonttool.  There is a bug where on exit it segfaults in SDL_GL_SwapBuffers, I'm probably missing something (don't know what) but it works fine otherwise (Taylor Richards)
20  *
21  * Revision 1.2  2002/06/09 04:41:16  relnev
22  * added copyright header
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:08  root
25  * Initial import.
26  *
27  * 
28  * 6     5/19/99 4:07p Dave
29  * Moved versioning code into a nice isolated common place. Fixed up
30  * updating code on the pxo screen. Fixed several stub problems.
31  * 
32  * 5     12/18/98 1:14a Dave
33  * Rough 1024x768 support for Direct3D. Proper detection and usage through
34  * the launcher.
35  * 
36  * 4     12/02/98 9:58a Dave
37  * Got fonttool working under glide/direct3d.
38  * 
39  * 3     11/30/98 1:09p Dave
40  * 
41  * 2     10/24/98 5:15p Dave
42  * 
43  * 1     10/24/98 4:58p Dave
44  * 
45  * 14    5/06/98 5:30p John
46  * Removed unused cfilearchiver.  Removed/replaced some unused/little used
47  * graphics functions, namely gradient_h and _v and pixel_sp.   Put in new
48  * DirectX header files and libs that fixed the Direct3D alpha blending
49  * problems.
50  * 
51  * 13    4/13/98 10:11a John
52  * Made timer functions thread safe.  Made timer_init be called in all
53  * projects.
54  * 
55  * 12    3/10/98 4:18p John
56  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
57  * & Glide have popups and print screen.  Took out all >8bpp software
58  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
59  * support Fred.  Made zbuffering key off of functions rather than one
60  * global variable.
61  * 
62  * 11    3/05/98 11:15p Hoffoss
63  * Changed non-game key checking to use game_check_key() instead of
64  * game_poll().
65  * 
66  * 10    10/30/97 4:56p John
67  * Fixed up font stuff to build.  Fixed bug where it didn't show the last
68  * 3 characters in kerning table.
69  * 
70  * 9     9/03/97 4:32p John
71  * changed bmpman to only accept ani and pcx's.  made passing .pcx or .ani
72  * to bm_load functions not needed.   Made bmpman keep track of palettes
73  * for bitmaps not mapped into game palettes.
74  * 
75  * 8     6/06/97 6:47p John
76  * Fixed bug
77  * 
78  * 7     6/06/97 4:41p John
79  * Fixed alpha colors to be smoothly integrated into gr_set_color_fast
80  * code.
81  * 
82  * 6     6/06/97 11:10a John
83  * made scrolling kern pair box.
84  * 
85  * 5     6/06/97 9:21a John
86  * added some kerning pairs
87  * 
88  * 4     6/06/97 9:18a John
89  * Added capital hamburger.    
90  * 
91  * 3     6/05/97 5:00p John
92  * used fonttool.pcx
93  * 
94  * 2     6/05/97 4:53p John
95  * First rev of new antialiased font stuff.
96  * 
97  * 1     6/02/97 4:04p John
98  *
99  * $NoKeywords: $
100  */
101
102 #ifndef PLAT_UNIX
103 #include <windows.h>
104 #endif
105 #include <stdlib.h>
106 #include <stdio.h>
107 #include <time.h>
108 #ifndef PLAT_UNIX
109 #include <io.h>
110 #include <conio.h>
111 #endif
112
113 #include "pstypes.h"
114 #include "osapi.h"
115 #include "cfile.h"
116 #include "2d.h"
117 #include "key.h"
118 #include "mouse.h"
119 #include "palman.h"
120 #include "timer.h"
121 #include "bmpman.h"
122 #include "osregistry.h"
123
124 #include "fonttool.h"
125
126 char *SampleText = "This is some sample text that is here to\n" \
127 "Show you how the antialiasing will\n"  \
128 "look over different color backgrounds\n" \
129 "KERN PAIRS: VaWaVeWeVAV-LyT.T,TyTvTcYe\n";
130
131 static void myexit(int value)
132 {
133 //      getch();
134         exit(value);
135 }
136
137 int game_check_key()
138 {
139         return key_inkey();
140 }
141
142 int game_poll()
143 {
144         return key_inkey();
145 }
146
147 int os_done = 0;
148
149 void os_close()
150 {
151         os_done = 1;
152 }
153
154 int fonttool_get_kerning( font *fnt, int c1, int c2, int *pairnum )
155 {
156         int i;
157
158         int l1 = c1 - fnt->first_ascii;
159         int l2 = c2 - fnt->first_ascii;
160
161         for (i=0; i<fnt->num_kern_pairs; i++ )  {
162                 if ( (fnt->kern_data[i].c1 == l1) && (fnt->kern_data[i].c2 == l2) )     {
163                         if (pairnum) *pairnum = i;
164                         return fnt->kern_data[i].offset;
165                 }
166         }
167         return 0;
168 }
169
170 void fonttool_resync_kerning( font *fnt )
171 {
172         int i;
173
174         // update all the font into
175         for (i=0; i<fnt->num_chars; i++ )       {
176                 fnt->char_data[i].kerning_entry = -1;
177         }
178
179         for (i=0; i<fnt->num_kern_pairs; i++ )  {
180                 int c = fnt->kern_data[i].c1;
181                 if ( fnt->char_data[c].kerning_entry == -1 )
182                         fnt->char_data[c].kerning_entry = (short)i;
183         }
184 }
185
186 void fonttool_remove_kern_pair( font *fnt, int index )
187 {
188         // not found, add it
189         int i, n, new_num_pairs;
190
191         new_num_pairs = fnt->num_kern_pairs - 1;
192
193         if ( new_num_pairs < 1 )        {
194                 fonttool_remove_kerning(fnt);
195                 return;
196         }
197
198         font_kernpair *new_kern_data = (font_kernpair *)malloc( new_num_pairs*sizeof(font_kernpair) );
199         if (!new_kern_data)     {
200                 printf( "Out of memory!\n" );
201                 myexit(1);
202         }
203
204
205         n=0;
206         for (i=0; i<fnt->num_kern_pairs; i++ )  {
207                 if ( i != index )       {
208                         new_kern_data[n] = fnt->kern_data[i];
209                         n++;
210                 }
211         }
212
213         if ( fnt->kern_data ) free( fnt->kern_data );
214         fnt->kern_data = new_kern_data;
215         fnt->kern_data_size = sizeof(font_kernpair)*new_num_pairs;
216         fnt->num_kern_pairs = new_num_pairs;
217
218         fonttool_resync_kerning(fnt);
219
220         mprintf(( "Font has %d kern pairs\n", fnt->num_kern_pairs ));
221 }
222
223 void fonttool_set_kerning( font *fnt, int c1, int c2, int dist )
224 {
225         int i;
226
227         int l1 = c1 - fnt->first_ascii;
228         int l2 = c2 - fnt->first_ascii;
229
230         for (i=0; i<fnt->num_kern_pairs; i++ )  {
231                 if ( (fnt->kern_data[i].c1 == l1) && (fnt->kern_data[i].c2 == l2) )     {
232                         fnt->kern_data[i].offset = (signed char)dist;
233                         if ( dist == 0 )        {
234                                 fonttool_remove_kern_pair( fnt, i );                            
235                         }
236                         return;
237                 }
238         }
239         if ( dist == 0 )        return;
240
241         // not found, add it
242         int new_num_pairs;
243
244         new_num_pairs = fnt->num_kern_pairs+1;
245
246         font_kernpair *new_kern_data = (font_kernpair *)malloc( new_num_pairs*sizeof(font_kernpair) );
247         if (!new_kern_data)     {
248                 printf( "Out of memory!\n" );
249                 myexit(1);
250         }
251
252
253         int n=0;
254         uint newcode = l1*256+l2;
255
256         for (i=0; i<fnt->num_kern_pairs; i++ )  {
257                 uint code = fnt->kern_data[i].c1*256 + fnt->kern_data[i].c2;
258                 if ( code < newcode )   {
259                         new_kern_data[n] = fnt->kern_data[i];
260                         n++;
261                 } else {
262                         break;
263                 }
264         }
265
266
267         new_kern_data[n].c1 = (char)l1;
268         new_kern_data[n].c2 = (char)l2;
269         new_kern_data[n].offset = (signed char)dist;
270         n++;
271
272         
273         for (; i<fnt->num_kern_pairs; i++ )     {
274                 new_kern_data[n] = fnt->kern_data[i];
275                 n++;
276         }
277
278
279         if ( fnt->kern_data ) free( fnt->kern_data );
280         fnt->kern_data = new_kern_data;
281         fnt->kern_data_size +=  sizeof(font_kernpair);
282         fnt->num_kern_pairs++;
283
284         fonttool_resync_kerning(fnt);
285
286         mprintf(( "Font has %d kern pairs\n", fnt->num_kern_pairs ));
287
288 }
289
290
291 void fonttool_remove_kerning( font *fnt )
292 {
293         int i;
294
295         for (i=0; i<fnt->num_chars; i++ )       {
296                 fnt->char_data[i].kerning_entry = -1;
297         }
298
299         fnt->kern_data_size = 0;
300         if (fnt->kern_data)
301                 free( fnt->kern_data );
302         fnt->kern_data = NULL;
303         fnt->num_kern_pairs = 0;
304 }
305
306
307 void fonttool_edit_kerning(char *fname1, char *argv[])
308 {
309         int i, k,x;
310         int done;
311         int bkg;
312         font KernFont, tmpfont;
313         int alpha = 16;
314         int cr=16, cb=16, cg=16;
315         int c1 = 'b', c2 = 'u';
316         char kerntext[128];
317         int current_pair = -1;
318         int first_item = 0;
319         int current_item = 0;
320         int num_items_displayed = 1;
321         int last_good_pair = -1;
322         char *ptr;
323         color ac;
324         
325         printf( "Editing kerning data for %s\n", fname1 );
326         fonttool_read( fname1, &KernFont );
327
328         timer_init();
329
330         // setup the fred exe directory so CFILE can init properly
331         //char *c = GetCommandLine();
332         //Assert(c != NULL);
333         //char *tok = strtok(c, " ");
334         //Assert(tok != NULL);  
335 #ifdef PLAT_UNIX
336         char whee[1024];
337         getcwd (whee, 1024);
338         strcat(whee, "/");
339         strcat(whee, fname1);
340         cfile_init(whee);
341 #else
342         cfile_init(argv[0]);
343 #endif
344
345         os_init( "FontTool", "FontTool - Kerning Table Editor" );
346         // init the registry
347 #ifndef PLAT_UNIX
348         os_init_registry_stuff(Osreg_company_name, Osreg_app_name,NULL);
349 #endif
350         ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);      
351         if((ptr == NULL) || !stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
352 #ifndef PLAT_UNIX
353                 MessageBox((HWND)os_get_window(), "Warning, Freespace 2 requires Glide or Direct3D hardware accleration. You will not be able to run Freespace 2 without it", "Warning", MB_OK);                
354 #endif
355                 exit(1);
356         }
357
358         if (!stricmp(ptr, NOX("3DFX Glide"))) {
359                 // Glide
360                 gr_init(GR_640, GR_GLIDE);
361         } else if (strstr(ptr, NOX("Direct 3D -"))){
362                 // Direct 3D
363                 gr_init(GR_640, GR_DIRECT3D);
364         } else if (strstr(ptr, NOX("OpenGL"))){
365                 // OpenGL
366                 gr_init(GR_640, GR_OPENGL);
367         } else {
368                 Int3();
369         }       
370
371         gr_set_palette("none",NULL);
372 #ifndef PLAT_UNIX
373         bkg = bm_load( "code\\fonttool\\FontTool" );
374 #else
375         bkg = bm_load( "fonttool" );
376 #endif
377         if ( bkg < 0 )  {
378                 printf("Error loading FontTool\n" );
379                 myexit(1);
380         }
381         palette_use_bm_palette(bkg);
382
383         key_init();
384         mouse_init();
385
386         gr_init_alphacolor( &ac, cr*16,cg*16,cb*16,alpha*16 );
387         
388
389         {
390                 extern font *Current_font;
391                 Current_font = &KernFont;
392         }
393
394         done = 0;
395         while (!done)   {
396                 
397                 os_poll();
398                 k = key_inkey();
399                 switch(k)       {               
400                 case KEY_F5:
401                         fonttool_read( fname1, &tmpfont );
402                         fonttool_copy_kern( &tmpfont, &KernFont );
403                         break;
404
405                 case KEY_F6:
406                         fonttool_remove_kerning( &KernFont );
407                         break;
408
409                 case KEY_F10:
410                         fonttool_dump( fname1, &KernFont );
411                         done=1;
412                         break;
413
414                 case KEY_COMMA:
415                         if ( alpha > 1 )        {
416                                 alpha--;
417                                 gr_init_alphacolor(&ac,cr*16,cg*16,cb*16,alpha*16);
418                         }
419                         break;
420
421                 case KEY_PERIOD:
422                         if ( alpha < 17 )       {
423                                 alpha++;
424                                 gr_init_alphacolor(&ac,cr*16,cg*16,cb*16,alpha*16);
425                         }
426                         break;
427
428                 case KEY_R:
429                         if ( cr == 16 ) cr = 1; else cr = 16;
430                         gr_init_alphacolor(&ac,cr*16,cg*16,cb*16,alpha*16);
431                         break;
432
433                 case KEY_G:
434                         if ( cg == 16 ) cg = 1; else cg = 16;
435                         gr_init_alphacolor(&ac,cr*16,cg*16,cb*16,alpha*16);
436                         break;
437
438                 case KEY_B:
439                         if ( cb == 16 ) cb = 1; else cb = 16;
440                         gr_init_alphacolor(&ac,cr*16,cg*16,cb*16,alpha*16);
441                         break;
442
443                 case KEY_PAD6:
444                         x = fonttool_get_kerning( &KernFont, c1, c2, NULL );
445                         fonttool_set_kerning( &KernFont, c1, c2, x+1 );
446                         break;
447
448                 case KEY_PAD4:
449                         x = fonttool_get_kerning( &KernFont, c1, c2, NULL );
450                         fonttool_set_kerning( &KernFont, c1, c2, x-1 );
451                         break;
452
453                 case KEY_PAD5:
454                         fonttool_set_kerning( &KernFont, c1, c2, 0 );
455                         break;
456
457                 case KEY_PAD7:  
458                         if ( c1 < KernFont.first_ascii + KernFont.num_chars-1 ) c1++;
459                         break;
460
461                 case KEY_PAD1:  
462                         if ( c1 > KernFont.first_ascii ) c1--;
463                         break;
464
465                 case KEY_PAD9:  
466                         if ( c2 < KernFont.first_ascii + KernFont.num_chars-1 ) c2++;
467                         mprintf(( "C2 = %d\n", c2 ));
468                         break;
469
470                 case KEY_PAD3:  
471                         if ( c2 > KernFont.first_ascii ) c2--;
472                         mprintf(( "C2 = %d\n", c2 ));
473                         break;
474
475                 case KEY_PAD2:
476                         if ( current_pair < 0 ) 
477                                 current_pair = last_good_pair;
478                         else 
479                                 current_pair++;
480                         if ( current_pair >= KernFont.num_kern_pairs )  {
481                                 current_pair = KernFont.num_kern_pairs-1;
482                         }
483                         if ( (current_pair < KernFont.num_kern_pairs) && (current_pair > -1) )  {
484                                 c1 = KernFont.kern_data[current_pair].c1 + KernFont.first_ascii;
485                                 c2 = KernFont.kern_data[current_pair].c2 + KernFont.first_ascii;
486                         }
487                         break;
488
489                 case KEY_PAD8:
490                         if ( current_pair < 0 ) 
491                                 current_pair = last_good_pair;
492                         else
493                                 current_pair--;
494                         if ( current_pair < 0 ) {
495                                 current_pair = 0;
496                         }
497                         if ( (current_pair < KernFont.num_kern_pairs) && (current_pair > -1) )  {
498                                 c1 = KernFont.kern_data[current_pair].c1 + KernFont.first_ascii;
499                                 c2 = KernFont.kern_data[current_pair].c2 + KernFont.first_ascii;
500                         }
501                         break;
502
503                 case KEY_ESC:
504                         done=1;
505                         break;
506                 }
507
508                 if ( current_pair >= KernFont.num_kern_pairs )  {
509                         current_pair = -1;
510                 }
511
512                 int tmpp=-1;
513                 fonttool_get_kerning( &KernFont, c1, c2, &tmpp );
514
515                 if ( tmpp != -1 )       {
516                         current_pair = tmpp;
517                 } else  {
518                         if ( current_pair > -1 )
519                                 last_good_pair = current_pair;
520                         current_pair = -1;
521                 }
522         
523                 gr_reset_clip();
524                 gr_set_bitmap(bkg);
525                 gr_bitmap(0,0);
526                 gr_set_color_fast(&ac);
527
528                 sprintf( kerntext, "%c (%d)", c1, c1 );
529                 gr_string( 240, 210, kerntext );
530                 sprintf( kerntext, "%c (%d)", c2, c2 );
531                 gr_string( 340, 210, kerntext );
532
533                 sprintf( kerntext, "Ham%c%crger", c1, c2 );
534                 gr_string( 0x8000, 240, kerntext );
535
536                 sprintf( kerntext, "HAM%c%cRGER", c1, c2 );
537                 gr_string( 0x8000, 270, kerntext );
538
539                 sprintf( kerntext, "Offset: %d pixels", fonttool_get_kerning( &KernFont, c1, c2, NULL ) );
540                 gr_string( 0x8000, 300, kerntext );
541
542                 {
543                         int tw, th;
544                         gr_get_string_size( &tw, &th, kerntext );
545
546                         gr_string( 0x8000, 360, SampleText );
547                         gr_string( 20, 360+th+20, SampleText );
548                 }
549
550                 int x = 5, y = 200;
551                 int widest = 0;
552
553                  //= ( 330 - 200 ) / KernFont.h;
554                 int num_items = KernFont.num_kern_pairs;
555
556                 if ( current_pair > -1 )
557                         current_item = current_pair;
558
559                 if (current_item <0 )
560                         current_item = 0;
561
562                 if (current_item >= num_items )
563                         current_item = num_items-1;
564
565                 if (current_item<first_item)
566                         first_item = current_item;
567
568                 if (current_item>=(first_item+num_items_displayed))
569                         first_item = current_item-num_items_displayed+1;
570
571                 if (num_items <= num_items_displayed )  
572                         first_item = 0;
573
574                 int stop = first_item+num_items_displayed;
575                 if (stop>num_items) stop = num_items;
576
577                 int n = 0;
578                 for (i=first_item; i<stop; i++ )        {
579                         int tw, th;
580
581                         sprintf( kerntext, "%c%c", KernFont.kern_data[i].c1 + KernFont.first_ascii, KernFont.kern_data[i].c2 + KernFont.first_ascii );
582                         if ( i==current_pair )  {
583                                 gr_set_color( 255, 0, 0 );
584                                 //hud_tri( i2fl(x),i2fl(y), i2fl(x+6), i2fl(y+5), i2fl(x), i2fl(y+8) );
585                                 
586                                 int x1 = x;
587                                 int y1 = y;
588                                 int x2 = x+6;
589                                 int y2 = y+5;
590                                 int x3 = x;
591                                 int y3 = y+8;
592         
593                                 gr_line(x1,y1,x2,y2);
594                                 gr_line(x2,y2,x3,y3);
595                                 gr_line(x3,y3,x1,y1);
596
597                                 gr_set_color_fast(&ac);
598                         }
599                         gr_string( x+8, y, kerntext );
600                         n++;
601                         gr_get_string_size( &tw, &th, kerntext );
602                         tw += 8;
603                         if ( tw > widest )
604                                 widest = tw;
605                         y += KernFont.h;
606                         if ( y > 330 ) {
607                                 y = 200;
608                                 x += widest + 5;
609                                 if ( x > 150 ) {
610                                         num_items_displayed=n;
611                                         break;
612                                 }
613                                 widest = 0;
614                         }
615                 }
616                 if (i==stop)
617                         num_items_displayed++;
618
619                 if (num_items_displayed < 1 )
620                         num_items_displayed = 1;
621
622                 if (num_items_displayed > num_items )
623                         num_items_displayed = num_items;
624
625                 //mprintf(( "Num items = %d\n", num_items_displayed ));
626
627
628                 gr_flip();
629
630         }
631
632         // cleanup
633         if (bkg >= -1) {
634                 bm_unload(bkg);
635         }
636
637
638         exit(0);
639 }
640