home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / test / ftstring.c < prev    next >
C/C++ Source or Header  |  1997-10-06  |  19KB  |  726 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*  The FreeType project -- a free and portable quality TrueType renderer.  */
  4. /*                                                                          */
  5. /*  Copyright 1996, 1997 by                                                 */
  6. /*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
  7. /*                                                                          */
  8. /* FTString :  Making string  text from individual glyph indormation        */
  9. /*             This program makes use of FreeType's kerning extension       */
  10. /*                                                                          */
  11. /*  Keys:                                                                   */
  12. /*                                                                          */
  13. /*  x :   fine counter-clockwise rotation                                   */
  14. /*  c :   fine clockwise rotation                                           */
  15. /*                                                                          */
  16. /*  v :   fast counter-clockwise rotation                                   */
  17. /*  b :   fast clockwise rotation                                           */
  18. /*                                                                          */
  19. /*  + :   fast scale up                                                     */
  20. /*  - :   fast scale down                                                   */
  21. /*  u :   fine scale down                                                   */
  22. /*  j :   fine scale up                                                     */
  23. /*                                                                          */
  24. /*  l :   go to next glyph                                                  */
  25. /*  k :   go to previous glyph                                              */
  26. /*                                                                          */
  27. /*  o :   go to tenth next glyph                                            */
  28. /*  i :   go to tenth previous glyph                                        */
  29. /*                                                                          */
  30. /*  0 :   go to hundredth next glyph                                        */
  31. /*  9 :   go to hundredth previous glyph                                    */
  32. /*                                                                          */
  33. /*  n :   go to next (or last) .ttf file                                    */
  34. /*  p :   go to previous (or first) .ttf file                               */
  35. /*                                                                          */
  36. /*  h :   toggle hinting                                                    */
  37. /*                                                                          */
  38. /*  ESC :   exit                                                            */
  39. /*                                                                          */
  40. /*                                                                          */
  41. /*  NOTE:  This is just a test program that is used to show off and         */
  42. /*         debug the current engine.                                        */
  43. /*                                                                          */
  44. /****************************************************************************/
  45.  
  46. #ifdef ARM
  47. #include "std.h"
  48. #include "graflink.h"
  49. #endif
  50.  
  51. #include "freetype.h"
  52. #include "ftxkern.h"
  53. #include "tterror.h"  /* for Panic() and Message() only */
  54.  
  55. #include "ft_conf.h" 
  56. /* This is needed to have getopt() and getind()     */
  57. /* working on Solaris.  We should be able to remove */
  58. /* this line on other platforms...                  */
  59.  
  60. #include "stdio.h"
  61. #include "stdlib.h"
  62. #include "string.h"
  63.  
  64.  
  65. /* getopt() should be in either getopt.h, stdlib.h, or unistd.h */
  66.  
  67. /* The following is needed before the #include <unistd.h>   */
  68. /* with my school's Suns to have 'getopt' working  - DavidT */
  69.  
  70. #if defined(__sun__)
  71. #define __EXTENSIONS__
  72. #endif
  73.  
  74. #ifdef HAVE_GETOPT_H
  75. #include <getopt.h>
  76. #else
  77. #ifdef HAVE_UNISTD_H
  78. #include <unistd.h>
  79. #endif
  80. #endif
  81.  
  82. #include "gmain.h"
  83. #include "gevents.h"
  84. #include "gdriver.h"
  85.  
  86.  
  87. #ifdef ARM
  88. #include "armsup.c" /* pull in our routines */
  89. #endif
  90.  
  91. /* The SunOS header files do not provide external declarations for optarg() */
  92. /* and optind(), so declare them here if necessary.  A check to see if the  */
  93. /* GNU C library is being used on SunOS should be added at some point.  If  */
  94. /* The GNU C library is being used, these declarations are not necessary.   */
  95.  
  96. #if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
  97.   extern char*  optarg;
  98.   extern int    optind;
  99. #endif
  100.  
  101. #define  Pi         3.1415926535
  102.  
  103. #define  MAXPTSIZE  500                 /* dtp */
  104. #define  Center_X   ( Bit.width / 2 )   /* dtp */
  105. #define  Center_Y   ( Bit.rows  / 2 )   /* dtp */
  106.  
  107.   char                Header[128];
  108.  
  109.   TT_Face      face;
  110.   TT_Instance  instance;
  111.   TT_Glyph     glyph;
  112.   TT_CharMap   char_map;
  113.  
  114.   TT_Glyph_Metrics     metrics;
  115.   TT_Glyph_Outline     outline;
  116.   TT_Face_Properties   properties;
  117.   TT_Instance_Metrics  imetrics;
  118.  
  119.   int  num_glyphs;
  120.  
  121.   int  ptsize;
  122.   int  hinted;
  123.  
  124.   TT_Raster_Map  Bit;
  125.   TT_Raster_Map  Small_Bit;   /* used when font-smoothing is enabled */
  126.  
  127.   int            Rotation;
  128.   int            Fail;
  129.   int            Num;
  130.   unsigned char  autorun;
  131.  
  132.   int            gray_render;
  133.  
  134.   static void   ClearData();
  135.   extern char*  basename( char* );
  136.  
  137.   char          palette[5] = { 0, 1, 2, 3, 4 };
  138.  
  139.   /* Or-ing the possible palette values gets us from 0 to 7 */
  140.   /* We must bound check these..                            */
  141.  
  142.   const char    bounded_palette[8] = { 0, 1, 2, 3, 4, 4, 4, 4 };
  143.  
  144.  
  145.   short  glyph_code[128];
  146.   int    num_codes;
  147.  
  148.  
  149.   static void  Set_Raster_Area()
  150.   {
  151.     Bit.rows  = vio_Height;     /* The whole window */
  152.     Bit.width = vio_Width & -4;
  153.     Bit.flow  = TT_Flow_Up;
  154.  
  155.     if ( gray_render )
  156.     {
  157.       Bit.cols  = Bit.width;
  158.       Bit.size  = Bit.rows * Bit.width;
  159.     }
  160.     else
  161.     {
  162.       Bit.cols  = ( Bit.width + 7 ) / 8;    /* convert to # of bytes     */
  163.       Bit.size  = Bit.rows * Bit.cols;      /* number of bytes in buffer */
  164.     }
  165.   }
  166.  
  167.  
  168.   static int  Init_Engine() 
  169.   {
  170.     Set_Raster_Area();   /* set up maximum raster size */
  171.   
  172.     Bit.bitmap = (void*)malloc( (int)Bit.size );
  173.     if ( !Bit.bitmap ) 
  174.       Panic( "ERROR: Not enough memory to allocate bitmap!\n" );
  175.   
  176.     ClearData();
  177.  
  178.     return 0;
  179.   }
  180.   
  181.   
  182.   static void  ClearData()
  183.   {
  184.     memset( Bit.bitmap, 0, Bit.size );
  185.   }
  186.  
  187.  
  188.   static void  ClearSmall()
  189.   {
  190.     memset( Small_Bit.bitmap, 0, Small_Bit.size );
  191.   }
  192.  
  193.   static void CharToUnicode( char* source )
  194.   {
  195.     int i, n;
  196.     short platform, encoding;
  197.  
  198.     /* First, look for a Unicode charmap */
  199.  
  200.     n = TT_Get_CharMap_Count( face );
  201.  
  202.     for ( i = 0; i < n; i++ )
  203.     {
  204.       TT_Get_CharMap_ID( face, i, &platform, &encoding );
  205.       if ( (platform == 3 && encoding == 1 )  ||
  206.            (platform == 0 && encoding == 0 ) )
  207.       {
  208.         TT_Get_CharMap( face, i, &char_map );
  209.         i     = n+1;
  210.       }
  211.     }
  212.  
  213.     if ( i == n )
  214.       Panic( "Sorry, but this font doesn't contain any Unicode mapping table\n" );
  215.  
  216.     for ( n = 0; n < 128 && source[n]; n++ )
  217.       glyph_code[n] = TT_Char_Index( char_map, (short)source[n] );
  218.  
  219.     num_codes = n;
  220.   }
  221.  
  222.  
  223.   static void  ConvData()
  224.   {
  225.     unsigned char*  p;
  226.     int             i;
  227.  
  228.     if ( gray_render )
  229.     {
  230.       p = Bit.bitmap;
  231.       for ( i = 0; i < Bit.size; i++ )
  232.       {
  233.         *p = gray_palette[(int)bounded_palette[*p]];
  234.         p++;
  235.       }
  236.  
  237.     }
  238.   }
  239.  
  240.  
  241.   static TT_Error  Reset_Scale( int  pointSize )
  242.   {
  243.     TT_Error  error;
  244.  
  245.     if ( (error = TT_Set_Instance_PointSize( instance, pointSize )) )
  246.     {
  247.       RestoreScreen();
  248.       Message( "error = %d\n", error );
  249.       Panic( "could not reset instance\n" );
  250.     }
  251.  
  252.     TT_Get_Instance_Metrics( instance, &imetrics );
  253.  
  254.     /* now re-allocates the small bitmap */
  255.  
  256.     if ( gray_render )
  257.     {
  258.       Small_Bit.rows  = imetrics.y_ppem + 32;
  259.       Small_Bit.width = imetrics.x_ppem + 32;
  260.       Small_Bit.cols  = (Small_Bit.width+3) & -4; /* pad */
  261.       Small_Bit.flow  = TT_Flow_Up;
  262.       Small_Bit.size  = Small_Bit.rows * Small_Bit.cols;
  263.  
  264.       if ( Small_Bit.bitmap )
  265.         free( Small_Bit.bitmap );
  266.  
  267.       Small_Bit.bitmap = malloc( (int)Small_Bit.size );
  268.       ClearSmall();
  269.     }
  270.  
  271.     return TT_Err_Ok;
  272.   }
  273.   
  274.  
  275.   static TT_Error  LoadTrueTypeChar( int  idx, int  hint )
  276.   {
  277.     int  flags;
  278.  
  279.     flags = TTLOAD_SCALE_GLYPH;
  280.     if ( hint )
  281.       flags |= TTLOAD_HINT_GLYPH;
  282.  
  283.     return TT_Load_Glyph( instance, glyph, idx, flags );
  284.   }
  285.  
  286.  
  287.   static TT_Error  ConvertRaster( int  x_offset, int  y_offset )
  288.   {
  289.     if ( !gray_render )
  290.       return TT_Get_Glyph_Bitmap( glyph, &Bit, x_offset*64, y_offset*64 );
  291.     else
  292.     {
  293.       TT_Error    error;
  294.       TT_F26Dot6  x, y, xmin, ymin, xmax, ymax;
  295.       int         ioff, iread;
  296.       char        *off, *read, *_off, *_read;
  297.  
  298.       /* grid-fit the bounding box */
  299.  
  300.       xmin =  metrics.xMin & -64;
  301.       ymin =  metrics.yMin & -64;
  302.       xmax = (metrics.xMax + 63) & -64;
  303.       ymax = (metrics.yMax + 63) & -64;
  304.  
  305.       /* now render the glyph in the small pixmap */
  306.  
  307.       ClearSmall();
  308.  
  309.       error = TT_Get_Glyph_Pixmap( glyph, &Small_Bit, -xmin, -ymin );
  310.       if ( error )
  311.         return error;
  312.  
  313.       /* Blit-or the resulting small pixmap into the biggest one */
  314.  
  315.       xmin = xmin/64 + x_offset;
  316.       ymin = ymin/64 + y_offset;
  317.  
  318.       xmax = xmax/64 + x_offset;
  319.       ymax = ymax/64 + y_offset;
  320.  
  321.       /* take care of comparing xmin and ymin with signed values ! */
  322.       /* this was the cause of strange misplacements               */
  323.  
  324.       if ( xmin >= (int)Bit.width ||
  325.            ymin >= (int)Bit.rows  ||
  326.            xmax < 0               ||
  327.            ymax < 0 )
  328.         return TT_Err_Ok;
  329.  
  330.       /* in exotic glyphs, the bounding box maybe larger than the size */
  331.       /* of the small pixmap.. take care of that here                  */
  332.  
  333.       if ( xmax-xmin+1 > Small_Bit.width )
  334.         xmax = xmin + Small_Bit.width-1;
  335.  
  336.       if ( ymax-ymin+1 > Small_Bit.rows )
  337.         ymax = ymin + Small_Bit.rows-1;
  338.  
  339.       /* this got rid of the 'invalid grayshade error' which */
  340.       /* were caused by pixmap overruns..                    */
  341.  
  342.       iread = 0;
  343.       
  344.       if ( ymin < 0 )
  345.       {
  346.     iread -= ymin * Small_Bit.cols;
  347.     ioff   = 0;
  348.         ymin   = 0;
  349.       }
  350.       else
  351.     ioff   = ymin * Bit.cols;
  352.  
  353.       if ( ymax >= Bit.rows )
  354.         ymax = Bit.rows - 1;
  355.  
  356.       if ( xmin < 0 )
  357.       {
  358.         iread -= xmin;
  359.         xmin   = 0;
  360.       }
  361.       else
  362.     ioff  += xmin;
  363.  
  364.       if ( xmax >= Bit.width )
  365.         xmax = Bit.width - 1;
  366.  
  367.       _read = (char*)Small_Bit.bitmap + iread;
  368.       _off  = (char*)Bit.bitmap       + ioff;
  369.  
  370.       for ( y = ymin; y <= ymax; y++ )
  371.       {
  372.         read = _read;
  373.         off  = _off;
  374.  
  375.         for ( x = xmin; x <= xmax; x++ )
  376.     {
  377.       *off |= *read;
  378.       off++;
  379.       read++;
  380.     }
  381.     _read += Small_Bit.cols;
  382.     _off  += Bit.cols;
  383.       }
  384.  
  385.       return TT_Err_Ok;
  386.     }
  387.   }
  388.  
  389.  
  390.   static TT_Error  Render_All()
  391.   {
  392.     TT_F26Dot6  x, y, z, minx, miny, maxx, maxy;
  393.     int         i;
  394.  
  395.     TT_Error    error;
  396.  
  397.     /* On the first pass, we compute the compound bounding box */
  398.  
  399.     x = y = 0;
  400.  
  401.     minx = miny = maxx = maxy = 0;
  402.  
  403.     for ( i=0; i < num_codes; i++ )
  404.     {
  405.       if ( !(error = LoadTrueTypeChar( glyph_code[i], hinted )) )
  406.       {
  407.         TT_Get_Glyph_Metrics( glyph, &metrics );
  408.  
  409.         z = x + metrics.xMin;
  410.         if ( minx > z )
  411.           minx = z;
  412.  
  413.         z = x + metrics.yMax;
  414.         if ( maxx < z )
  415.           maxx = z;
  416.  
  417.         z = y + metrics.yMin;
  418.         if ( miny > z )
  419.           miny = z;
  420.  
  421.         z = y + metrics.yMax;
  422.         if ( maxy < z )
  423.           maxy = z;
  424.  
  425.         x += metrics.advanceWidth & -64;
  426.       }
  427.       else
  428.         Fail++;
  429.     }
  430.  
  431.     /* We now center the bbox inside the target bitmap */
  432.  
  433.     minx = ( minx & -64 ) >> 6;
  434.     miny = ( miny & -64 ) >> 6;
  435.  
  436.     maxx = ( (maxx+63) & -64 ) >> 6;
  437.     maxy = ( (maxy+63) & -64 ) >> 6;
  438.  
  439.     maxx -= minx;
  440.     maxy -= miny;
  441.  
  442.     minx = (Bit.width - maxx)/2;
  443.     miny = (Bit.rows  + miny)/2;
  444.  
  445.     maxx += minx;
  446.     maxy += maxy;
  447.  
  448.     /* On the second pass, we render each glyph to its centered position */
  449.     /* This is slow, because we reload each glyph to render it !         */
  450.  
  451.     x = minx;
  452.     y = miny;
  453.  
  454.     for ( i = 0; i < num_codes; i++ )
  455.     {
  456.       if ( !(error = LoadTrueTypeChar( glyph_code[i], hinted )) )
  457.       {
  458.         TT_Get_Glyph_Metrics( glyph, &metrics );
  459.  
  460.         ConvertRaster( x, y );
  461.  
  462.         x += metrics.advanceWidth/64;
  463.       }
  464.     }
  465.  
  466.     return TT_Err_Ok;
  467.   }
  468.  
  469.  
  470.   static int  Process_Event( TEvent*  event )
  471.   {
  472.     switch ( event->what )
  473.     {
  474.     case event_Quit:            /* ESC or q */
  475.       return 0;
  476.       
  477.     case event_Keyboard:
  478.       if ( event->info == 'n' ) /* Next file */
  479.         return 'n';
  480.       if ( event->info == 'p' ) /* Previous file */
  481.         return 'p';
  482.       if ( event->info == 'h' ) /* Toggle hinting */
  483.         hinted = !hinted;
  484.       break;
  485.       
  486.     case event_Rotate_Glyph:
  487.       Rotation = ( Rotation + event->info ) & 1023;
  488.       break;
  489.  
  490.     case event_Scale_Glyph:
  491.       ptsize += event->info;
  492.       if ( ptsize < 1 )         ptsize = 1;
  493.       if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE;
  494.       break;
  495.  
  496.     case event_Change_Glyph:
  497.       Num += event->info;
  498.       if ( Num < 0 )           Num = 0;
  499.       if ( Num >= num_glyphs ) Num = num_glyphs - 1;
  500.       break;
  501.     }
  502.  
  503.     return 1;
  504.   }
  505.  
  506.  
  507.   static void  usage( char*  execname )
  508.   {
  509.     Message( "\n" );
  510.     Message( "String: simple String Test Display - part of the FreeType project\n" );
  511.     Message( "-----------------------------------------------------------------\n" );
  512.     Message( "\n" );
  513.     Message( "Usage: %s [options below] ppem fontname[.ttf|.ttc] string\n",
  514.              execname );
  515.     Message( "\n" );
  516.     Message( "  -g     gray-level rendering (default: none)\n" );
  517.     Message( "\n" );
  518.  
  519.     exit( 1 );
  520.   }
  521.  
  522.  
  523.   int  main( int  argc, char**  argv ) 
  524.   {
  525.     int    i, old_ptsize, orig_ptsize, file;
  526.     int    XisSetup = 0;
  527.     char   filename[128 + 4];
  528.     char   alt_filename[128 + 4];
  529.     char*  execname;
  530.     int    option;
  531.  
  532.     TT_Error  error;
  533.     TEvent    event;
  534.  
  535.     execname = argv[0];
  536.  
  537.     while ( 1 )
  538.     {
  539.       option = getopt( argc, argv, "gf:r:" );
  540.  
  541.       if ( option == -1 )
  542.         break;
  543.  
  544.       switch ( option )
  545.       {
  546.       case 'g':
  547.         gray_render = 1;
  548.         break;
  549.  
  550.       default:
  551.         usage( execname );
  552.         break;
  553.       }
  554.     }
  555.  
  556.     argc -= optind;
  557.     argv += optind;
  558.  
  559.     if ( argc <= 1 )
  560.       usage( execname );
  561.  
  562.     if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 )
  563.       orig_ptsize = 64;
  564.  
  565.     file = 1;
  566.  
  567.     /* Initialize engine */
  568.  
  569.     if ( (error = TT_Init_FreeType()) )
  570.       Panic( "ERROR: While initializing engine, code = %d\n", error );
  571.  
  572.   NewFile:
  573.     ptsize = orig_ptsize;
  574.     hinted = 1;
  575.  
  576.     i = strlen( argv[file] );
  577.     while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
  578.     {
  579.       if ( argv[file][i] == '.' )
  580.         i = 0;
  581.         i--; 
  582.     }
  583.  
  584.     filename[128] = '\0';
  585.     alt_filename[128] = '\0';
  586.  
  587.     strncpy( filename, argv[file], 128 );
  588.     strncpy( alt_filename, argv[file], 128 );
  589.  
  590.     if ( i >= 0 )
  591.     {
  592.       strncpy( filename + strlen( filename ), ".ttf", 4 );
  593.       strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
  594.     }
  595.  
  596.     /* Load face */
  597.  
  598.     error = TT_Open_Face( filename, &face );
  599.  
  600.     if ( error == TT_Err_Could_Not_Open_File )
  601.     {
  602.       strcpy( filename, alt_filename );
  603.       error = TT_Open_Face( alt_filename, &face );
  604.     }
  605.  
  606.     if ( error )
  607.       Panic( "ERROR: could not find/open %s\n", filename );
  608.  
  609.     /* get face properties and allocate preload arrays */
  610.  
  611.     TT_Get_Face_Properties( face, &properties );
  612.  
  613.     num_glyphs = properties.num_Glyphs;
  614.         
  615.     /* create glyph */
  616.  
  617.     error = TT_New_Glyph( face, &glyph );
  618.     if ( error )
  619.       Panic( "ERROR: could not create glyph container\n" );
  620.  
  621.     /* create instance */
  622.  
  623.     error = TT_New_Instance( face, &instance );
  624.     if ( error )
  625.       Panic( "ERROR: could not create instance for %s\n", filename );
  626.  
  627.     error = TT_Set_Instance_Resolution( instance, 96, 96 );
  628.     if ( error )
  629.       Panic( "ERROR: could not set device resolutions" );
  630.  
  631.     if ( !XisSetup )
  632.     {
  633.       XisSetup = 1;
  634.  
  635.       if ( gray_render ) 
  636.       {
  637.         if ( !SetGraphScreen( Graphics_Mode_Gray ) )
  638.           Panic( "ERROR: could not set up grayscale graphics mode\n" );
  639.  
  640.         TT_Set_Raster_Gray_Palette( palette );
  641.       }
  642.       else
  643.       {
  644.         if ( !SetGraphScreen( Graphics_Mode_Mono ) )
  645.           Panic( "ERROR: could not set up mono graphics mode\n" );
  646.       }
  647.     }
  648.   
  649.     Init_Engine();
  650.  
  651.     Reset_Scale( ptsize );
  652.  
  653.     old_ptsize = ptsize;
  654.  
  655.     Fail = 0;
  656.     Num  = 0;
  657.  
  658.     CharToUnicode( ( argv[2] ? argv[2] :
  659.                      "The quick brown fox jumps over the lazy dog" ) );
  660.  
  661.     for ( ;; )
  662.     {
  663.       int  key;
  664.  
  665.       Render_All();
  666.       ConvData();
  667.  
  668.       sprintf( Header, "%s:   Glyph: %4d  ptsize: %4d  hinting: %s",
  669.                        basename( filename ), Num, ptsize,
  670.                        hinted ? "on" : "off" );
  671. #ifndef X11
  672. #ifndef OS2
  673.       Print_XY( 0, 0, Header );
  674. #endif
  675. #endif
  676.  
  677.       Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols );
  678.  
  679.       ClearData();
  680.  
  681.       Get_Event( &event );
  682.       if ( !( key = Process_Event( &event ) ) ) goto Fin;
  683.  
  684.       if ( key == 'n' )
  685.       {
  686.         TT_Close_Face( face );
  687.  
  688.         if ( file < argc - 1 )
  689.           file++;
  690.  
  691.         goto NewFile;
  692.       }
  693.  
  694.       if ( key == 'p' )
  695.       {
  696.         TT_Close_Face( face );
  697.  
  698.         if ( file > 1 )
  699.           file--;
  700.  
  701.         goto NewFile;
  702.       }
  703.  
  704.       if ( ptsize != old_ptsize )
  705.       {
  706.         if ( Reset_Scale( ptsize ) )
  707.           Panic( "ERROR: could not resize font\n" );
  708.  
  709.         old_ptsize = ptsize;
  710.       }
  711.     }
  712.  
  713.   Fin:
  714.     RestoreScreen();
  715.  
  716.     TT_Done_FreeType();
  717.  
  718.     Message( "execution completed succesfully\n" );
  719.     Message( "fails = %d\n", Fail );
  720.  
  721.     return 0;
  722. }
  723.  
  724.  
  725. /* End */
  726.