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