/****************************************************************************/
/*                                                                          */
/*  The FreeType project -- a free and portable quality TrueType renderer.  */
/*                                                                          */
/*  Copyright 1996, 1997 by                                                 */
/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
/*                                                                          */
/*  ftdump : Simple TrueType font file resource profiler                    */
/*                                                                          */
/*  This program dumps various properties of a given font file              */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*  NOTE:  This is just a test program that is used to show off and         */
/*         debug the current engine; which is still in alpha.               */
/*                                                                          */
/****************************************************************************/

#ifdef ARM
#include "std.h"
#include "graflink.h"
#endif

#include "freetype.h"
#include "tterror.h"  /* for Panic() */

#include "ttobjs.h"   /* We're going to access internal tables directly */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef ARM
#include "armsup.c" /* pull in our routines */
#endif

  TT_Error     error;

  TT_Engine    engine;
  TT_Face      face;
  TT_Instance  instance;
  TT_Glyph     glyph;

  TT_Instance_Metrics  imetrics;
  TT_Outline           outline;
  TT_Glyph_Metrics     metrics;

  TT_Face_Properties   properties;

  TT_CharMap    cmap;

  int  num_glyphs;
  int  ptsize;

  int  Fail;
  int  Num;


  int  flag_memory    = 1;
  int  flag_names     = 1;
  int  flag_encodings = 1;

extern long TTMemory_Allocated;

