home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / test / zoom.c < prev   
C/C++ Source or Header  |  1997-10-06  |  17KB  |  583 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. /*  zoom : A simple glyph viewer.  Now supports graylevel rendering         */
  9. /*         with the '-g' option.                                            */
  10. /*                                                                          */
  11. /*         use -p <platformID> together with -e <encodingID> to select      */
  12. /*         a cmap;                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*  Keys :                                                                  */
  16. /*                                                                          */
  17. /*  x :   fine counter_clockwise rotation                                   */
  18. /*  c :   fine clockwise rotation                                           */
  19. /*                                                                          */
  20. /*  v :   fast counter_clockwise rotation                                   */
  21. /*  b :   fast clockwise rotation                                           */
  22. /*                                                                          */
  23. /*  + :   fast scale up                                                     */
  24. /*  - :   fast scale down                                                   */
  25. /*  u :   fine scale down                                                   */
  26. /*  j :   fine scale up                                                     */
  27. /*                                                                          */
  28. /*  l :   go to next glyph                                                  */
  29. /*  k :   go to previous glyph                                              */
  30. /*                                                                          */
  31. /*  o :   go to tenth next glyph                                            */
  32. /*  i :   go to tenth previous glyph                                        */
  33. /*                                                                          */
  34. /*  0 :   go to hundredth next glyph                                        */
  35. /*  9 :   go to hundredth previous glyph                                    */
  36. /*                                                                          */
  37. /*    q :                                                                   */
  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; which is still in alpha. In no         */
  43. /*         way does it shows the final high-level interface that            */
  44. /*         client applications will use. Wait for at least a beta for       */
  45. /*         this.                                                            */
  46. /*                                                                          */
  47. /****************************************************************************/
  48.  
  49. #ifdef ARM
  50. #include "std.h"
  51. #include "graflink.h"
  52. #endif
  53.  
  54. #include "freetype.h"
  55. #include "tterror.h"  /* for Panic() and Message() only */
  56.  
  57. #include "ft_conf.h"  /* This is needed to have getopt() and getind()     */
  58.                       /* working on Solaris.  We should be able to remove */
  59.                       /* this line on other platforms...                  */
  60.  
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <string.h>
  64. #include <math.h>
  65.  
  66. /* getopt() should be in either getopt.h, stdlib.h, or unistd.h */
  67.  
  68. /* The following is needed before the #include <unistd.h>   */
  69. /* with my school's Suns to have 'getopt' working  - DavidT */
  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.  
  105.   char              Header[128];
  106.  
  107.   TT_Face      face;
  108.   TT_Instance  instance;
  109.   TT_Glyph     org_glyph;   /* original glyph */
  110.   TT_Glyph     glyph;       /* rotated glyph  */
  111.   TT_CharMap   char_map;
  112.  
  113.   TT_Glyph_Metrics     metrics;
  114.   TT_Glyph_Outline     org_outline;  /* original glyph outline */
  115.   TT_Glyph_Outline     outline;      /* rotated glyph oultine  */
  116.   TT_Face_Properties   properties;
  117.   TT_Instance_Metrics  imetrics;
  118.  
  119.   int  num_glyphs;
  120.   int  xcenter_upem;
  121.   int  ycenter_upem;
  122.   int  units_per_em;
  123.  
  124.   int    ptsize;
  125.   int    old_ptsize;
  126.   int    rotation;
  127.   int    old_rotation;
  128.  
  129.   TT_Matrix  matrix;
  130.   int        apply_matrix;
  131.   int        xcenter;
  132.   int        ycenter;
  133.   int        xoffset;
  134.   int        yoffset;
  135.  
  136.   TT_Raster_Map  Bit;
  137.  
  138.   int            Fail;
  139.   int            Num;
  140.   int            Code;
  141.   unsigned char  autorun;
  142.  
  143.   int            gray_render = 0;
  144.   int            hinted = 1;
  145.   int            use_cmap = 0;
  146.  
  147.  
  148.   static void  ClearData( void );
  149.  
  150.   char          palette[5] = { 0, 1, 2, 3, 4 };
  151.  
  152.   void  Init_Raster_Area()
  153.   {
  154.     Bit.rows  = vio_Height;   /* The whole window */
  155.     Bit.width = vio_Width;
  156.     Bit.flow  = TT_Flow_Up;
  157.  
  158.     if ( gray_render )
  159.     {
  160.       Bit.cols  = Bit.width;
  161.       Bit.size  = Bit.rows * Bit.width;
  162.     }
  163.     else
  164.     {
  165.       Bit.cols  = ( Bit.width + 7 ) / 8;    /* convert to # of bytes     */
  166.       Bit.size  = Bit.rows * Bit.cols;      /* number of bytes in buffer */
  167.     }
  168.  
  169.     Bit.bitmap = (void*)malloc( (int)Bit.size );
  170.     if ( !Bit.bitmap )
  171.       Panic( "ERROR: Not enough memory to allocate bitmap!\n" );
  172.  
  173.     ClearData();
  174.   }
  175.   
  176.   static void  ClearData()
  177.   {
  178.     if ( gray_render )
  179.       memset( Bit.bitmap, gray_palette[0], Bit.size );
  180.     else
  181.       memset( Bit.bitmap, 0, Bit.size );
  182.   }
  183.   
  184.  
  185.   static TT_Error  Reset_PtSize( int  pointSize )
  186.   {
  187.     TT_Error  error;
  188.  
  189.     if ( (error = TT_Set_Instance_PointSize( instance, pointSize )) )
  190.     {
  191.       RestoreScreen();
  192.       Message( "error = %d\n", error );
  193.       Panic( "could not reset instance\n" );
  194.     }
  195.  
  196.     TT_Get_Instance_Metrics( instance, &imetrics );
  197.  
  198.     xcenter = imetrics.x_ppem * xcenter_upem / units_per_em / 4;
  199.     ycenter = imetrics.y_ppem * ycenter_upem / units_per_em / 4;
  200.  
  201.     xoffset = vio_Width/2  - xcenter;
  202.     yoffset = vio_Height/2 - ycenter;
  203.  
  204.     return TT_Err_Ok;
  205.   }
  206.  
  207.  
  208.   static void Copy_Outline( TT_Glyph_Outline*  from,
  209.                             TT_Glyph_Outline*  to )
  210.   {
  211.     int n;
  212.  
  213.     to->points   = from->points;
  214.     to->contours = from->contours;
  215.  
  216.     n = from->points * sizeof(TT_F26Dot6 );
  217.  
  218.     memcpy( to->xCoord, from->xCoord, n );
  219.     memcpy( to->yCoord, from->yCoord, n );
  220.     memcpy( to->flag,   from->flag, from->points );
  221.     
  222.     n = from->contours * sizeof(short);
  223.  
  224.     memcpy( to->conStarts, from->conStarts, n );
  225.   }
  226.  
  227.  
  228.   static TT_Error  Reset_Rotation( int  rotation )
  229.   { 
  230.     /* TT_Error  error; */
  231.  
  232.     Copy_Outline( &org_outline, &outline );
  233.  
  234.     if ( rotation )
  235.     {
  236.       float  angle;
  237.  
  238.       /* error = TT_Set_Instance_Transforms( instance, 1, 0 );       */
  239.       /* it seems that rotation support is somehow broken, I'll have */
  240.       /* a finer look at that next week..  - David                   */
  241.  
  242.       angle = rotation * Pi / 512;
  243.  
  244.       matrix.xx = (TT_Fixed) (cos( angle ) * (1<<16));
  245.       matrix.xy = (TT_Fixed) (sin( angle ) * (1<<16));
  246.       matrix.yx = - matrix.xy;
  247.       matrix.yy = matrix.xx;
  248.  
  249.       apply_matrix = 1;
  250.     }
  251.     else
  252.       apply_matrix = 0;
  253.  
  254.     return TT_Err_Ok;
  255.   }
  256.  
  257.   static TT_Error  LoadTrueTypeChar( int  idx, int  hint )
  258.   {
  259.     TT_Error  error;
  260.     int       flags;
  261.  
  262.     flags = TTLOAD_SCALE_GLYPH;
  263.     if ( hint )
  264.       flags |= TTLOAD_HINT_GLYPH;
  265.  
  266.     error = TT_Load_Glyph( instance, glyph, idx, flags );
  267.     if (!error && apply_matrix)
  268.     {
  269.       TT_Get_Glyph_Outline( glyph, &outline );
  270.       TT_Apply_Outline_Translation( &outline, -xcenter*64, -ycenter*64 );
  271.       TT_Apply_Outline_Matrix( &outline, &matrix );
  272.       TT_Apply_Outline_Translation( &outline, xcenter*64, ycenter*64 );
  273.     }
  274.     return error;
  275.   }
  276.  
  277.  
  278.   TT_Error  ConvertRaster()
  279.   {
  280.     if ( gray_render )
  281.       return TT_Get_Glyph_Pixmap( glyph, &Bit, xoffset*64, yoffset*64 );
  282.     else
  283.       return TT_Get_Glyph_Bitmap( glyph, &Bit, xoffset*64, yoffset*64 );
  284.   }
  285.  
  286.  
  287.   int  Process_Event( TEvent*  event )
  288.   {
  289.     switch ( event->what )
  290.     {
  291.     case event_Quit:            /* ESC or q */
  292.       return 0;
  293.       
  294.     case event_Keyboard:
  295.       if ( event->info == 'h' ) /* Toggle hinting */
  296.         hinted = !hinted;
  297.       break;
  298.  
  299.     case event_Rotate_Glyph:
  300.       rotation = ( rotation + event->info ) & 1023;
  301.       break;
  302.  
  303.     case event_Scale_Glyph:
  304.       ptsize += event->info;
  305.       if ( ptsize < 1 )         ptsize = 1;
  306.       if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE;
  307.       break;
  308.  
  309.     case event_Change_Glyph:
  310.       Code += event->info;
  311.       if ( Code < 0 )           Code = 0;
  312.       if ( Code >= num_glyphs ) Code = num_glyphs - 1;
  313.       break;
  314.     }
  315.  
  316.     return 1;
  317.   }
  318.  
  319.  
  320.   void usage( char*  execname )
  321.   {
  322.     Message( "\n" );
  323.     Message( "Zoom: simple TrueType glyph viewer - part of the FreeType project\n" );
  324.     Message( "-----------------------------------------------------------------\n" );
  325.     Message( "\n" );
  326.     Message( "Usage: %s [options below] -fontname[.ttf|.ttc]\n", execname );
  327.     Message( "\n" );
  328.     Message( "  -g       gray-level rendering (default: none)\n" );
  329.     Message( "  -p id    platform id (default: none)\n" );
  330.     Message( "  -e id    encoding id (default: none)\n" );
  331.     Message( "    If either -p or -e is not set, no cmap will be used.\n" );
  332.     Message( "\n" );
  333.  
  334.     exit( 1 );
  335.   }
  336.  
  337.  
  338.   /* stack check dtp */
  339.  
  340.   int  main( int  argc, char**  argv ) 
  341.   {
  342.     int         i, xpos, ypos;
  343.     int         platform = -1, encoding = -1;
  344.     char        filename[128 + 4];
  345.     char        alt_filename[128 + 4];
  346.     char*       execname;
  347.     int         option;
  348.     TT_Error    error;
  349.   
  350.     TEvent  event;
  351.  
  352.     execname    = argv[0];
  353.     gray_render = 0;
  354.  
  355.     while ( 1 )
  356.     {
  357.       option = getopt( argc, argv, "e:gp:" );
  358.  
  359.       if ( option == -1 )
  360.         break;
  361.  
  362.       switch ( option )
  363.       {
  364.       case 'e':
  365.         encoding = atoi( optarg );
  366.         break;
  367.  
  368.       case 'g':
  369.         gray_render = 1;
  370.         break;
  371.  
  372.       case 'p':
  373.         platform = atoi( optarg );
  374.         break;
  375.  
  376.       default:
  377.         usage( execname );
  378.         break;
  379.       }
  380.     }
  381.  
  382.     if ( optind == argc )
  383.       usage( execname );
  384.  
  385.     i = strlen( argv[optind] );
  386.     while ( i > 0 && argv[optind][i] != '\\' && argv[optind][i] != '/' )
  387.     {
  388.       if ( argv[optind][i] == '.' )
  389.         i = 0;
  390.       i--;
  391.     }
  392.  
  393.     filename[128] = '\0';
  394.     alt_filename[128] = '\0';
  395.  
  396.     strncpy( filename, argv[optind], 128 );
  397.     strncpy( alt_filename, argv[optind], 128 );
  398.  
  399.     if ( i >= 0 )
  400.     {
  401.       strncpy( filename + strlen( filename ), ".ttf", 4 );
  402.       strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
  403.     }
  404.  
  405.     if ( platform >= 0 || encoding >= 0 )
  406.       use_cmap = 1;
  407.  
  408.     /* Initialization */
  409.     TT_Init_FreeType();
  410.  
  411.     /* Load face */
  412.  
  413.     error = TT_Open_Face( filename, &face );
  414.  
  415.     if ( error == TT_Err_Could_Not_Open_File )
  416.     {
  417.       strcpy( filename, alt_filename );
  418.       error = TT_Open_Face( alt_filename, &face );
  419.     }
  420.  
  421.     if ( error )
  422.       Panic( "ERROR: could not find/open %s\n", filename );
  423.  
  424.     /* get face properties and allocate preload arrays */
  425.  
  426.     TT_Get_Face_Properties( face, &properties );
  427.  
  428.     num_glyphs   = properties.num_Glyphs;
  429.     xcenter_upem = (properties.header->xMax - properties.header->xMin) / 2;
  430.     ycenter_upem = (properties.header->yMax - properties.header->yMin) / 2;
  431.     units_per_em = properties.header->Units_Per_EM;
  432.  
  433.     /* create glyph */
  434.  
  435.     error = TT_New_Glyph( face, &org_glyph );
  436.     if ( error )
  437.       Panic( "ERROR: could not create glyph container\n" );
  438.  
  439.     error = TT_New_Glyph( face, &glyph );
  440.     if ( error )
  441.       Panic( "ERROR: could not create glyph container\n" );
  442.  
  443.     /* create instance */
  444.  
  445.     error = TT_New_Instance( face, &instance );
  446.     if ( error )
  447.       Panic( "ERROR: could not create instance for %s\n", filename );
  448.  
  449.     error = TT_Set_Instance_Resolution( instance, 96, 96 );
  450.     if ( error )
  451.       Panic( "ERROR: could not set device resolutions" );
  452.  
  453.     if ( gray_render )
  454.     {
  455.       if ( !SetGraphScreen( Graphics_Mode_Gray ) )
  456.         Panic( "ERROR: could not set up grayscale graphics mode\n" );
  457.  
  458.       TT_Set_Raster_Gray_Palette( gray_palette );
  459.     }
  460.     else
  461.     {
  462.       if ( !SetGraphScreen( Graphics_Mode_Mono ) )
  463.         Panic( "ERROR: could not set up mono graphics mode\n" );
  464.     }
  465.  
  466.     Init_Raster_Area();
  467.  
  468.     old_ptsize   = ptsize   = 150;
  469.     old_rotation = rotation = 0;
  470.  
  471.     Reset_PtSize  ( ptsize );
  472.     Reset_Rotation( rotation );
  473.  
  474.     if ( use_cmap )
  475.     {
  476.       int    num_cmap;
  477.       short  cmap_plat;
  478.       short  cmap_enc;
  479.  
  480.       num_cmap = TT_Get_CharMap_Count( face );
  481.       for ( i = 0; i < num_cmap; i++ )
  482.       {
  483.         error = TT_Get_CharMap_ID( face, i, &cmap_plat, &cmap_enc );
  484.         if ( error )
  485.           Panic( "ERROR: cannot query cmap, error=%d\n", error );
  486.         if ( cmap_plat == platform && cmap_enc == encoding )
  487.           break;
  488.       }
  489.  
  490.       if ( i == num_cmap )
  491.         Panic( "ERROR: invalid platform and/or encoding ID\n" );
  492.  
  493.       error = TT_Get_CharMap( face, i, &char_map );
  494.       if ( error )
  495.         Panic( "ERROR: cannot load cmap, error=%d\n", error );
  496.  
  497.       num_glyphs = 1<<16;
  498.     }
  499.  
  500.     Code     = 0;
  501.     autorun  = 0;
  502.     Fail     = 0;
  503.     xpos     = 0;
  504.     ypos     = 0;
  505.  
  506.     for ( ;; )
  507.     {
  508.       ClearData();
  509.  
  510.       if ( ptsize != old_ptsize )
  511.       {
  512.     Reset_PtSize( ptsize );
  513.     old_ptsize = ptsize;
  514.       }
  515.  
  516.       if ( rotation != old_rotation )
  517.       {
  518.     Reset_Rotation( rotation );
  519.     old_rotation = rotation;
  520.       }
  521.  
  522.       if ( use_cmap )
  523.         Num = TT_Char_Index( char_map, Code );
  524.       else
  525.         Num = Code;
  526.  
  527.       if ( (error = LoadTrueTypeChar( Num, hinted )) == TT_Err_Ok )
  528.       {
  529.         ConvertRaster();
  530.         sprintf( Header, "glyph index = %3d, char code = 0x%x",
  531.                  Num, Code );
  532.       }
  533.       else {
  534.         Fail++;
  535.         sprintf( Header, "glyph index = %3d, (ERROR) %x",
  536.                  Num, error );
  537.       }
  538.  
  539.       Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols ); 
  540. #ifndef X11
  541. #ifndef OS2
  542.       Print_XY( 20, 0, Header );
  543. #endif
  544. #endif
  545.  
  546. #if 0
  547.       if ( autorun )
  548.       {
  549.         xpos += cur_AdvanceWidth;
  550.         if ( xpos + cur_AdvanceWidth > 640 )
  551.         {
  552.           xpos = 0;
  553.           ypos += ( cur_Ascent - cur_Descent ) / 64;
  554.           /* is == TRUETYPE DEFINED Precision */
  555.         }
  556.  
  557.         Num = autorun++;
  558.         if( !autorun )
  559.         {
  560.           xpos = 0;
  561.           ypos += ( cur_Ascent - cur_Descent ) / 64;
  562.           /* is == TRUETYPE DEFINED Precision */
  563.         }
  564.       }
  565.       else
  566. #endif
  567.       {
  568.         Get_Event( &event );
  569.         if ( !Process_Event( &event ) ) goto Fin;
  570.       }
  571.     }
  572.  
  573.   Fin:
  574.  
  575.     RestoreScreen();
  576.  
  577.     TT_Done_FreeType();
  578.  
  579.     Message( "fails = %d\n", Fail );
  580.  
  581.     return 0;
  582.   }
  583.