shithub: freetype+ttf2subf

Download patch

ref: 241e151eb2e97d01734d8f52693b404943b3a765
parent: 2e421319fc4bedef44218fc144b1186ea53df584
author: David Turner <[email protected]>
date: Sun May 28 13:15:37 EDT 2000

oops, forgot to commit these files

git/fs: mount .git/fs: mount/attach disallowed
--- /dev/null
+++ b/demos/src/ftmulti.c
@@ -1,0 +1,809 @@
+/****************************************************************************/
+/*                                                                          */
+/*  The FreeType project -- a free and portable quality TrueType renderer.  */
+/*                                                                          */
+/*  Copyright 1996-1999 by                                                  */
+/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
+/*                                                                          */
+/*                                                                          */
+/*  FTMulti- a simple multiple masters font viewer                          */
+/*                                                                          */
+/*  Press F1 when running this program to have a list of key-bindings       */
+/*                                                                          */
+/****************************************************************************/
+
+#include <freetype/freetype.h>
+#include <freetype/ftraster.h>
+#include <freetype/ftgrays.h>
+#include <freetype/ftmm.h>
+
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "graph.h"
+#include "grfont.h"
+
+#define  DIM_X   500
+#define  DIM_Y   400
+
+#define  CENTER_X   (bit.width/2)
+#define  CENTER_Y   (bit.rows/2)
+
+#define  MAXPTSIZE  500                 /* dtp */
+
+  char  Header[128];
+  char* new_header = 0;
+
+  const unsigned char*  Text = (unsigned char*)
+"The quick brown fox jumped over the lazy dog 0123456789 \
+\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 \
+&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ \
+$\243^\250*\265\371%!\247:/;.,?<>";
+  FT_Library    library;      /* the FreeType library            */
+  FT_Face       face;         /* the font face                   */
+  FT_Size       size;         /* the font size                   */
+  FT_GlyphSlot  glyph;        /* the glyph slot                  */
+
+  FT_Error      error;        /* error returned by FreeType ?    */
+
+  grSurface*     surface;     /* current display surface         */
+  grBitmap       bit;         /* current display bitmap          */
+
+  int  num_glyphs;            /* number of glyphs */
+  int  ptsize;                /* current point size */
+
+  int  hinted      = 1;       /* is glyph hinting active ?    */
+  int  antialias   = 1;       /* is anti-aliasing active ?    */
+  int  use_sbits   = 1;       /* do we use embedded bitmaps ? */
+  int  low_prec    = 0;       /* force low precision          */
+  int  Num;                   /* current first glyph index    */
+
+  int    res = 72;
+
+  static grColor  fore_color = { 255 };
+
+  int            Fail;
+  unsigned char  autorun;
+
+  int  graph_init = 0;
+
+  int  render_mode = 1;
+  int  use_grays   = 1;
+
+  /* the standard raster's interface */
+  FT_Raster_Funcs  std_raster;
+
+  FT_Multi_Master  multimaster;
+  FT_Long          design_pos[ T1_MAX_MM_AXIS ];
+
+#define RASTER_BUFF_SIZE   32768
+  char     raster_buff[ RASTER_BUFF_SIZE ];
+
+#define DEBUGxxx
+
+#ifdef DEBUG
+#define LOG(x)  LogMessage##x
+#else
+#define LOG(x)  /* rien */
+#endif
+
+#ifdef DEBUG
+  static void  LogMessage( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+    va_start( ap, fmt );
+    vfprintf( stderr, fmt, ap );
+    va_end( ap );
+  }
+#endif
+
+  /* PanicZ */
+  static void PanicZ( const char* message )
+  {
+    fprintf( stderr, "%s\n  error = 0x%04x\n", message, error );
+    exit(1);
+  }
+
+
+  /* Clears the Bit bitmap/pixmap */
+  static void  Clear_Display( void )
+  {
+    long  size = (long)bit.pitch * bit.rows;
+
+    if (size < 0) size = -size;
+    memset( bit.buffer, 0, size );
+  }
+
+
+  /* Initialize the display bitmap named Bit */
+  static int  Init_Display()
+  {
+    grInitDevices();
+
+    bit.mode   = gr_pixel_mode_gray;
+    bit.width  = DIM_X;
+    bit.rows   = DIM_Y;
+    bit.grays  = 256;
+
+    surface = grNewSurface( 0, &bit );
+    if (!surface)
+      PanicZ( "could not allocate display surface\n" );
+
+    graph_init = 1;
+    return 0;
+  }
+
+
+#define MAX_BUFFER  300000
+
+#define FLOOR(x)  ((x) & -64)
+#define CEIL(x)   (((x)+63) & -64)
+#define TRUNC(x)  ((x) >> 6)
+
+  static
+  char   bit_buffer[ MAX_BUFFER ];
+
+  /* Render a single glyph with the "grays" component */
+  static FT_Error  Render_Glyph( int  x_offset,
+                                 int  y_offset )
+  {
+    /* first, render the glyph into an intermediate buffer */
+    FT_Bitmap  bit2;
+    grBitmap   bit3;
+    int        width, height, pitch, size;
+    int        left, right, top, bottom;
+    int        x_top, y_top;
+
+    left  = FLOOR( glyph->metrics.horiBearingX );
+    right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
+    width = TRUNC(right - left);
+
+    top    = CEIL( glyph->metrics.horiBearingY );
+    bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
+    height = TRUNC( top - bottom );
+
+    if ( glyph->format == ft_glyph_format_outline )
+    {
+      pitch  = ( antialias ? (width+3) & -4 : (width+7) >> 3 );
+      size   = pitch*height;
+
+      if (size > MAX_BUFFER)
+        return FT_Err_Out_Of_Memory;
+
+      bit2.width      = width;
+      bit2.rows       = height;
+      bit2.pitch      = pitch;
+      bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
+      bit2.buffer     = bit_buffer;
+
+      bit3.rows   = bit2.rows;
+      bit3.width  = bit2.width;
+      bit3.pitch  = bit2.pitch;
+      bit3.mode   = antialias ? bit.mode : gr_pixel_mode_mono;
+      bit3.buffer = bit_buffer;
+      bit3.grays  = 256;
+
+      FT_Outline_Translate( &glyph->outline, -left, -bottom );
+      memset( bit_buffer, 0, size );
+
+      if (low_prec)
+        glyph->outline.flags &= ~ft_outline_high_precision;
+
+      error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 );
+    }
+    else
+    {
+      bit3.rows   = glyph->bitmap.rows;
+      bit3.width  = glyph->bitmap.width;
+      bit3.pitch  = glyph->bitmap.pitch;
+      bit3.mode   = gr_pixel_mode_mono;
+      bit3.buffer = glyph->bitmap.buffer;
+      bit3.grays  = 0;
+    }
+
+    /* Then, blit the image to the target surface */
+    x_top = x_offset + TRUNC(left);
+    y_top = y_offset - TRUNC(top);
+
+/*
+    if (bit.pitch < 0)
+      y_top = bit.rows - y_top;
+*/
+    grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
+    return 0;
+  }
+
+  static FT_Error  Reset_Scale( int  pointSize )
+  {
+    FT_Error  error;
+
+    error = FT_Set_Char_Size( face, pointSize << 6,
+                                    pointSize << 6,
+                                    res,
+                                    res );
+    if ( error )
+    {
+    }
+    return FT_Err_Ok;
+  }
+
+
+  static FT_Error  LoadChar( int  idx, int  hint )
+  {
+    int  flags;
+
+    flags = FT_LOAD_DEFAULT;
+
+    if ( !hint )
+      flags |= FT_LOAD_NO_HINTING;
+
+    if ( !use_sbits )
+      flags |= FT_LOAD_NO_BITMAP;
+
+    return FT_Load_Glyph( face, idx, flags );
+  }
+
+
+
+  static FT_Error  Render_All( int  first_glyph, int  ptsize )
+  {
+    FT_F26Dot6  start_x, start_y, step_x, step_y, x, y;
+    int         i;
+
+    FT_Error    error;
+
+    start_x = 4;
+    start_y = 36 + ptsize ;
+
+    step_x = size->metrics.x_ppem + 4;
+    step_y = size->metrics.y_ppem + 10;
+
+    x = start_x;
+    y = start_y;
+
+    i = first_glyph;
+
+#if 0
+     while ( i < first_glyph+1 )
+#else
+     while ( i < num_glyphs )
+#endif
+    {
+      if ( !(error = LoadChar( i, hinted )) )
+      {
+        #ifdef DEBUG
+        if (i <= first_glyph+6)
+        {
+          LOG(( "metrics[%02d] = [%x %x]\n",
+                i,
+                glyph->metrics.horiBearingX,
+                glyph->metrics.horiAdvance ));
+
+          if (i == first_glyph+6)
+          LOG(( "-------------------------\n"));
+        }
+        #endif
+
+        Render_Glyph( x, y );
+
+        x += ( glyph->metrics.horiAdvance >> 6 ) + 1;
+
+        if ( x + size->metrics.x_ppem > bit.width )
+        {
+          x  = start_x;
+          y += step_y;
+
+          if ( y >= bit.rows )
+            return FT_Err_Ok;
+        }
+      }
+      else
+        Fail++;
+
+      i++;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  static FT_Error  Render_Text( int  first_glyph, int  ptsize )
+  {
+    FT_F26Dot6  start_x, start_y, step_x, step_y, x, y;
+    int         i;
+
+    FT_Error             error;
+    const unsigned char* p;
+
+    start_x = 4;
+    start_y = 32 + size->metrics.y_ppem;
+
+    step_x = size->metrics.x_ppem + 4;
+    step_y = size->metrics.y_ppem + 10;
+
+    x = start_x;
+    y = start_y;
+
+    i = first_glyph;
+    p = Text;
+    while (i > 0 && *p) { p++; i--; }
+
+    while ( *p )
+    {
+      if ( !(error = LoadChar( FT_Get_Char_Index( face, (unsigned char)*p ), hinted )) )
+      {
+        #ifdef DEBUG
+        if (i <= first_glyph+6)
+        {
+          LOG(( "metrics[%02d] = [%x %x]\n",
+                i,
+                glyph->metrics.horiBearingX,
+                glyph->metrics.horiAdvance ));
+
+          if (i == first_glyph+6)
+          LOG(( "-------------------------\n"));
+        }
+        #endif
+
+        Render_Glyph( x, y );
+
+        x += ( glyph->metrics.horiAdvance >> 6 ) + 1;
+
+        if ( x + size->metrics.x_ppem > bit.width )
+        {
+          x  = start_x;
+          y += step_y;
+
+          if ( y >= bit.rows )
+            return FT_Err_Ok;
+        }
+      }
+      else
+        Fail++;
+
+      i++;
+      p++;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  static void Help( )
+  {
+    grEvent  dummy_event;
+
+    Clear_Display();
+    grGotoxy( 0, 0 );
+    grSetMargin( 2, 1 );
+    grGotobitmap( &bit );
+
+    grWriteln("FreeType Glyph Viewer - part of the FreeType test suite" );
+    grLn();
+    grWriteln("This program is used to display all glyphs from one or" );
+    grWriteln("several font files, with the FreeType library.");
+    grLn();
+    grWriteln("Use the following keys :");
+    grLn();
+    grWriteln("  F1 or ?   : display this help screen" );
+    grWriteln("  a         : toggle anti-aliasing" );
+    grWriteln("  h         : toggle outline hinting" );
+    grWriteln("  b         : toggle embedded bitmaps" );
+    grWriteln("  l         : toggle low precision rendering" );
+    grWriteln("  g         : toggle between 'smooth' and 'standard' anti-aliaser" );
+    grWriteln("  space     : toggle rendering mode" );
+    grLn();
+    grWriteln("  Up        : increase pointsize by 1 unit" );
+    grWriteln("  Down      : decrease pointsize by 1 unit" );
+    grWriteln("  Page Up   : increase pointsize by 10 units" );
+    grWriteln("  Page Down : decrease pointsize by 10 units" );
+    grLn();
+    grWriteln("  Right     : increment first glyph index" );
+    grWriteln("  Left      : decrement first glyph index" );
+    grLn();
+    grWriteln("  F3        : decrement first axis position by 20" );
+    grWriteln("  F4        : increment first axis position by 20" );
+    grWriteln("  F3        : decrement second axis position by 20" );
+    grWriteln("  F4        : increment second axis position by 20" );
+    grWriteln("  F3        : decrement third axis position by 20" );
+    grWriteln("  F4        : increment third axis position by 20" );
+    grLn();
+    grWriteln("press any key to exit this help screen");
+
+    grRefreshSurface( surface );
+    grListenSurface( surface, gr_event_key, &dummy_event );
+  }
+
+  static void  reset_raster( void )
+  {
+    if ( antialias && use_grays )
+      FT_Set_Raster( library, &ft_grays_raster );
+    else
+      FT_Set_Raster( library, &std_raster );
+  }
+
+
+  static int  Process_Event( grEvent*  event )
+  {
+    int  i, axis;
+
+    switch ( event->key )
+    {
+    case grKeyEsc:            /* ESC or q */
+    case grKEY('q'):
+      return 0;
+
+    case grKEY('a'):
+      antialias = !antialias;
+      new_header = ( antialias
+                   ? "anti-aliasing is now on"
+                   : "anti-aliasing is now off" );
+      reset_raster();
+      return 1;
+
+    case grKEY('b'):
+      use_sbits  = !use_sbits;
+      new_header = ( use_sbits
+                   ? "embedded bitmaps are now used when available"
+                   : "embedded bitmaps are now ignored" );
+      return 1;
+
+    case grKEY('n'):
+    case grKEY('p'):
+      return (int)event->key;
+
+    case grKEY('g'):
+      use_grays = !use_grays;
+      new_header = ( use_grays
+                   ? "now using the smooth anti-aliaser"
+                   : "now using the standard anti-aliaser" );
+      reset_raster();
+      break;
+
+    case grKEY('l'):
+      low_prec = !low_prec;
+      new_header = ( low_prec
+                   ? "rendering precision is now forced to low"
+                   : "rendering precision is now normal" );
+      break;
+
+    case grKEY('h'):
+      hinted = !hinted;
+      new_header = ( hinted
+                   ? "glyph hinting is now active"
+                   : "glyph hinting is now ignored" );
+      break;
+
+    case grKEY(' '):
+      render_mode ^= 1;
+      new_header = ( render_mode
+                   ? "rendering all glyphs in font"
+                   : "rendering test text string" );
+      break;
+
+    case grKeyF1:
+    case grKEY('?'):
+      Help();
+      return 1;
+
+    case grKeyF3:  i = -20; axis = 0; goto Do_Axis;
+    case grKeyF4:  i =  20; axis = 0; goto Do_Axis;
+    case grKeyF5:  i = -20; axis = 1; goto Do_Axis;
+    case grKeyF6:  i =  20; axis = 1; goto Do_Axis;
+    case grKeyF7:  i = -20; axis = 2; goto Do_Axis;
+    case grKeyF8:  i =  20; axis = 2; goto Do_Axis;
+
+    case grKeyPageUp:   i =  10; goto Do_Scale;
+    case grKeyPageDown: i = -10; goto Do_Scale;
+    case grKeyUp:       i =   1; goto Do_Scale;
+    case grKeyDown:     i =  -1; goto Do_Scale;
+
+    case grKeyLeft:  i =  -1; goto Do_Glyph;
+    case grKeyRight: i =   1; goto Do_Glyph;
+    case grKeyF9:    i = -100; goto Do_Glyph;
+    case grKeyF10:   i =  100; goto Do_Glyph;
+    case grKeyF11:   i = -1000; goto Do_Glyph;
+    case grKeyF12:   i =  1000; goto Do_Glyph;
+    default:
+      ;
+    }
+    return 1;
+
+  Do_Axis:
+    if (axis < multimaster.num_axis)
+    {
+      FT_MM_Axis*  a = multimaster.axis + axis;
+      FT_Long      pos = design_pos[axis];
+      
+      pos += i;
+      if (pos < a->minimum)  pos = a->minimum;
+      if (pos > a->maximum)  pos = a->maximum;
+      
+      design_pos[axis] = pos;
+      
+      FT_Set_MM_Design_Coordinates( face, multimaster.num_axis, design_pos );
+    }
+    return 1;
+
+  Do_Scale:
+    ptsize += i;
+    if (ptsize < 1)         ptsize = 1;
+    if (ptsize > MAXPTSIZE) ptsize = MAXPTSIZE;
+    return 1;
+
+  Do_Glyph:
+    Num += i;
+    if (Num < 0)           Num = 0;
+    if (Num >= num_glyphs) Num = num_glyphs-1;
+    return 1;
+  }
+
+
+
+  static void  usage( char*  execname )
+  {
+    fprintf( stderr,  "\n" );
+    fprintf( stderr,  "ftmulti: multiple masters font viewer - part of FreeType\n" );
+    fprintf( stderr,  "--------------------------------------------------------\n" );
+    fprintf( stderr,  "\n" );
+    fprintf( stderr,  "Usage: %s [options below] ppem fontname[.ttf|.ttc] ...\n",
+             execname );
+    fprintf( stderr,  "\n" );
+    fprintf( stderr,  "  -r R      use resolution R dpi (default: 72 dpi)\n" );
+    fprintf( stderr,  "  -f index  specify first glyph index to display\n" );
+    fprintf( stderr,  "\n" );
+
+    exit( 1 );
+  }
+
+
+  int  main( int  argc, char**  argv )
+  {
+    int    i, old_ptsize, orig_ptsize, file;
+    int    first_glyph = 0;
+    int    XisSetup = 0;
+    char   filename[128 + 4];
+    char   alt_filename[128 + 4];
+    char*  execname;
+    int    option;
+    int    file_loaded;
+
+    FT_Error  error;
+    grEvent   event;
+
+    execname = ft_basename( argv[0] );
+
+    while ( 1 )
+    {
+      option = getopt( argc, argv, "f:r:" );
+
+      if ( option == -1 )
+        break;
+
+      switch ( option )
+      {
+      case 'f':
+        first_glyph = atoi( optarg );
+        break;
+
+      case 'r':
+        res = atoi( optarg );
+        if ( res < 1 )
+          usage( execname );
+        break;
+
+      default:
+        usage( execname );
+        break;
+      }
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if ( argc <= 1 )
+      usage( execname );
+
+    if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 )
+      orig_ptsize = 64;
+
+    file = 1;
+
+    /* Initialize engine */
+    error = FT_Init_FreeType( &library );
+    if (error) PanicZ( "Could not initialise FreeType library" );
+
+    /* retrieve the standard raster's interface */
+    (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster );
+    reset_raster();
+
+  NewFile:
+    ptsize      = orig_ptsize;
+    hinted      = 1;
+    file_loaded = 0;
+
+#ifndef macintosh
+    i = strlen( argv[file] );
+    while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
+    {
+      if ( argv[file][i] == '.' )
+        i = 0;
+      i--;
+    }
+#endif
+
+    filename[128] = '\0';
+    alt_filename[128] = '\0';
+
+    strncpy( filename, argv[file], 128 );
+    strncpy( alt_filename, argv[file], 128 );
+
+#ifndef macintosh
+    if ( i >= 0 )
+    {
+      strncpy( filename + strlen( filename ), ".ttf", 4 );
+      strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
+    }
+#endif
+
+    /* Load face */
+    error = FT_New_Face( library, filename, 0, &face );
+    if (error) goto Display_Font;
+
+    /* retrieve multiple master information */
+    error = FT_Get_Multi_Master( face, &multimaster ); 
+    if (error) goto Display_Font;
+
+    /* set the current position to the minimum of each axis */
+    {
+      int  n;
+      
+      for ( n = 0; n < multimaster.num_axis; n++ )
+        design_pos[n] =
+          (multimaster.axis[n].minimum + multimaster.axis[n].maximum)/2;
+    }
+    
+    error = FT_Set_MM_Design_Coordinates( face, multimaster.num_axis, design_pos );
+    if (error) goto Display_Font;
+    
+    file_loaded++;
+
+    error = Reset_Scale( ptsize );
+    if (error) goto Display_Font;
+
+    num_glyphs = face->num_glyphs;
+    glyph      = face->glyph;
+    size       = face->size;
+
+  Display_Font:
+    /* initialise graphics if needed */
+    if ( !XisSetup )
+    {
+      XisSetup = 1;
+      Init_Display();
+    }
+
+    grSetTitle( surface, "FreeType Glyph Viewer - press F1 for help" );
+    old_ptsize = ptsize;
+
+    if ( file_loaded >= 1 )
+    {
+      Fail = 0;
+      Num  = first_glyph;
+
+      if ( Num >= num_glyphs )
+        Num = num_glyphs-1;
+
+      if ( Num < 0 )
+        Num = 0;
+    }
+
+    for ( ;; )
+    {
+      int  key;
+
+      Clear_Display();
+
+      if ( file_loaded >= 1 )
+      {
+        switch (render_mode)
+        {
+          case 0:
+            Render_Text( Num, ptsize );
+            break;
+
+          default:
+            Render_All( Num, ptsize );
+        }
+
+        sprintf( Header, "%s %s (file %s)",
+                         face->family_name,
+                         face->style_name,
+                         ft_basename( filename ) );
+
+        if (!new_header)
+          new_header = Header;
+
+        grWriteCellString( &bit, 0, 0, new_header, fore_color );
+        new_header = 0;
+
+        sprintf( Header, "axis: " );
+        {
+          int  n;
+          for ( n = 0; n < multimaster.num_axis; n++ )
+          {
+            char   temp[32];
+            sprintf( temp, "  %s:%ld", multimaster.axis[n].name, design_pos[n] );
+            strcat( Header, temp );
+          }
+        }
+        grWriteCellString( &bit, 0, 16, Header, fore_color );
+          
+        sprintf( Header, "at %d points, first glyph = %d",
+                         ptsize,
+                         Num );
+      }
+      else
+      {
+        sprintf( Header, "%s : is not a multiple masters font file or could not be opened",
+                         ft_basename(filename) );
+      }
+
+      grWriteCellString( &bit, 0, 8, Header, fore_color );
+      grRefreshSurface( surface );
+
+      grListenSurface( surface, 0, &event );
+      if ( !( key = Process_Event( &event ) ) )
+        goto Fin;
+
+      if ( key == 'n' )
+      {
+        if (file_loaded >= 1)
+          FT_Done_Face( face );
+
+        if ( file < argc - 1 )
+          file++;
+
+        goto NewFile;
+      }
+
+      if ( key == 'p' )
+      {
+        if (file_loaded >= 1)
+          FT_Done_Face( face );
+
+        if ( file > 1 )
+          file--;
+
+        goto NewFile;
+      }
+
+      if ( ptsize != old_ptsize )
+      {
+        if ( Reset_Scale( ptsize ) )
+          PanicZ( "Could not resize font." );
+
+        old_ptsize = ptsize;
+      }
+    }
+
+  Fin:
+#if 0
+    grDoneSurface(surface);
+    grDone();
+#endif
+    printf( "Execution completed successfully.\n" );
+    printf( "Fails = %d\n", Fail );
+
+    exit( 0 );      /* for safety reasons */
+    return 0;       /* never reached */
+}
+
+
+/* End */
+
--- /dev/null
+++ b/src/sfnt/sfobjs.c
@@ -1,0 +1,499 @@
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+#include <freetype/ttnameid.h>
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Name                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a given ENGLISH name record in ASCII.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /*    nameid :: The name id of the name record to return.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Char string.  NULL if no name is present.                          */
+  /*                                                                       */
+  static
+  FT_String*  Get_Name( TT_Face    face,
+                        FT_UShort  nameid )
+  {
+    FT_Memory    memory = face->root.memory;
+    FT_UShort    n;
+    TT_NameRec*  rec;
+    FT_Bool      wide_chars = 1;
+
+    /* first pass, look for a given name record */
+    rec = face->name_table.names;
+    for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ )
+    {
+      if ( rec->nameID == nameid )
+      {
+        /* found the name - now create an ASCII string from it */
+        FT_Bool  found = 0;
+
+        /* Test for Microsoft English language */
+        if ( rec->platformID == TT_PLATFORM_MICROSOFT &&
+             rec->encodingID <= TT_MS_ID_UNICODE_CS   &&
+             (rec->languageID & 0x3FF) == 0x009 )
+          found = 1;
+
+        /* Test for Apple Unicode encoding */
+        else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE )
+          found = 1;
+
+        /* Test for Apple Roman */
+        else if ( rec->platformID == TT_PLATFORM_MACINTOSH &&
+                  rec->languageID == TT_MAC_ID_ROMAN       )
+        {
+          found      = 1;
+          wide_chars = 0;
+        }
+
+        /* Found a Unicode Name */
+        if ( found )
+        {
+          FT_String*  string;
+          FT_UInt     len;
+
+          if ( wide_chars )
+          {
+            TT_UInt   m;
+
+            len = (TT_UInt)rec->stringLength / 2;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            for ( m = 0; m < len; m ++ )
+              string[m] = rec->string[2*m + 1];
+          }
+          else
+          {
+            len = rec->stringLength;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            MEM_Copy( string, rec->string, len );
+          }
+
+          string[len] = '\0';
+          return string;
+        }
+      }
+    }
+    return NULL;
+  }
+
+
+  static
+  FT_Encoding   find_encoding( int  platform_id,
+                               int  encoding_id )
+  {
+    typedef struct  TEncoding
+    {
+      int          platform_id;
+      int          encoding_id;
+      FT_Encoding  encoding;
+
+    } TEncoding;
+
+    static
+    const TEncoding   tt_encodings[] =
+    {
+      { TT_PLATFORM_ISO,                         -1, ft_encoding_unicode },
+
+      { TT_PLATFORM_APPLE_UNICODE,               -1, ft_encoding_unicode },
+
+      { TT_PLATFORM_MACINTOSH,      TT_MAC_ID_ROMAN, ft_encoding_apple_roman },
+
+      { TT_PLATFORM_MICROSOFT,  TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,  TT_MS_ID_SJIS,       ft_encoding_sjis },
+      { TT_PLATFORM_MICROSOFT,  TT_MS_ID_BIG_5,      ft_encoding_big5 }
+    };
+
+    const TEncoding  *cur, *limit;
+
+    cur   = tt_encodings;
+    limit = cur + sizeof(tt_encodings)/sizeof(tt_encodings[0]);
+
+    for ( ; cur < limit; cur++ )
+    {
+      if (cur->platform_id == platform_id)
+      {
+        if (cur->encoding_id == encoding_id ||
+            cur->encoding_id == -1          )
+          return cur->encoding;
+      }
+    }
+    return ft_encoding_none;
+  }
+
+
+
+
+  LOCAL_FUNC
+  FT_Error  SFNT_Init_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            TT_Int         face_index,
+                            TT_Int         num_params,
+                            FT_Parameter*  params )
+  {
+    FT_Error           error;
+    SFNT_Interface*    sfnt;
+    PSNames_Interface* psnames;
+
+    /* for now, parameters are unused */
+    UNUSED(num_params);
+    UNUSED(params);
+
+    sfnt = (SFNT_Interface*)face->sfnt;
+    if (!sfnt)
+    {
+      /* look-up the SFNT driver */
+      FT_Driver  sfnt_driver;
+
+      sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" );
+      if (!sfnt_driver)
+      {
+        error = FT_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      sfnt = (SFNT_Interface*)(sfnt_driver->interface.format_interface);
+      if (!sfnt)
+      {
+        error = FT_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      face->sfnt       = sfnt;
+      face->goto_table = sfnt->goto_table;
+    }
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if (!psnames)
+    {
+      /* look-up the PSNames driver */
+      FT_Driver  psnames_driver;
+
+      psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
+      if (psnames_driver)
+        face->psnames = (PSNames_Interface*)
+                            (psnames_driver->interface.format_interface);
+    }
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->load_format_tag( face, stream, face_index,
+                                    &face->format_tag );
+    if (error) goto Exit;                                    
+
+    /* Load font directory */
+    error = sfnt->load_directory( face, stream, face_index );
+    if ( error ) goto Exit;
+
+    face->root.num_faces = face->ttc_header.DirCount;
+    if ( face->root.num_faces < 1 )
+      face->root.num_faces = 1;
+
+  Exit:
+    return error;
+  }
+
+
+
+#undef  LOAD_
+#define LOAD_(x)   ( (error = sfnt->load_##x( face, stream )) != FT_Err_Ok )
+
+
+  LOCAL_FUNC
+  TT_Error  SFNT_Load_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            TT_Int         face_index,
+                            TT_Int         num_params,
+                            FT_Parameter*  params )
+  {
+    FT_Error   error;
+    SFNT_Interface*    sfnt = (SFNT_Interface*)face->sfnt;
+
+    /* Load tables */
+    if ( LOAD_( header )        ||
+         LOAD_( max_profile )   ||
+
+         (error = sfnt->load_metrics( face, stream, 0 )) != FT_Err_Ok  ||
+         /* load the `hhea' & `hmtx' tables at once */
+
+         (error = sfnt->load_metrics( face, stream, 1 )) != FT_Err_Ok ||
+         /* try to load the `vhea' & `vmtx' at once if present */
+
+         LOAD_( charmaps )      ||
+         LOAD_( names )         ||
+         LOAD_( os2 )           ||
+         LOAD_( psnames )       )
+     goto Exit;
+
+    /* the optional tables */
+
+    /* embedded bitmap support. */
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    if (sfnt->load_sbits && LOAD_(sbits)) goto Exit;
+#endif
+
+    if ( LOAD_( hdmx )          ||
+         LOAD_( gasp )          ||
+         LOAD_( kerning )       ||
+		 LOAD_( pclt )          )
+      goto Exit;
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+    if ( ( error = TT_Extension_Create( face ) ) != FT_Err_Ok )
+      goto Exit;
+#endif
+
+    face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY );
+    face->root.style_name  = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY );
+
+    /* now set up root fields */
+    {
+      FT_Face     root = &face->root;
+      FT_Int      flags;
+      TT_CharMap  charmap;
+      TT_Int      n;
+      FT_Memory   memory;
+
+      memory = root->memory;
+
+      /*****************************************************************/
+      /*                                                               */
+      /* Compute face flags.                                           */
+      /*                                                               */
+      flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
+              FT_FACE_FLAG_SFNT      |    /* SFNT file format  */
+              FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */
+
+      /* fixed width font ? */
+      if ( face->postscript.isFixedPitch )
+        flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      /* vertical information ? */
+      if ( face->vertical_info )
+        flags |= FT_FACE_FLAG_VERTICAL;
+
+      /* kerning available ? */
+      if ( face->kern_pairs )
+        flags |= FT_FACE_FLAG_KERNING;
+
+      root->face_flags = flags;
+
+      /*****************************************************************/
+      /*                                                               */
+      /* Compute style flags.                                          */
+      /*                                                               */
+      flags = 0;
+
+      if ( face->os2.version != 0xFFFF )
+      {
+        /* We have an OS/2 table, use the `fsSelection' field */
+        if ( face->os2.fsSelection & 1 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+
+        if ( face->os2.fsSelection & 32 )
+          flags |= FT_STYLE_FLAG_BOLD;
+      }
+      else
+      {
+        /* This is an old Mac font, use the header field */
+        if ( face->header.Mac_Style & 1 )
+          flags |= FT_STYLE_FLAG_BOLD;
+
+        if ( face->header.Mac_Style & 2 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+      }
+
+      face->root.style_flags = flags;
+
+      /*****************************************************************/
+      /*                                                               */
+      /* Polish the charmaps.                                          */
+      /*                                                               */
+      /*   Try to set the charmap encoding according to the platform & */
+      /*   encoding ID of each charmap.                                */
+      /*                                                               */
+      charmap            = face->charmaps;
+      root->num_charmaps = face->num_charmaps;
+
+      /* allocate table of pointers */
+      if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+        goto Exit;
+
+      for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+      {
+        FT_Int  platform = charmap->cmap.platformID;
+        FT_Int  encoding = charmap->cmap.platformEncodingID;
+
+        charmap->root.face        = (FT_Face)face;
+        charmap->root.platform_id = platform;
+        charmap->root.encoding_id = encoding;
+        charmap->root.encoding    = find_encoding(platform,encoding);
+
+        /* now, set root->charmap with a unicode charmap wherever available */
+        if (!root->charmap && charmap->root.encoding == ft_encoding_unicode)
+          root->charmap = (FT_CharMap)charmap;
+
+        root->charmaps[n] = (FT_CharMap)charmap;
+      }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+      if ( face->num_sbit_strikes )
+      {
+       face->root.num_fixed_sizes = face->num_sbit_strikes;
+       if ( ALLOC_ARRAY( face->root.available_sizes,
+                         face->num_sbit_strikes,
+                         FT_Bitmap_Size ) )
+         return error;
+
+       for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
+       {
+         face->root.available_sizes[n].width =
+           face->sbit_strikes[n].x_ppem;
+         face->root.available_sizes[n].height =
+           face->sbit_strikes[n].y_ppem;
+       }
+      }
+      else
+#else
+      {
+       root->num_fixed_sizes = 0;
+       root->available_sizes = 0;
+      }
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+      /*****************************************************************/
+      /*                                                               */
+      /*  Set up metrics.                                              */
+      /*                                                               */
+      root->bbox.xMin    = face->header.xMin;
+      root->bbox.yMin    = face->header.yMin;
+      root->bbox.xMax    = face->header.xMax;
+      root->bbox.yMax    = face->header.yMax;
+      root->units_per_EM = face->header.Units_Per_EM;
+
+      /* The ascender/descender/height are computed from the OS/2 table   */
+      /* when found.  Otherwise, they're taken from the horizontal header */
+      if ( face->os2.version != 0xFFFF )
+      {
+        root->ascender  =  face->os2.sTypoAscender;
+        root->descender = -face->os2.sTypoDescender;
+        root->height    =  root->ascender + root->descender +
+                           face->os2.sTypoLineGap;
+      }
+      else
+      {
+        root->ascender  = face->horizontal.Ascender;
+        root->descender = face->horizontal.Descender;
+        root->height    = root->ascender + root->descender +
+                          face->horizontal.Line_Gap;
+      }
+
+      root->max_advance_width  = face->horizontal.advance_Width_Max;
+
+      root->max_advance_height = root->height;
+      if ( face->vertical_info )
+        root->max_advance_height = face->vertical.advance_Height_Max;
+
+      root->underline_position  = face->postscript.underlinePosition;
+      root->underline_thickness = face->postscript.underlineThickness;
+
+      /* root->max_points      - already set up */
+      /* root->max_contours    - already set up */
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#undef LOAD_
+
+
+  LOCAL_FUNC
+  void  SFNT_Done_Face( TT_Face  face )
+  {
+    FT_Memory        memory = face->root.memory;
+    SFNT_Interface*  sfnt   = face->sfnt;
+
+    if (sfnt)
+    {
+      /* destroy the postscript names table if it is supported */
+      if (sfnt->free_psnames)
+        sfnt->free_psnames( face );
+
+      /* destroy the embedded bitmaps table if it is supported */
+      if (sfnt->free_sbits)
+        sfnt->free_sbits( face );
+    }
+
+    /* freeing the kerning table */
+    FREE( face->kern_pairs );
+    face->num_kern_pairs = 0;
+
+    /* freeing the collection table */
+    FREE( face->ttc_header.TableDirectory );
+    face->ttc_header.DirCount = 0;
+
+    /* freeing table directory */
+    FREE( face->dir_tables );
+    face->num_tables = 0;
+
+    /* freeing the character mapping tables */
+    if (sfnt && sfnt->load_charmaps )
+    {
+      FT_UShort  n;
+      for ( n = 0; n < face->num_charmaps; n++ )
+        sfnt->free_charmap( face, &face->charmaps[n].cmap );
+    }
+
+    FREE( face->charmaps );
+    face->num_charmaps = 0;
+
+    FREE( face->root.charmaps );
+    face->root.num_charmaps = 0;
+    face->root.charmap      = 0;
+
+    /* freeing the horizontal metrics */
+    FREE( face->horizontal.long_metrics );
+    FREE( face->horizontal.short_metrics );
+
+    /* freeing the vertical ones, if any */
+    if ( face->vertical_info )
+    {
+      FREE( face->vertical.long_metrics  );
+      FREE( face->vertical.short_metrics );
+      face->vertical_info = 0;
+    }
+
+    /* freeing the gasp table */
+    FREE( face->gasp.gaspRanges );
+    face->gasp.numRanges = 0;
+
+    /* freeing the name table */
+    sfnt->free_names( face );
+
+    /* freeing the hdmx table */
+    sfnt->free_hdmx( face );
+
+    /* freeing family and style name */
+    FREE( face->root.family_name );
+    FREE( face->root.style_name );
+
+    /* freeing sbit size table */
+    face->root.num_fixed_sizes = 0;
+    if ( face->root.available_sizes )
+      FREE( face->root.available_sizes );
+
+    face->sfnt = 0;
+  }
+
--- /dev/null
+++ b/src/sfnt/sfobjs.h
@@ -1,0 +1,45 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfobjs.h                                                               */
+/*                                                                         */
+/*    SFNT object management                                               */
+/*                                                                         */
+/*  Copyright 1996-1999 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+#ifndef SFOBJS_H
+#define SFOBJS_H
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+  LOCAL_DEF
+  FT_Error  SFNT_Init_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            TT_Int         face_index,
+                            TT_Int         num_params,
+                            FT_Parameter*  params );
+
+  LOCAL_DEF
+  FT_Error  SFNT_Load_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            TT_Int         face_index,
+                            TT_Int         num_params,
+                            FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  SFNT_Done_Face( TT_Face  face );
+
+
+#endif /* SFDRIVER_H */
+
+
+/* END */