long   org_memory, old_memory, cur_memory;
  
  const char* Apple_Encodings[33] =
  {
    "Roman", "Japanese", "Chinese", "Korean", "Arabic", "Hebrew",
    "Greek", "Russian", "RSymbol", "Devanagari", "Gurmukhi",
    "Gujarati", "Oriya", "Bengali", "Tamil", "Belugu", "Kannada",
    "Malayalam", "Sinhalese", "Burmese", "Khmer", "Tai", "Laotian",
    "Georgian", "Armenian", "Maldivian", "Tibetan", "Mongolian",
    "Geez", "Slavic", "Vietnamese", "Sindhi", "Uninterp"
  };

  struct
  {
    long  initial_overhead;
    long  face_object;
    long  glyph_object;
    long  first_instance;
    long  second_instance;

  } memory_footprint;


  void  Save_Memory( long* var )
  {
    *var = TTMemory_Allocated - old_memory;
    old_memory += *var;
  }

  #define FOOTPRINT(field)  Save_Memory( &memory_footprint.##field )

  static void  
  Print_Mem( long val, char* string )
  {
    Message( "%6d bytes (%4d Kb) :  %s\n",
             val,
             (val+1023)/1024,
             string );
  }

  #define PRINT_MEM(field,string)  \
            Print_Mem( memory_footprint.##field, string )


  /* Print the memory footprint */

  void  Print_Memory()
  {
    /* create glyph */
    error = TT_New_Glyph( face, &glyph );
    if ( error )
      Panic( "ERROR: could not create glyph container\n" );

    FOOTPRINT(glyph_object);

    /* create instance */
    error = TT_New_Instance( face, &instance );
    if ( error )
      Panic( "ERROR: could not create instance\n" );

    FOOTPRINT(first_instance);

    error = TT_New_Instance( face, &instance );
    if ( error )
      Panic( "ERROR: could not create 2nd instance" );

    FOOTPRINT(second_instance);

    Message( "Memory footprint statistics :\n" );
    Message( "-----------------------------------------------\n" );

    /* NOTE : In our current implementation, the face's execution */
    /*        context object is created lazily with the first     */
    /*        instance. However, all later instances share the    */
    /*        the same context..                                  */

    PRINT_MEM(face_object,     "face object"     );
    PRINT_MEM(glyph_object,    "glyph_object"    );
    PRINT_MEM(second_instance, "instance object" );

    Print_Mem( memory_footprint.first_instance - 
               memory_footprint.second_instance, "exec. context object" );

    Message( "-----------------------------------------------\n" );
    Print_Mem( memory_footprint.face_object    +
               memory_footprint.glyph_object   +
               memory_footprint.first_instance,
               "total memory use" );

    Message( "\n" );
  }

  static  char  name_buffer[257];
  static  int   name_len = 0;


  static char*  LookUp_Name( int index )
  {
    int i, j, n;

    short  platform, encoding, language, id;
    char*  string;
    int    string_len;

    int    found;

    n = TT_Get_Name_Count( face );
    if ( n < 0 )
      return NULL;

    for ( i = 0; i < n; i++ )
    {
      TT_Get_Name_ID( face, i, &platform, &encoding, &language, &id );
      TT_Get_Name_String( face, i, &string, &string_len );

      if ( id == index )
      {

   /* The following code was inspired from Mark Leisher's ttf2bdf package */

        found = 0;

        /* Try to find a Microsoft English name */

        if ( platform == 3 )
          for ( j = 1; j >= 0; j-- )
            if ( encoding == j )  /* Microsoft ? */
              switch (language)
              {
                case 0x409:
                case 0x809:
                case 0xc09:
                case 0x1009:
                case 0x1409:
                case 0x1809: found = 1;
                             break;
              }

        if ( !found && platform == 0 && language == 0 )
          found = 1;

        /*   
         * Found a Unicode Name.                                       
         */
        if (found)
        {
          if ( string_len > 512 )
            string_len = 512;
  
          name_len = 0;
  
          for ( i = 1; i < string_len; i += 2 ) 
            name_buffer[name_len++] = string[i];
  
          name_buffer[name_len] = '\0';
  
          return name_buffer;
        }
      }
    }

    /* Not found */
    return NULL;
  }


  static void 
  Print_Names()
  {
     Message( "font name table entries\n" );
     Message( "-----------------------------------------------\n" );

     if ( LookUp_Name( 4 ) )
       Message( "%s - ", name_buffer );

     if ( LookUp_Name( 5 ) )
       Message( "%s\n\n", name_buffer );

     if ( LookUp_Name( 0 ) )
       Message( "%s\n\n", name_buffer );

     if ( LookUp_Name( 7 ) )
       Message( name_buffer );

     Message( "\n" );
     Message( "-----------------------------------------------\n\n" );
  }


  static void
  Print_Encodings()
  {
     int n, i;
     short platform, encoding;
     char  *platStr, *encoStr;

     char  tempStr[128];

     Message( "character map encodings\n" );
     Message( "-----------------------------------------------\n" );

     n = TT_Get_CharMap_Count( face );
     if ( n < 0 )
     {
       Message( "The file doesn't seem to have any encoding table\n" );
       return;
     }

     Message( "There are %d encodings :\n\n", n );

     for ( i = 0; i < n; i++ )
     {
       TT_Get_CharMap_ID( face, i, &platform, &encoding );
       Message( "encoding %2d : ", i );

       platStr = encoStr = NULL;

       switch (platform)
       {
         case 0 :  platStr = "Apple";
                   encoStr = "Unicode";
                   break;

         case 1 :  platStr = "Apple";
                   if (encoding < 0 || encoding > 32)
                   {
                     sprintf( tempStr, "Unknown %d", encoding );
                     encoStr = tempStr;
                   }
                   else
                     encoStr = (char*)Apple_Encodings[encoding];
                   break;

         case 2 : platStr = "Iso";
                  switch (encoding)
                  {
                    case 0 : platStr = "Ascii";
                             encoStr = "7-bit";
                             break;

                    case 1 : encoStr = "10646";
                             break;

                    case 2 : encoStr = "8859-1";
                             break;

                    default: sprintf( tempStr, "%d", encoding );
                             encoStr = tempStr;
                  }
                  break;

         case 3 : platStr = "Windows";
                  switch (encoding)
                  {
                    case 0: encoStr = "Symbol";
                            break;

                    case 1: encoStr = "Unicode";
                            break;

                    case 4: encoStr = "WGL4";
                            break;

                    default: sprintf( tempStr, "unknown %d", encoding );
                             encoStr = tempStr;
                  }
                  break;

         default: sprintf( tempStr, "%d - %d", platform, encoding );
                  platStr = "Unknown";
                  encoStr = tempStr;
       }

       Message( "%s %s\n", platStr, encoStr );
     }

     Message( "\n" );
     Message( "-----------------------------------------------\n\n" );
  }


  int  main( int  argc, char**  argv ) 
  {
    int    i;
    char   filename[128 + 4];
    char   alt_filename[128 + 4];
    char*  execname;

    execname = argv[0];

    if ( argc != 2 )
    {
      Message( "ftdump: simple TrueType Dumper - part of the FreeType project\n" );
      Message( "-------------------------------------------------------------\n\n" );
      Message( "Usage: %s fontname[.ttf|.ttc]\n\n", execname );
      exit( 1 );
    }

    i = strlen( argv[1] );
    while ( i > 0 && argv[1][i] != '\\' )
    {
      if ( argv[1][i] == '.' )
        i = 0;
      i--;
    }

    filename[128] = '\0';
    alt_filename[128] = '\0';

    strncpy( filename, argv[1], 128 );
    strncpy( alt_filename, argv[1], 128 );

    if ( i >= 0 )
    {
      strncpy( filename + strlen( filename ), ".ttf", 4 );
      strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
    }

    /* Initialize engine */

    old_memory = 0;

    if ( (error = TT_Init_FreeType( &engine )) )
      Panic( "ERROR: While initializing engine, code = %d\n", error );

    FOOTPRINT(initial_overhead);
  
    /* Open and Load face */
  
    error = TT_Open_Face( engine, filename, &face );

    if (error == TT_Err_Could_Not_Open_File)
    {
      strcpy( filename, alt_filename );
      error = TT_Open_Face( engine, alt_filename, &face );
    }

    if ( error )
      Panic( "ERROR: could not find/open %s\n", filename );

    FOOTPRINT(face_object);

    /* get face properties and allocate preload arrays */

    TT_Get_Face_Properties( face, &properties );
    num_glyphs = properties.num_Glyphs;

    /* Now do various dumps */

    if (flag_names)
      Print_Names();

    if (flag_encodings)
      Print_Encodings();

    if (flag_memory)
      Print_Memory();
        
    TT_Close_Face( face );

    TT_Done_FreeType( engine );

    return 0;
}


/* End */
