contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / test / ftstrtto.c
blobf23ced320d3fde6f5e145390415add44b06fea05
1 /****************************************************************************/
2 /* */
3 /* The FreeType project -- a free and portable quality TrueType renderer. */
4 /* */
5 /* Copyright 1996-1999 by */
6 /* D. Turner, R.Wilhelm, and W. Lemberg */
7 /* */
8 /* ftstrtto: Making string text from individual glyph information, using */
9 /* TrueType Open features. */
10 /* */
11 /* Keys: */
12 /* */
13 /* + : fast scale up */
14 /* - : fast scale down */
15 /* u : fine scale down */
16 /* j : fine scale up */
17 /* */
18 /* h : toggle hinting */
19 /* K : toggle kerning */
20 /* B : toggle sbit */
21 /* G : toggle GSUB */
22 /* */
23 /* q : */
24 /* ESC : exit */
25 /* */
26 /* */
27 /* NOTE: This is just a test program that is used to show off and */
28 /* debug the current engine. */
29 /* */
30 /****************************************************************************/
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 #include "arabic.h"
37 #include "blitter.h"
38 #include "common.h" /* for Panic() only */
39 #include "display.h"
41 #include "freetype.h"
42 #include "ftxkern.h"
43 #include "ftxopen.h"
44 #include "ftxsbit.h"
46 #include "gdriver.h"
47 #include "gevents.h"
48 #include "gmain.h"
51 #define MAXPTSIZE 500 /* dtp */
52 #define Center_X ( Bit.width / 2 ) /* dtp */
53 #define Center_Y ( Bit.rows / 2 ) /* dtp */
55 #define FEATURE_init MAKE_TT_TAG( 'i', 'n', 'i', 't' )
56 #define FEATURE_medi MAKE_TT_TAG( 'm', 'e', 'd', 'i' )
57 #define FEATURE_fina MAKE_TT_TAG( 'f', 'i', 'n', 'a' )
58 #define FEATURE_isol MAKE_TT_TAG( 'i', 's', 'o', 'l' )
61 char Header[128];
63 TT_Engine engine;
64 TT_Face face;
65 TT_Instance instance;
66 TT_Glyph glyph;
67 TT_CharMap char_map;
68 TT_Kerning directory;
70 TTO_GSUBHeader gsub_;
71 TTO_GSUBHeader* gsub;
72 TTO_GDEFHeader gdef_;
73 TTO_GDEFHeader* gdef;
75 TT_Big_Glyph_Metrics metrics;
76 TT_Outline outline;
77 TT_Face_Properties face_properties;
78 TT_Instance_Metrics imetrics;
80 TT_SBit_Image* sbit;
82 int pt_size;
83 int ttc_index;
84 TT_Bool hinted;
85 TT_Bool gray_render;
86 TT_Bool r2l;
87 TT_Bool vertical;
89 TT_Bool has_kern;
90 TT_Bool use_kern;
91 TT_Bool has_gdef;
92 TT_Bool has_gsub;
93 TT_Bool use_gsub;
94 TT_Bool has_sbit;
95 TT_Bool use_sbit;
96 TT_Bool glyph_has_sbit;
98 TT_Bool default_language_system;
100 int Fail;
102 char* char_string;
104 TT_UShort glyph_code_array[129];
105 TT_UShort char_code[128];
106 TT_UShort properties[128];
108 TT_UShort* glyph_code;
109 int num_glyphs;
111 TT_ULong script_tag;
112 char* script_tag_string;
113 TT_UShort script_index;
115 TT_ULong language_tag;
116 char* language_tag_string;
117 TT_UShort language_index;
118 TT_UShort req_feature_index = 0xFFFF;
120 TT_ULong* feature_tags;
121 char** feature_tag_strings;
122 TT_UShort* feature_indices;
123 int num_features;
126 static void Select_CMap( void )
128 TT_UShort i, n;
129 TT_UShort platform, encoding;
132 n = face_properties.num_CharMaps;
134 for ( i = 0; i < n; i++ )
136 TT_Get_CharMap_ID( face, i, &platform, &encoding );
137 if ( platform == 3 && encoding == 1 )
139 TT_Get_CharMap( face, i, &char_map );
140 break;
144 /* we try only pid/eid (0,0) if no (3,1) map is found -- many Windows
145 fonts have only rudimentary (0,0) support. */
147 if ( i == n )
149 for ( i = 0; i < n; i++ )
151 TT_Get_CharMap_ID( face, i, &platform, &encoding );
152 if ( platform == 0 && encoding == 0 )
154 TT_Get_CharMap( face, i, &char_map );
155 break;
159 if ( i == n )
160 Panic( "Sorry, but this font doesn't contain"
161 " any Unicode mapping table\n" );
166 /* Convert a Latin 1 string to a string of glyph indexes. */
167 /* */
168 /* IMPORTANT NOTE: */
169 /* */
170 /* There is no portable way to convert from any system's char. code */
171 /* to Unicode. This function simply takes a char. string as argument */
172 /* and `interprets' each character as a Unicode char. index with no */
173 /* further check. */
174 /* */
175 /* We interpret the command line string as Unicode with the high byte */
176 /* set to zero. This is equivalent to Latin-1. */
178 static void Latin1Char_To_Glyph( char* source )
180 TT_UShort n;
183 glyph_code = glyph_code_array + 1; /* we want to make glyph_code[-1] */
184 glyph_code[-1] = 0; /* possible. */
186 for ( n = 0; n < 128 && source[n]; n++ )
188 char_code[n] = (TT_UShort)( (unsigned char)source[n] );
189 glyph_code[n] = TT_Char_Index( char_map, char_code[n] );
192 num_glyphs = n;
196 static void UTF8Char_To_Glyph( char* source )
198 TT_UShort in, out, in_code, out_code;
199 TT_UShort count, limit;
202 glyph_code = glyph_code_array + 1; /* we want to make glyph_code[-1] */
203 glyph_code[-1] = 0; /* possible. */
205 for ( in = out = 0, count = limit = 1, in_code = out_code = 0;
206 in < 128 && source[in]; in++ )
208 in_code = (TT_UShort)( (unsigned char)source[in] );
210 if ( in_code >= 0xC0 )
212 limit = 1;
213 count = 1;
215 if ( in_code < 0xE0 ) /* U+0080 - U+07FF */
217 limit = 2;
218 out_code = in_code & 0x1F;
220 else if ( in_code < 0xF0 ) /* U+0800 - U+FFFF */
222 limit = 3;
223 out_code = in_code & 0x0F;
225 continue;
227 else if ( in_code >= 0x80 )
229 count++;
231 if ( count <= limit )
233 out_code <<= 6;
234 out_code += in_code & 0x3F;
236 if ( count != limit )
237 continue;
239 else
240 out_code = in_code;
242 char_code[out] = out_code;
243 glyph_code[out++] = TT_Char_Index( char_map, out_code );
246 num_glyphs = out;
250 static TT_Error Reset_Scale( int pointSize )
252 TT_Error error;
255 error = TT_Set_Instance_CharSize( instance, pointSize * 64L );
256 if ( error )
258 RestoreScreen();
259 Panic( "Could not reset instance, code = 0x%x.\n", error );
262 TT_Get_Instance_Metrics( instance, &imetrics );
264 /* now re-allocate the small bitmap */
265 if ( gray_render )
267 Init_Small( imetrics.x_ppem, imetrics.y_ppem );
268 Clear_Small();
271 return TT_Err_Ok;
275 static TT_Error Load_TrueType_Char( TT_UShort idx,
276 int hint )
278 int flags;
279 TT_Error error;
282 glyph_has_sbit = 0;
284 error = TT_Load_Glyph_Bitmap( face, instance, idx, sbit );
285 if ( error == TT_Err_Ok )
287 has_sbit = 1;
288 glyph_has_sbit = 1;
291 if ( glyph_has_sbit && use_sbit )
292 return TT_Err_Ok;
294 flags = TTLOAD_SCALE_GLYPH;
295 if ( hint )
296 flags |= TTLOAD_HINT_GLYPH;
298 return TT_Load_Glyph( instance, glyph, idx, flags );
302 static TT_Error Get_Kern_Values( TT_UShort idx,
303 TT_Pos* x,
304 TT_Pos* y )
306 TT_UShort i;
307 TT_Kern_Subtable table;
308 TT_Kern_0_Pair* pairs_0;
310 TT_UShort min, max, new_min, new_max, middle;
311 TT_Long target_idx, current_idx;
314 *x = 0;
315 *y = 0;
317 for ( i = 0; i < directory.nTables; i++ )
319 table = directory.tables[i];
321 /* handle only horizontal kerning tables */
323 if ( table.coverage & 0x0001 )
325 switch ( table.format )
327 case 0:
328 pairs_0 = table.t.kern0.pairs;
329 target_idx = ( glyph_code[idx - 1] << 16 ) + glyph_code[idx];
331 /* binary search */
333 new_min = 0;
334 new_max = table.t.kern0.nPairs - 1;
338 min = new_min;
339 max = new_max;
340 middle = max - ( ( max - min ) >> 1 );
342 current_idx = ( pairs_0[middle].left << 16 ) +
343 pairs_0[middle].right;
345 if ( target_idx == current_idx )
347 *x += pairs_0[middle].value;
348 break;
350 else if ( target_idx < current_idx )
352 if ( middle == min )
353 break;
354 new_max = middle - 1;
356 else
358 if ( middle == max )
359 break;
360 new_min = middle + 1;
362 } while ( min < max );
364 break;
366 /* we currently ignore format 2 kerning tables */
368 case 2:
369 break;
374 /* scaling and rounding */
376 *x = ( ( ( *x * imetrics.x_scale ) / 0x10000 ) + 32 ) & -64;
377 *y = ( ( ( *y * imetrics.y_scale ) / 0x10000 ) + 32 ) & -64;
379 return TT_Err_Ok;
383 /* for testing purposes, we always select the last available alternate
384 glyph, not using the `data' field. */
386 static TT_UShort alternate_function( TT_ULong pos,
387 TT_UShort glyphID,
388 TT_UShort num_alternates,
389 TT_UShort* alternates,
390 void* data )
392 return num_alternates - 1;
396 static TT_Error Render_All( void )
398 TT_Pos x, y, z, min_x, min_y, max_x, max_y;
399 TT_Pos kern_x, kern_y;
400 int i, n;
401 TT_UShort* gc;
402 TT_UShort glyph_property = 0;
404 TT_Error error;
406 TTO_GSUB_String in, out;
409 /* On the first pass, we compute the compound bounding box */
411 x = y = 0;
412 kern_x = kern_y = 0;
413 min_x = min_y = max_x = max_y = 0;
415 in.length = num_glyphs;
416 in.pos = 0;
417 in.string = glyph_code;
418 in.properties = properties;
420 out.pos = 0;
421 out.allocated = 0;
422 out.string = NULL;
423 out.properties = NULL;
425 if ( has_gsub && use_gsub )
427 error = TT_GSUB_Apply_String( gsub, &in, &out );
428 if ( error && error != TTO_Err_Not_Covered )
429 return error;
431 n = out.length;
432 gc = out.string;
434 else
436 n = in.length;
437 gc = in.string;
440 has_sbit = 0;
442 for ( i = 0; i < n; i++ )
444 error = Load_TrueType_Char( gc[i], hinted );
445 if ( error == TT_Err_Ok )
447 if ( glyph_has_sbit && use_sbit )
448 metrics = sbit->metrics;
449 else
450 TT_Get_Glyph_Big_Metrics( glyph, &metrics );
451 if ( has_kern && use_kern )
452 Get_Kern_Values( i, &kern_x, &kern_y );
454 z = x + metrics.bbox.xMin + kern_x;
455 if ( min_x > z )
456 min_x = z;
458 z = x + metrics.bbox.xMax + kern_x;
459 if ( max_x < z )
460 max_x = z;
462 z = y + metrics.bbox.yMin + kern_y;
463 if ( min_y > z )
464 min_y = z;
466 z = y + metrics.bbox.yMax + kern_y;
467 if ( max_y < z )
468 max_y = z;
470 if ( has_gdef )
472 error = TT_GDEF_Get_Glyph_Property( gdef, gc[i], &glyph_property );
473 if ( error )
474 return error;
477 /* advance only if it is not a mark glyph */
479 if ( !( glyph_property & TTO_MARK ) )
481 if ( vertical )
482 y += ( metrics.vertAdvance & -64 ) + kern_y;
483 else
484 x += ( metrics.horiAdvance & -64 ) + kern_x;
487 else
488 Fail++;
491 /* We now center the bbox inside the target bitmap */
493 min_x = ( min_x & -64 ) >> 6;
494 min_y = ( min_y & -64 ) >> 6;
496 max_x = ( (max_x + 63) & -64 ) >> 6;
497 max_y = ( (max_y + 63) & -64 ) >> 6;
499 max_x -= min_x;
500 max_y -= min_y;
502 min_x = ( Bit.width - max_x ) / 2;
503 min_y = ( Bit.rows - max_y ) / 2;
505 max_x += min_x;
506 max_y += min_y;
508 /* On the second pass, we render each glyph to its centered position. */
509 /* This is slow, because we reload each glyph to render it! */
511 x = vertical ? min_x : ( r2l ? max_x : min_x );
512 y = vertical ? ( r2l ? min_y : max_y ) : min_y;
514 for ( i = 0; i < n; i++ )
516 error = Load_TrueType_Char( gc[i], hinted );
517 if ( error == TT_Err_Ok )
519 if ( glyph_has_sbit && use_sbit )
520 metrics = sbit->metrics;
521 else
522 TT_Get_Glyph_Big_Metrics( glyph, &metrics );
523 if ( has_kern && use_kern )
524 Get_Kern_Values( i, &kern_x, &kern_y );
526 if ( has_gdef )
527 (void)TT_GDEF_Get_Glyph_Property( gdef, gc[i], &glyph_property );
529 if ( !( glyph_property & TTO_MARK ) )
531 if ( r2l )
533 if ( vertical )
534 y += metrics.vertAdvance / 64;
535 else
536 x -= metrics.horiAdvance / 64;
538 else
540 if ( vertical )
541 y -= kern_y / 64;
542 else
543 x += kern_x / 64;
547 /* We must specify the upper left corner of the bitmap, but the
548 lower left corner for the outline. Another complication is that
549 Blit_Bitmap() assumes that increasing y values means moving
550 downwards.
552 For vertical layout, the origin of the horizontal and vertical
553 bearings of embedded bitmaps is the top, thus we shift the
554 outline glyphs down. */
556 if ( glyph_has_sbit && use_sbit )
557 Blit_Bitmap( &Bit,
558 &sbit->map,
559 gray_render ? 8 : 1,
561 ( vertical ? metrics.vertBearingX :
562 metrics.horiBearingX ) / 64,
563 Bit.rows - y -
564 ( vertical ? metrics.vertBearingY :
565 metrics.horiBearingY ) / 64,
566 gray_palette[4] );
567 else
568 Render_Single_Glyph(
569 gray_render,
570 glyph,
573 ( vertical ? metrics.vertBearingY + metrics.bbox.yMax :
574 0 ) / 64 );
576 if ( !( glyph_property & TTO_MARK ) )
578 if ( r2l )
580 if ( vertical )
581 y += kern_y / 64;
582 else
583 x -= kern_x / 64;
585 else
587 if ( vertical )
588 y -= metrics.vertAdvance / 64;
589 else
590 x += metrics.horiAdvance / 64;
596 if ( out.string )
597 free( out.string );
598 if ( out.properties )
599 free( out.properties );
601 return TT_Err_Ok;
605 static int Process_Event( TEvent* event )
607 switch ( event->what )
609 case event_Quit: /* ESC or q */
610 return 0;
612 case event_Keyboard:
613 if ( event->info == 'h' ) /* Toggle hinting */
614 hinted = !hinted;
615 else if ( event->info == 'K' ) /* Toggle kerning */
616 use_kern = !use_kern;
617 else if ( event->info == 'B' ) /* Toggle sbit */
618 use_sbit = !use_sbit;
619 else if ( event->info == 'G' ) /* Toggle gsub */
620 use_gsub = !use_gsub;
621 break;
623 case event_Rotate_Glyph:
624 break;
626 case event_Scale_Glyph:
627 pt_size += event->info;
628 if ( pt_size < 1 ) pt_size = 1;
629 if ( pt_size > MAXPTSIZE ) pt_size = MAXPTSIZE;
630 break;
632 case event_Change_Glyph:
633 break;
636 return 1;
640 static void Usage( char* execname )
642 fprintf( stderr,
643 "\n"
644 "ftstrtto: TrueType Open String Test Display -- part of the FreeType project\n"
645 "---------------------------------------------------------------------------\n"
646 "\n"
647 "Usage: %s [options below] ppem fontname[.ttf|.ttc] [string|-]\n"
648 "\n"
649 " -c C use font with index C in TrueType collection (default: 0)\n"
650 " -f F use feature F (can be specified more than once)\n"
651 " -g gray-level rendering\n"
652 " -l L use language L\n"
653 " -r R use resolution R dpi (default: 96)\n"
654 " -s S use script S\n"
655 " -u interpret input data as UTF8-encoded\n"
656 " -v display string vertically\n"
657 " -x display string from right to left\n"
658 "\n"
659 " F, L, and S must be specified as 4-character tags.\n"
660 " Specifying only F and S selects default language system of S.\n"
661 " Specifying only L and S selects the req. feature of L only (if any).\n"
662 "\n"
663 " If `-' is specified as input string, stdin is read instead.\n"
664 "\n", execname );
666 exit( EXIT_FAILURE );
670 static TT_ULong Make_Tag( char* tag_string )
672 char t1 = ' ', t2 = ' ', t3 = ' ', t4 = ' ';
675 if ( !tag_string )
676 return 0;
678 t1 = tag_string[0];
679 if ( tag_string[1] )
680 t2 = tag_string[1];
681 if ( tag_string[2] )
682 t3 = tag_string[2];
683 if ( tag_string[3] )
684 t4 = tag_string[3];
686 return MAKE_TT_TAG( t1, t2, t3, t4 );
690 int main( int argc,
691 char** argv )
693 int i, old_pt_size, orig_pt_size, file;
695 int graphics_initialized = 0;
697 char filename[128 + 4];
698 char alt_filename[128 + 4];
699 char* execname;
701 int option;
702 int res = 96;
703 int utf8 = 0;
705 TT_Error error;
706 TEvent event;
709 execname = argv[0];
711 while ( 1 )
713 option = ft_getopt( argc, argv, "c:f:gl:r:s:uvx" );
715 if ( option == -1 )
716 break;
718 switch ( option )
720 case 'c':
721 ttc_index = atoi( ft_optarg );
722 if ( ttc_index < 0 )
723 Usage( execname );
724 break;
726 case 'f':
727 num_features++;
728 feature_tag_strings = (char**)
729 realloc( feature_tag_strings,
730 num_features * sizeof ( char* ) );
731 feature_tags = (TT_ULong*)
732 realloc( feature_tags,
733 num_features * sizeof ( TT_ULong ) );
734 feature_tag_strings[num_features - 1] = ft_optarg;
735 if ( !(feature_tags[num_features - 1] = Make_Tag( ft_optarg ) ) )
736 Usage( execname );
737 break;
739 case 'g':
740 gray_render = 1;
741 break;
743 case 'l':
744 language_tag_string = ft_optarg;
745 if ( !(language_tag = Make_Tag( ft_optarg ) ) )
746 Usage( execname );
747 break;
749 case 'r':
750 res = atoi( ft_optarg );
751 if ( res < 1 )
752 Usage( execname );
753 break;
755 case 's':
756 script_tag_string = ft_optarg;
757 if ( !(script_tag = Make_Tag( ft_optarg ) ) )
758 Usage( execname );
759 break;
761 case 'u':
762 utf8 = 1;
763 break;
765 case 'v':
766 vertical = 1;
767 break;
769 case 'x':
770 r2l = 1;
771 break;
773 default:
774 Usage( execname );
775 break;
779 argc -= ft_optind;
780 argv += ft_optind;
782 if ( argc <= 1 )
783 Usage( execname );
785 if ( sscanf( argv[0], "%d", &orig_pt_size ) != 1 )
786 orig_pt_size = 64;
788 file = 1;
790 /* Initialize engine */
792 error = TT_Init_FreeType( &engine );
793 if ( error )
794 Panic( "Error while initializing engine, code = 0x%x.\n", error );
796 error = TT_Init_Kerning_Extension( engine );
797 if ( error )
798 Panic( "Error while initializing kerning extension, code = 0x%x.\n",
799 error );
801 error = TT_Init_SBit_Extension( engine );
802 if ( error )
803 Panic( "Error while initializing sbit extension, code = 0x%x.\n",
804 error );
806 error = TT_Init_GDEF_Extension( engine );
807 if ( error )
808 Panic( "Error while initializing GDEF extension, code = 0x%x.\n",
809 error );
811 error = TT_Init_GSUB_Extension( engine );
812 if ( error )
813 Panic( "Error while initializing GSUB extension, code = 0x%x.\n",
814 error );
816 pt_size = orig_pt_size;
817 hinted = 1;
818 use_gsub = 1;
819 use_kern = 1;
820 use_sbit = 1;
822 i = strlen( argv[file] );
823 while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
825 if ( argv[file][i] == '.' )
826 i = 0;
827 i--;
830 filename[128] = '\0';
831 alt_filename[128] = '\0';
833 strncpy( filename, argv[file], 128 );
834 strncpy( alt_filename, argv[file], 128 );
836 if ( i >= 0 )
838 strncpy( filename + strlen( filename ), ".ttf", 4 );
839 strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
842 /* Load face */
844 error = TT_Open_Face( engine, filename, &face );
845 if ( error == TT_Err_Could_Not_Open_File )
847 strcpy( filename, alt_filename );
848 error = TT_Open_Face( engine, alt_filename, &face );
850 if ( error == TT_Err_Could_Not_Open_File )
851 Panic( "Could not find/open `%s'.\n", filename );
852 else if ( error )
853 Panic( "Error while opening `%s', code = 0x%x.\n",
854 filename, error );
856 /* get face properties and allocate preload arrays */
858 TT_Get_Face_Properties( face, &face_properties );
860 /* open font in collection */
862 if ( ttc_index >= face_properties.num_Faces )
863 Panic( "There is no collection with index %d in this font file.\n",
864 ttc_index );
866 TT_Close_Face( face );
868 error = TT_Open_Collection( engine, filename, ttc_index, &face );
869 if ( error )
870 Panic( "Error while opening collection %d in `%s', code = 0x%x.\n",
871 ttc_index, filename, error );
873 /* create glyph */
875 error = TT_New_Glyph( face, &glyph );
876 if ( error )
877 Panic( "Could not create glyph container, code = 0x%x.\n", error );
879 /* create sbit slot */
881 error = TT_New_SBit_Image( &sbit );
882 if ( error )
883 Panic( "Could not create sbit slot, code = 0x%x.\n" , error);
885 /* create instance */
887 error = TT_New_Instance( face, &instance );
888 if ( error )
889 Panic( "Could not create instance for `%s', code = 0x%x.\n",
890 filename, error );
892 error = TT_Set_Instance_Resolutions( instance, res, res );
893 if ( error )
894 Panic( "Could not set device resolutions, code = 0x%x.\n", error );
896 error = TT_Get_Kerning_Directory( face, &directory );
897 if ( error )
898 Panic( "Could not get kerning directory, code = 0x%x.\n", error );
900 /* load all kerning tables */
902 for ( i = 0; i < directory.nTables; i++ )
904 error = TT_Load_Kerning_Table( face, i );
905 if ( error )
906 Panic( "Could not load kerning table, code = 0x%x.\n", error );
909 if ( directory.nTables )
910 has_kern = 1;
912 Select_CMap();
914 /* GDEF support */
916 gdef = &gdef_;
918 error = TT_Load_GDEF_Table( face, gdef );
919 if ( !error )
920 has_gdef = 1;
921 else if ( error != TT_Err_Table_Missing )
922 Panic( "Error while loading GDEF table, code = 0x%x.\n", error );
924 /* we must assign glyph properties in case no GDEF table is available */
926 if ( !has_gdef )
928 Build_Arabic_Glyph_Properties( char_map, face_properties.num_Glyphs,
929 &gdef );
930 if ( gdef )
931 has_gdef = 1;
934 /* GSUB support */
936 gsub = &gsub_;
938 error = TT_Load_GSUB_Table( face, gsub, gdef );
939 if ( !error )
941 if ( script_tag && feature_tags )
942 has_gsub = 1;
943 if ( script_tag && language_tag )
944 has_gsub = 1;
946 else if ( error != TT_Err_Table_Missing )
947 Panic( "Error while loading GSUB table, code = 0x%x.\n", error );
949 TT_GSUB_Clear_Features( gsub );
951 if ( has_gsub && !language_tag )
952 default_language_system = 1;
954 feature_indices = (TT_UShort*)
955 malloc( num_features * sizeof ( TT_UShort ) );
957 if ( has_gsub )
959 error = TT_GSUB_Select_Script( gsub,
960 script_tag,
961 &script_index );
962 if ( error )
963 Panic( "Requested script `%-4.4s' not found.\n",
964 script_tag_string );
966 if ( default_language_system )
968 for ( i = 0; i < num_features; i++ )
970 error = TT_GSUB_Select_Feature( gsub,
971 feature_tags[i],
972 script_index, 0xFFFF,
973 &feature_indices[i] );
974 if ( error )
975 Panic( "Requested feature `%-4.4s'\n"
976 "for default language system of script `%-4.4s' not found.\n",
977 feature_tag_strings[i], script_tag_string );
980 else
982 error = TT_GSUB_Select_Language( gsub,
983 language_tag,
984 script_index,
985 &language_index,
986 &req_feature_index );
987 if ( error )
988 Panic( "Requested language `%-4.4s'\n"
989 "for script `%-4.4s' not found.\n",
990 language_tag_string, script_tag_string );
992 for ( i = 0; i < num_features; i++ )
994 error = TT_GSUB_Select_Feature( gsub,
995 feature_tags[i],
996 script_index, language_index,
997 &feature_indices[i] );
998 if ( error )
999 Panic( "Requested feature `%-4.4s'\n"
1000 "for script `%-4.4s', language `%-4.4s' not found.\n",
1001 feature_tag_strings[i], script_tag_string,
1002 language_tag_string );
1006 if ( req_feature_index != 0xFFFF )
1007 TT_GSUB_Add_Feature( gsub, req_feature_index, ALL_GLYPHS );
1008 else if ( !num_features )
1009 has_gsub = 0;
1011 for ( i = 0; i < num_features; i++ )
1013 if ( feature_tags[i] == FEATURE_init )
1014 TT_GSUB_Add_Feature( gsub, feature_indices[i], initial );
1015 else if ( feature_tags[i] == FEATURE_medi )
1016 TT_GSUB_Add_Feature( gsub, feature_indices[i], medial );
1017 else if ( feature_tags[i] == FEATURE_fina )
1018 TT_GSUB_Add_Feature( gsub, feature_indices[i], final );
1019 else if ( feature_tags[i] == FEATURE_isol )
1020 TT_GSUB_Add_Feature( gsub, feature_indices[i], isolated );
1021 else
1022 TT_GSUB_Add_Feature( gsub, feature_indices[i], ALL_GLYPHS );
1025 TT_GSUB_Register_Alternate_Function( gsub, alternate_function, NULL );
1029 if ( !graphics_initialized )
1031 graphics_initialized = 1;
1033 if ( gray_render )
1035 if ( !SetGraphScreen( Graphics_Mode_Gray ) )
1036 Panic( "Could not set up grayscale graphics mode.\n" );
1038 TT_Set_Raster_Gray_Palette( engine, virtual_palette );
1040 else
1042 if ( !SetGraphScreen( Graphics_Mode_Mono ) )
1043 Panic( "Could not set up mono graphics mode.\n" );
1047 Init_Display( gray_render );
1049 Reset_Scale( pt_size );
1051 old_pt_size = pt_size;
1053 Fail = 0;
1055 /* get string to display, if any */
1057 if ( argv[2] )
1059 if ( argv[2][0] == '-' )
1061 int ch;
1062 char* p;
1065 char_string = (char*)malloc( 128 * sizeof ( char ) );
1066 p = char_string;
1068 for ( i = 0; i < 128; i++ )
1070 ch = getchar();
1071 if ( ch == '\n' || ch == EOF )
1073 *p = '\0';
1074 break;
1077 *p++ = (char)ch;
1080 *p = '\0';
1082 else
1083 char_string = argv[2];
1085 else
1086 char_string = "The quick brown fox jumps over the lazy dog";
1088 if ( utf8 )
1089 UTF8Char_To_Glyph( char_string );
1090 else
1091 Latin1Char_To_Glyph( char_string );
1093 /* we assign Arabic script features (e.g. `initial' or `final') */
1095 Assign_Arabic_Properties( char_code, properties, num_glyphs );
1097 for ( ;; )
1099 int key;
1102 Clear_Display();
1104 error = Render_All();
1105 if ( error )
1106 Panic( "Error while rendering string, code = 0x%x.\n", error );
1108 if ( gray_render )
1109 Convert_To_Display_Palette();
1111 sprintf( Header,
1112 "%s: ptsize: %d hinting: %s%s%s%s%s%s%s",
1113 ft_basename( filename ),
1114 pt_size,
1115 hinted ? "on" : "off",
1116 has_kern ? " kerning: " : "",
1117 has_kern ? ( use_kern ? "on" : "off" ) : "",
1118 has_sbit ? " sbit: " : "",
1119 has_sbit ? ( use_sbit ? "on" : "off" ) : "",
1120 has_gsub ? " GSUB: " : "",
1121 has_gsub ? ( use_gsub ? "on" : "off" ) : "" );
1123 Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols );
1125 #ifndef X11
1126 #ifndef OS2
1127 Print_XY( 0, 0, Header );
1128 #endif
1129 #endif
1131 Get_Event( &event );
1132 if ( !( key = Process_Event( &event ) ) )
1133 goto Fin;
1135 if ( pt_size != old_pt_size )
1137 if ( Reset_Scale( pt_size ) )
1138 Panic( "Could not resize font.\n" );
1140 old_pt_size = pt_size;
1144 Fin:
1145 RestoreScreen();
1147 TT_Done_FreeType( engine );
1149 printf( "Execution completed successfully.\n" );
1150 printf( "Fails = %d.\n", Fail );
1152 exit( EXIT_SUCCESS ); /* for safety reasons */
1154 return 0; /* never reached */
1158 /* End */