T168_111\appl\Text\Freetype文件:第9~23个文件

TTCACHE.C 、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcache.c                                                   1.1
 *
 *    Generic object cache
 *
 *  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.
 *
 * Changes between 1.1 and 1.0:
 *
 *  - introduced the refresher and finalizer in the cache class
 *    definition/implementation.
 *
 ******************************************************************/

#include "ttengine.h"
#include "ttmemory.h"
#include "ttcache.h"
#include "ttobjs.h"
#include "ttdebug.h"

/* required by the tracing mode */
#undef  TT_COMPONENT
#define TT_COMPONENT  trace_cache

#define ZERO_List( list )  list = NULL

/* The macro FREE_Elements aliases the current engine instance's */
/* free list_elements recycle list.                              */
#define FREE_Elements  ( engine->list_free_elements )

/* Redefinition of LOCK and UNLOCK macros for New_Element and Done_Element */
/* Note: The macros are redefined below for the cache functions            */

#undef  LOCK
#define LOCK()    MUTEX_Lock   ( engine->lock )

#undef  UNLOCK
#define UNLOCK()  MUTEX_Release( engine->lock )

/*******************************************************************
 *
 *  Function    :  Element_New
 *
 *  Description :  Gets a new (either fresh or recycled) list
 *                 element.  The element is unlisted.
 *
 *  Input  :  None
 *
 *  Output :  List element address.  NULL if out of memory.
 *
 ******************************************************************/

  static
  PList_Element  Element_New( PEngine_Instance  engine )
  {
    PList_Element  element;


    LOCK();
    if ( FREE_Elements )
    {
      element       = (PList_Element)FREE_Elements;
      FREE_Elements = element->next;
    }
    else
    {
      if ( !MEM_Alloc( element, sizeof ( TList_Element ) ) )
      {
        element->next = NULL;
        element->data = NULL;
      }
    }

    /* Note: in case of failure, Alloc sets the pointer to NULL */
    UNLOCK();

    return element;
  }


/*******************************************************************
 *
 *  Function    :  Element_Done
 *
 *  Description :  Recycles an unlinked list element.
 *
 *  Input  :  The list element to recycle.  It _must_ be unlisted.
 *
 *  Output :  none.
 *
 *  Note   :  This function doesn't check the element.
 *
 ******************************************************************/

  static
  void  Element_Done( PEngine_Instance  engine,
                      PList_Element     element )
  {
    LOCK();
    /* Simply add the list element to the recycle list */
    element->next = (PList_Element)FREE_Elements;
    FREE_Elements = element;
    UNLOCK();
  }


/* Redefinition of LOCK and UNLOCK macros for the cache functions          */
/* Note: The macros are defined above for the list element functions       */

#undef  LOCK
#define LOCK()    MUTEX_Lock( *cache->lock )

#undef  UNLOCK
#define UNLOCK()  MUTEX_Release( *cache->lock )


/*******************************************************************
 *
 *  Function    :  Cache_Create
 *
 *  Description :  Creates a new cache that will be used to list
 *                 and recycle several objects of the same class.
 *
 *  Input  :  clazz       a pointer to the cache's class.  This is
 *                        a simple structure that describes the
 *                        the cache's object types and recycling
 *                        limits.
 *
 *            cache       address of cache to create
 *
 *            lock        address of the mutex to use for this
 *                        cache.  The mutex will be used to protect
 *                        the cache's lists.  Use NULL for unprotected
 *                        cache.
 *
 *  Output :  Error code.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  Cache_Create( PEngine_Instance  engine,
                          PCache_Class      clazz,
                          TCache*           cache,
                          TMutex*           lock )
  {
    cache->engine     = engine;
    cache->clazz      = clazz;
    cache->lock       = lock;
    cache->idle_count = 0;

    ZERO_List( cache->active );
    ZERO_List( cache->idle );

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  Cache_Destroy
 *
 *  Description :  Destroys a cache and all its idle and active
 *                 objects.  This will call each object's destructor
 *                 before freeing it.
 *
 *  Input  :  cache   address of cache to destroy
 *
 *  Output :  error code.
 *
 *  Note: This function is not MT-Safe, as we assume that a client
 *        isn't stupid enough to use an object while destroying it.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  Cache_Destroy( TCache*  cache )
  {
    PDestructor    destroy;
    PList_Element  current;
    PList_Element  next;


    /* now destroy all active and idle listed objects */

    /* get the destructor function */
    destroy = cache->clazz->done;

    /* destroy all elements in active list */
    current = cache->active;
    while ( current )
    {
      next = current->next;
      destroy( current->data );
      FREE( current->data );

      Element_Done( cache->engine, current );
      current = next;
    }
    ZERO_List(cache->active);

    /* destroy all elements in idle list */
    current = cache->idle;
    while ( current )
    {
      next = current->next;
      destroy( current->data );
      FREE( current->data );

      Element_Done( cache->engine, current );
      current = next;
    }
    ZERO_List(cache->idle);

    cache->clazz      = NULL;
    cache->idle_count = 0;

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  Cache_New
 *
 *  Description :  Extracts a new object from a cache.  This will
 *                 try to recycle an idle object, if any is found.
 *                 Otherwise, a new object will be allocated and
 *                 built (by calling its constructor).
 *
 *  Input  :   cache          address of cache to use
 *             new_object     address of target pointer to the 'new'
 *                            object
 *             parent_object  this pointer is passed to a new object
 *                            constructor (unused if object is
 *                            recycled)
 *
 *  Output :   Error code.
 *
 *  Notes: This function is thread-safe, each cache list is protected
 *         through the cache's mutex, if there is one...
 *
 *         *new_object will be set to NULL in case of failure.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  Cache_New( TCache*  cache,
                       void**   new_object,
                       void*    parent_object )
  {
    TT_Error       error;
    PList_Element  current;
    PConstructor   build;
    PRefresher     reset;
    void*          object;


    LOCK();
    current = cache->idle;
    if ( current )
    {
      cache->idle = current->next;
      cache->idle_count--;
    }
    UNLOCK();

    if ( current )
    {
      object = current->data;
      reset  = cache->clazz->reset;
      if ( reset )
      {
        error = reset( object, parent_object );
        if ( error )
        {
          LOCK();
          current->next = cache->idle;
          cache->idle   = current;
          cache->idle_count++;
          UNLOCK();
          goto Exit;
        }
      }
    }
    else
    {
      /* if no object was found in the cache, create a new one */
      build  = cache->clazz->init;

      if ( MEM_Alloc( object, cache->clazz->object_size ) )
        goto Memory_Fail;

      current = Element_New( cache->engine );
      if ( !current )
        goto Memory_Fail;

      current->data = object;

      error = build( object, parent_object );
      if ( error )
      {
        Element_Done( cache->engine, current );
        goto Fail;
      }
    }

    LOCK();
    current->next = cache->active;
    cache->active = current;
    UNLOCK();

    *new_object = current->data;
    return TT_Err_Ok;

  Exit:
    *new_object = NULL;
    return  error;

  Memory_Fail:
    error = TT_Err_Out_Of_Memory;

  Fail:
    FREE( object );
    goto Exit;
  }


/*******************************************************************
 *
 *  Function    :  Cache_Done
 *
 *  Description :  Releases an object to the cache.  This will either
 *                 recycle or destroy the object, based on the cache's
 *                 class and state.
 *
 *  Input  :  cache   the cache to use
 *            data    the object to recycle/discard
 *
 *  Output :  error code.
 *
 *  Notes  :  The object's destructor is called only when
 *            the objectwill be effectively destroyed by this
 *            function.  This will not happen during recycling.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  Cache_Done( TCache*  cache, void*  data )
  {
    TT_Error       error;
    PList_Element  element;
    PList_Element  prev;
    PFinalizer     finalize;
    Long           limit;
    Bool           destroy;


    /* Look for object in active list */
    LOCK();

    element = cache->active;
    prev = NULL;
    while ( element )
    {
      if ( element->data == data )
      {
        if ( prev )
          prev->next = element->next;
        else
          cache->active = element->next;
        goto Suite;
      }
      prev = element;
      element = element->next;
    }

    UNLOCK();
    return TT_Err_Unlisted_Object;

  Suite:

    limit   = cache->clazz->idle_limit;
    destroy = (cache->idle_count >= limit);
    UNLOCK();

    if ( destroy )
    {
      /* destroy the object when the cache is full */
      cache->clazz->done( element->data );
      FREE( element->data );
      Element_Done( cache->engine, element );
    }
    else
    {
      /* Finalize the object before adding it to the   */
      /* idle list.  Return the error if any is found. */

      finalize = cache->clazz->finalize;
      if ( finalize )
      {
        error = finalize( element->data );
        if ( error )
          goto Exit;

        /* Note: a failure at finalize time is a severe bug in     */
        /*       the engine, which is why we allow ourselves to    */
        /*       lose the object in this case.  A finalizer should */
        /*       have its own error codes to spot this kind of     */
        /*       problems easily.                                  */
      }

      LOCK();
      element->next = cache->idle;
      cache->idle   = element;
      cache->idle_count++;
      UNLOCK();
    }

    error = TT_Err_Ok;

  Exit:
    return error;
  }


  LOCAL_FUNC
  TT_Error  TTCache_Init( PEngine_Instance  engine )
  {
    /* Create list elements mutex */
    FREE_Elements = NULL;
    return TT_Err_Ok;
  }


  LOCAL_FUNC
  TT_Error  TTCache_Done( PEngine_Instance  engine )
  {
    /* We don't protect this function, as this is the end of the engine's */
    /* execution..                                                        */
    PList_Element  element, next;


    /* frees the recycled list elements */
    element = FREE_Elements;
    while ( element )
    {
      next = element->next;
      FREE( element );
      element = next;
    }
    return TT_Err_Ok;
  }


/* END */
 

TTCACHE.H  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcache.h                                                   1.1
 *
 *    Generic object cache
 *
 *  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.
 *
 *
 *  This component defines and implements object caches.
 *
 *  An object class is a structure layout that encapsulate one
 *  given type of data used by the FreeType engine.  Each object
 *  class is completely described by:
 *
 *    - a 'root' or 'leading' structure containing the first
 *      important fields of the class.  The root structure is
 *      always of fixed size.
 *
 *      It is implemented as a simple C structure, and may
 *      contain several pointers to sub-tables that can be
 *      sized and allocated dynamically.
 *
 *      Examples:  TFace, TInstance, TGlyph & TExecution_Context
 *                 (defined in 'ttobjs.h')
 *
 *    - we make a difference between 'child' pointers and 'peer'
 *      pointers.  A 'child' pointer points to a sub-table that is
 *      owned by the object, while a 'peer' pointer points to any
 *      other kind of data the object isn't responsible for.
 *
 *      An object class is thus usually a 'tree' of 'child' tables.
 *
 *    - each object class needs a constructor and a destructor.
 *
 *      A constructor is a function which receives the address of
 *      freshly allocated and zeroed object root structure and
 *      'builds' all the valid child data that must be associated
 *      to the object before it becomes 'valid'.
 *
 *      A destructor does the inverse job: given the address of
 *      a valid object, it must discard all its child data and
 *      zero its main fields (essentially the pointers and array
 *      sizes found in the root fields).
 *
 *
 *  Important notes:
 *
 *      When the constructor fails to allocate an object, it must
 *      return immediately with an error code, and not try to release
 *      what it has previously allocated before the error.  The cache
 *      manager detects the error and calls the destructor on the
 *      partial object, before returning the error to the caller (along
 *      with a NULL pointer for the "new" object).
 *
 *      The destructor must thus be able to deal with "partial objects",
 *      i.e., objects where only part of the child tables are allocated,
 *      and only release these ones.  As the TT_Free() function accepts
 *      a NULL parameter (and returns successfuly in this case), no check
 *      is really necessary when using the macro 'FREE()'.
 *
 *      Currently, there is no check in the cache manager to see if a
 *      destructor fails (double error state!).
 *
 *      This scheme is more compact and more maintanable than the one
 *      where de-allocation code is duplicated in the constructor
 *      _and_ the destructor.
 *
 *
 *
 * Changes between 1.1 and 1.0:
 *
 *  - introduced the refreshed and finalizer class definition/implementation
 *  - inserted an engine instance pointer in the cache structure
 *
 ******************************************************************/

#ifndef TTCACHE_H
#define TTCACHE_H

#include "tttypes.h"
#include "ttconfig.h"
#include "ttmutex.h"

#ifdef __cplusplus
  extern "C" {
#endif

  typedef TT_Error  TConstructor( void*  object,
                                  void*  parent );

  typedef TT_Error  TDestructor ( void*  object );

  typedef TConstructor  TRefresher;
  typedef TDestructor   TFinalizer;

  typedef TConstructor*  PConstructor;
  typedef TDestructor*   PDestructor;
  typedef TRefresher*    PRefresher;
  typedef TFinalizer*    PFinalizer;


  /* A Cache class record holds the data necessary to define */
  /* a cache kind.                                           */
  struct  TCache_Class_
  {
    ULong         object_size;
    Long          idle_limit;
    PConstructor  init;
    PDestructor   done;
    PRefresher    reset;
    PFinalizer    finalize;
  };

  typedef struct TCache_Class_  TCache_Class;
  typedef TCache_Class*         PCache_Class;

  /* Simple list node record.  A list element is said to be 'unlinked' */
  /* when it doesn't belong to any list.                               */
  struct  TList_Element_;

  typedef struct TList_Element_  TList_Element;
  typedef TList_Element*         PList_Element;

  struct  TList_Element_
  {
    PList_Element  next;
    void*          data;
  };


  /* Simple singly-linked list record - LIFO style, no tail field */
  typedef PList_Element  TSingle_List;

  struct  TCache_
  {
    PEngine_Instance  engine;
    PCache_Class      clazz;      /* 'class' is a reserved word in C++ */
    TMutex*           lock;
    TSingle_List      active;
    TSingle_List      idle;
    Long              idle_count;
  };

  typedef struct TCache_  TCache;
  typedef TCache*         PCache;

  /* Returns a new list element, either fresh or recycled. */
  /* Note: the returned element is unlinked.               */

  /* An object cache holds two lists tracking the active and */
  /* idle objects that are currently created and used by the */
  /* engine.  It can also be 'protected' by a mutex.         */

  /* Initializes a new cache, of class 'clazz', pointed by 'cache', */
  /* protected by the 'lock' mutex. Set 'lock' to NULL if the cache */
  /* doesn't need protection                                        */

  LOCAL_DEF
  TT_Error  Cache_Create( PEngine_Instance  engine,
                          PCache_Class      clazz,
                          TCache*           cache,
                          TMutex*           lock );

  /* Destroys a cache and all its listed objects */

  LOCAL_DEF
  TT_Error  Cache_Destroy( TCache*  cache );


  /* Extracts a new object from the cache */

  LOCAL_DEF
  TT_Error Cache_New( TCache*  cache,
                      void**   new_object,
                      void*    parent_object );


  /* Returns an object to the cache, or discards it depending */
  /* on the cache class' 'idle_limit' field                   */

  LOCAL_DEF
  TT_Error  Cache_Done( TCache*  cache, void*  data );

#define CACHE_New( _cache, _newobj, _parent ) \
          Cache_New( (TCache*)_cache, (void**)&_newobj, (void*)_parent )

#define CACHE_Done( _cache, _obj ) \
          Cache_Done( (TCache*)_cache, (void*)_obj )

  LOCAL_DEF
  TT_Error  TTCache_Init( PEngine_Instance  engine );

  LOCAL_DEF
  TT_Error  TTCache_Done( PEngine_Instance  engine );


#ifdef __cplusplus
  }
#endif

#endif /* TTCACHE_H */


/* END */
 

TTCALC.C  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcalc.c
 *
 *    Arithmetic Computations (body).
 *
 *  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.
 *
 ******************************************************************/

#include "ttcalc.h"
#include "ttdebug.h"
#include "tttables.h"

/* required by the tracing mode */
#undef  TT_COMPONENT
#define TT_COMPONENT      trace_calc


/* Support for 1-complement arithmetic has been totally dropped in this */
/* release.  You can still write your own code if you need it...        */

  static const Long  Roots[63] =
  {
       1,    1,    2,     3,     4,     5,     8,    11,
      16,   22,   32,    45,    64,    90,   128,   181,
     256,  362,  512,   724,  1024,  1448,  2048,  2896,
    4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340,

      65536,   92681,  131072,   185363,   262144,   370727,
     524288,  741455, 1048576,  1482910,  2097152,  2965820,
    4194304, 5931641, 8388608, 11863283, 16777216, 23726566,

      33554432,   47453132,   67108864,   94906265,
     134217728,  189812531,  268435456,  379625062,
     536870912,  759250125, 1073741824, 1518500250,
    2147483647
  };


#ifdef LONG64

  EXPORT_FUNC
  TT_Long  TT_MulDiv( TT_Long  a, TT_Long  b, TT_Long  c )
  {
    Long  s;


    s  = a; a = ABS( a );
    s ^= b; b = ABS( b );
    s ^= c; c = ABS( c );

    a = ((TT_Int64)a * b + c/2) / c;
    return ( s < 0 ) ? -a : a;
  }


  EXPORT_FUNC
  TT_Long  TT_MulFix( TT_Long  a, TT_Long  b )
  {
    Long  s;


    s  = a; a = ABS( a );
    s ^= b; b = ABS( b );

    a = ((TT_Int64)a * b + 0x8000) / 0x10000;
    return ( s < 0 ) ? -a : a;
  }


  LOCAL_FUNC
  Int  Order64( TT_Int64  z )
  {
    Int  j = 0;


    while ( z )
    {
      z = (unsigned INT64)z >> 1;
      j++;
    }
    return j - 1;
  }


  LOCAL_FUNC
  TT_Int32  Sqrt64( TT_Int64  l )
  {
    TT_Int64  r, s;


    if ( l <= 0 ) return 0;
    if ( l == 1 ) return 1;

    r = Roots[Order64( l )];

    do
    {
      s = r;
      r = ( r + l/r ) >> 1;
    }
    while ( r > s || r*r > l );

    return r;
  }

#else /* LONG64 */


  /* The TT_MulDiv function has been optimized thanks to ideas from      */
  /* Graham Asher. The trick is to optimize computation when everything  */
  /* fits within 32-bits (a rather common case).                         */
  /*                                                                     */
  /*  we compute 'a*b+c/2', then divide it by 'c'. (positive values)     */
  /*                                                                     */
  /*  46340 is FLOOR(SQRT(2^31-1)).                                      */
  /*                                                                     */
  /*  if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 )         */
  /*                                                                     */
  /*  0x7FFFFFFF - 0x7FFEA810 = 0x157F0                                  */
  /*                                                                     */
  /*  if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF )                */
  /*                                                                     */
  /*  and 2*0x157F0 = 176096                                             */
  /*                                                                     */

  EXPORT_FUNC
  TT_Long  TT_MulDiv( TT_Long  a, TT_Long  b, TT_Long  c )
  {
    long   s;


    if ( a == 0 || b == c )
      return a;

    s  = a; a = ABS( a );
    s ^= b; b = ABS( b );
    s ^= c; c = ABS( c );

    if ( a <= 46340 && b <= 46340 && c <= 176095 )
    {
      a = ( a*b + c/2 )/c;
    }
    else
    {
      TT_Int64  temp, temp2;

      MulTo64( a, b, &temp );
      temp2.hi = (TT_Int32)(c >> 31);
      temp2.lo = (TT_Word32)(c / 2);
      Add64( &temp, &temp2, &temp );
      a = Div64by32( &temp, c );
    }

    return ( s < 0 ) ? -a : a;
  }

  /* The optimization for TT_MulFix is different. We could simply be     */
  /* happy by applying the same principles than with TT_MulDiv, because  */
  /*                                                                     */
  /*    c = 0x10000 < 176096                                             */
  /*                                                                     */
  /* however, in most cases, we have a 'b' with a value around 0x10000   */
  /* which is greater than 46340.                                        */
  /*                                                                     */
  /* According to Graham's testing, most cases have 'a' < 100, so a good */
  /* idea is to use bounds like 1024 and 2097151 (= floor(2^31-1)/1024 ) */
  /* for 'a' and 'b' respectively..                                      */
  /*                                                                     */

  EXPORT_FUNC
  TT_Long   TT_MulFix( TT_Long  a, TT_Long  b )
  {
    long   s;

    if ( a == 0 || b == 0x10000 )
      return a;

    s  = a; a = ABS( a );
    s ^= b; b = ABS( b );

    if ( a <= 1024 && b <= 2097151 )
    {
      a = ( a*b + 0x8000 ) >> 16;
    }
    else
    {
      TT_Int64  temp, temp2;

      MulTo64( a, b, &temp );
      temp2.hi = 0;
      temp2.lo = 0x8000;
      Add64( &temp, &temp2, &temp );
      a = Div64by32( &temp, 0x10000 );
    }

    return ( s < 0 ) ? -a : a;
  }


  LOCAL_FUNC
  void  Neg64( TT_Int64*  x )
  {
    /* Remember that -(0x80000000) == 0x80000000 with 2-complement! */
    /* We take care of that here.                                   */

    x->hi ^= 0xFFFFFFFFUL;
    x->lo ^= 0xFFFFFFFFUL;
    x->lo++;

    if ( !x->lo )
    {
      x->hi++;
      if ( x->hi == 0x80000000UL )  /* Check -MaxInt32 - 1 */
      {
        x->lo--;
        x->hi--;  /* We return 0x7FFFFFFF! */
      }
    }
  }


  LOCAL_FUNC
  void  Add64( TT_Int64*  x, TT_Int64*  y, TT_Int64*  z )
  {
    register TT_Word32  lo, hi;


    lo = x->lo + y->lo;
    hi = x->hi + y->hi + ( lo < x->lo );

    z->lo = lo;
    z->hi = hi;
  }


  LOCAL_FUNC
  void  Sub64( TT_Int64*  x, TT_Int64*  y, TT_Int64*  z )
  {
    register TT_Word32  lo, hi;


    lo = x->lo - y->lo;
    hi = x->hi - y->hi - ( (TT_Int32)lo < 0 );

    z->lo = lo;
    z->hi = hi;
  }


  LOCAL_FUNC
  void  MulTo64( TT_Int32  x, TT_Int32  y, TT_Int64*  z )
  {
    TT_Int32   s;
    TT_Word32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;


    s  = x; x = ABS( x );
    s ^= y; y = ABS( y );

    lo1 = x & 0x0000FFFF;  hi1 = x >> 16;
    lo2 = y & 0x0000FFFF;  hi2 = y >> 16;

    lo = lo1*lo2;
    i1 = lo1*hi2;
    i2 = lo2*hi1;
    hi = hi1*hi2;

    /* Check carry overflow of i1 + i2 */

    if ( i2 )
    {
      if ( i1 >= (TT_Word32)-(TT_Int32)i2 ) hi += 1L << 16;
      i1 += i2;
    }

    i2 = i1 >> 16;
    i1 = i1 << 16;

    /* Check carry overflow of i1 + lo */
    if ( i1 )
    {
      if ( lo >= (TT_Word32)-(TT_Int32)i1 ) hi++;
      lo += i1;
    }

    hi += i2;

    z->lo = lo;
    z->hi = hi;

    if ( s < 0 ) Neg64( z );
  }


  LOCAL_FUNC
  TT_Int32  Div64by32( TT_Int64*  x, TT_Int32  y )
  {
    TT_Int32   s;
    TT_Word32  q, r, i, lo;


    s  = x->hi; if ( s < 0 ) Neg64( x );
    s ^= y;     y = ABS( y );

    /* Shortcut */
    if ( x->hi == 0 )
    {
      q = x->lo / y;
      return ( s < 0 ) ? -(TT_Int32)q : (TT_Int32)q;
    }

    r  = x->hi;
    lo = x->lo;

    if ( r >= (TT_Word32)y )   /* we know y is to be treated as unsigned here */
      return ( s < 0 ) ? 0x80000001UL : 0x7FFFFFFFUL;
                            /* Return Max/Min Int32 if divide overflow */
                            /* This includes division by zero!         */
    q = 0;
    for ( i = 0; i < 32; i++ )
    {
      r <<= 1;
      q <<= 1;
      r  |= lo >> 31;

      if ( r >= (TT_Word32)y )
      {
        r -= y;
        q |= 1;
      }
      lo <<= 1;
    }

    return ( s < 0 ) ? -(TT_Int32)q : (TT_Int32)q;
  }


  LOCAL_FUNC
  Int  Order64( TT_Int64*  z )
  {
    TT_Word32  i;
    Int     j;


    if ( z->hi )
    {
      i = z->hi;
      j = 32;
    }
    else
    {
      i = z->lo;
      j = 0;
    }

    while ( i > 0 )
    {
      i >>= 1;
      j++;
    }
    return j-1;
  }


  LOCAL_FUNC
  TT_Int32  Sqrt64( TT_Int64*  l )
  {
    TT_Int64  l2;
    TT_Int32  r, s;


    if ( (TT_Int32)l->hi < 0          ||
        (l->hi == 0 && l->lo == 0) )  return 0;

    s = Order64( l );
    if ( s == 0 ) return 1;

    r = Roots[s];
    do
    {
      s = r;
      r = ( r + Div64by32(l,r) ) >> 1;
      MulTo64( r, r,   &l2 );
      Sub64  ( l, &l2, &l2 );
    }
    while ( r > s || (TT_Int32)l2.hi < 0 );

    return r;
  }

#endif /* LONG64 */


/* END */
 

TTCALC.H  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcalc.h
 *
 *    Arithmetic Computations (specification).
 *
 *  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 TTCALC_H
#define TTCALC_H

#include "ttconfig.h"
#include "freetype.h"


#ifdef __cplusplus
  extern "C" {
#endif

#ifdef LONG64

  typedef INT64  TT_Int64;

#define ADD_64( x, y, z )  z = x + y
#define SUB_64( x, y, z )  z = x - y
#define MUL_64( x, y, z )  z = (TT_Int64)(x) * (y)

#define DIV_64( x, y )     ( (x) / (y) )

#define SQRT_64( x )       Sqrt64( x )
#define SQRT_32( x )       Sqrt32( x )

  LOCAL_DEF TT_Int32  Sqrt64( TT_Int64  l );

#else /* LONG64 */

  struct  TT_Int64_
  {
    TT_Word32  lo;
    TT_Word32  hi;
  };

  typedef struct TT_Int64_  TT_Int64;

#define ADD_64( x, y, z )  Add64( &x, &y, &z )
#define SUB_64( x, y, z )  Sub64( &x, &y, &z )
#define MUL_64( x, y, z )  MulTo64( x, y, &z )

#define DIV_64( x, y )     Div64by32( &x, y )

#define SQRT_64( x )       Sqrt64( &x )
#define SQRT_32( x )       Sqrt32( x )

  LOCAL_DEF void  Add64( TT_Int64*  x, TT_Int64*  y, TT_Int64*  z );
  LOCAL_DEF void  Sub64( TT_Int64*  x, TT_Int64*  y, TT_Int64*  z );

  LOCAL_DEF void  MulTo64( TT_Int32  x, TT_Int32  y, TT_Int64*  z );

  LOCAL_DEF TT_Int32  Div64by32( TT_Int64*  x, TT_Int32  y );

  LOCAL_DEF int  Order64( TT_Int64*  z );

  LOCAL_DEF TT_Int32  Sqrt64( TT_Int64*  l );

#endif /* LONG64 */

  /* The two following functions are now part of the API!          */

  /* TT_Long  TT_MulDiv( TT_Long  a, TT_Long  b, TT_Long  c );     */
  /* TT_Long  TT_MulFix( TT_Long  a, TT_Long  b );                 */


#define INT_TO_F26DOT6( x )    ( (Long)(x) << 6  )
#define INT_TO_F2DOT14( x )    ( (Long)(x) << 14 )
#define INT_TO_FIXED( x )      ( (Long)(x) << 16 )
#define F2DOT14_TO_FIXED( x )  ( (Long)(x) << 2  )
#define FLOAT_TO_FIXED( x )    ( (Long)(x * 65536.0) )

#define ROUND_F26DOT6( x )     ( x >= 0 ? (   ((x) + 32) & -64) \
                                        : ( -((32 - (x)) & -64) ) )

#ifdef __cplusplus
  }
#endif

#endif /* TTCALC_H */

/* END */
 

TTCMAP.C  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcmap.c                                                    1.0
 *
 *    TrueType Character Mappings
 *
 *  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.
 *
 ******************************************************************/

#include "ttobjs.h"
#include "ttdebug.h"
#include "ttfile.h"
#include "ttmemory.h"
#include "ttload.h"
#include "ttcmap.h"

/* required by the tracing mode */
#undef  TT_COMPONENT
#define TT_COMPONENT      trace_cmap


/*******************************************************************
 *
 *  Function    :  CharMap_Load
 *
 *  Description :  Loads a given charmap into memory.
 *
 *  Input  :  cmap  pointer to cmap table
 *
 *  Output :  Error code.
 *
 *  Notes  :  - Assumes the the stream is already used (opened).
 *
 *            - In case of error, releases all partially allocated
 *              tables.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  CharMap_Load( PCMapTable  cmap,
                          TT_Stream   input )
  {
    DEFINE_LOAD_LOCALS( input );

    UShort  num_SH, num_Seg, i;

    UShort  u, l;

    PCMap0  cmap0;
    PCMap2  cmap2;
    PCMap4  cmap4;
    PCMap6  cmap6;

    PCMap2SubHeader cmap2sub;
    PCMap4Segment   segments;


    if ( cmap->loaded )
      return TT_Err_Ok;

    if ( FILE_Seek( cmap->offset ) )
      return error;

    switch ( cmap->format )
    {
    case 0:
      cmap0 = &cmap->c.cmap0;

      if ( ALLOC( cmap0->glyphIdArray, 256L )            ||
           FILE_Read( (void*)cmap0->glyphIdArray, 256L ) )
         goto Fail;

      break;

    case 2:
      num_SH = 0;
      cmap2  = &cmap->c.cmap2;

      /* allocate subheader keys */

      if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, UShort ) ||
           ACCESS_Frame( 512L )                             )
        goto Fail;

      for ( i = 0; i < 256; i++ )
      {
        u = GET_UShort() / 8;
        cmap2->subHeaderKeys[i] = u;

        if ( num_SH < u )
          num_SH = u;
      }

      FORGET_Frame();

      /* load subheaders */

      cmap2->numGlyphId = l =
        ( ( cmap->length - 2L * (256 + 3) - num_SH * 8L ) & 0xffff) / 2;

      if ( ALLOC_ARRAY( cmap2->subHeaders,
                        num_SH + 1,
                        TCMap2SubHeader )     ||
           ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
        goto Fail;

      cmap2sub = cmap2->subHeaders;

      for ( i = 0; i <= num_SH; i++ )
      {
        cmap2sub->firstCode     = GET_UShort();
        cmap2sub->entryCount    = GET_UShort();
        cmap2sub->idDelta       = GET_Short();
        /* we apply the location offset immediately */
        cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2;

        cmap2sub++;
      }

      FORGET_Frame();

      /* load glyph ids */

      if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, UShort ) ||
           ACCESS_Frame( l * 2L ) )
        goto Fail;

      for ( i = 0; i < l; i++ )
        cmap2->glyphIdArray[i] = GET_UShort();

      FORGET_Frame();
      break;

    case 4:
      cmap4 = &cmap->c.cmap4;

      /* load header */

      if ( ACCESS_Frame( 8L ) )
        goto Fail;

      cmap4->segCountX2    = GET_UShort();
      cmap4->searchRange   = GET_UShort();
      cmap4->entrySelector = GET_UShort();
      cmap4->rangeShift    = GET_UShort();

      num_Seg = cmap4->segCountX2 / 2;

      FORGET_Frame();

      /* load segments */

      if ( ALLOC_ARRAY( cmap4->segments,
                        num_Seg,
                        TCMap4Segment )           ||
           ACCESS_Frame( (num_Seg * 4 + 1) * 2L ) )
        goto Fail;

      segments = cmap4->segments;

      for ( i = 0; i < num_Seg; i++ )
        segments[i].endCount      = GET_UShort();

      (void)GET_UShort();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].startCount    = GET_UShort();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idDelta       = GET_Short();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idRangeOffset = GET_UShort();

      FORGET_Frame();

      cmap4->numGlyphId = l =
        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xffff ) / 2;

      /* load ids */

      if ( ALLOC_ARRAY( cmap4->glyphIdArray, l , UShort ) ||
           ACCESS_Frame( l * 2L ) )
        goto Fail;

      for ( i = 0; i < l; i++ )
        cmap4->glyphIdArray[i] = GET_UShort();

      FORGET_Frame();
      break;

    case 6:
      cmap6 = &cmap->c.cmap6;

      if ( ACCESS_Frame( 4L ) )
        goto Fail;

      cmap6->firstCode  = GET_UShort();
      cmap6->entryCount = GET_UShort();

      FORGET_Frame();

      l = cmap6->entryCount;

      if ( ALLOC_ARRAY( cmap6->glyphIdArray,
                        cmap6->entryCount,
                        Short )   ||
           ACCESS_Frame( l * 2L ) )
        goto Fail;

      for ( i = 0; i < l; i++ )
        cmap6->glyphIdArray[i] = GET_UShort();

      FORGET_Frame();
      break;

    default:   /* corrupt character mapping table */
      return TT_Err_Invalid_CharMap_Format;

    }
    return TT_Err_Ok;

  Fail:
    CharMap_Free( cmap );
    return error;
  }


/*******************************************************************
 *
 *  Function    :  CharMap_Free
 *
 *  Description :  Releases a given charmap table.
 *
 *  Input  :  cmap   pointer to cmap table
 *
 *  Output :  Error code.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  CharMap_Free( PCMapTable  cmap )
  {
    if ( !cmap )
      return TT_Err_Ok;

    switch ( cmap->format )
    {
      case 0:
        FREE( cmap->c.cmap0.glyphIdArray );
        break;

      case 2:
        FREE( cmap->c.cmap2.subHeaderKeys );
        FREE( cmap->c.cmap2.subHeaders );
        FREE( cmap->c.cmap2.glyphIdArray );
        break;

      case 4:
        FREE( cmap->c.cmap4.segments );
        FREE( cmap->c.cmap4.glyphIdArray );
        cmap->c.cmap4.segCountX2 = 0;
        break;

      case 6:
        FREE( cmap->c.cmap6.glyphIdArray );
        cmap->c.cmap6.entryCount = 0;
        break;

      default:
        /* invalid table format, do nothing */
        ;
    }

    cmap->loaded = FALSE;
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  CharMap_Index
 *
 *  Description :  Performs charcode->glyph index translation.
 *
 *  Input  :  cmap   pointer to cmap table
 *
 *  Output :  Glyph index, 0 in case of failure.
 *
 ******************************************************************/

  static UShort  code_to_index0( UShort  charCode, PCMap0  cmap0 );
  static UShort  code_to_index2( UShort  charCode, PCMap2  cmap2 );
  static UShort  code_to_index4( UShort  charCode, PCMap4  cmap4 );
  static UShort  code_to_index6( UShort  charCode, PCMap6  cmap6 );


  LOCAL_FUNC
  UShort  CharMap_Index( PCMapTable  cmap,
                         UShort      charcode )
  {
    switch ( cmap->format )
    {
      case 0:
        return code_to_index0( charcode, &cmap->c.cmap0 );
      case 2:
        return code_to_index2( charcode, &cmap->c.cmap2 );
      case 4:
        return code_to_index4( charcode, &cmap->c.cmap4 );
      case 6:
        return code_to_index6( charcode, &cmap->c.cmap6 );
      default:
        return 0;
    }
  }


/*******************************************************************
 *
 *  Function    : code_to_index0
 *
 *  Description : Converts the character code into a glyph index.
 *                Uses format 0.
 *                charCode will be masked to get a value in the range
 *                0x00-0xFF.
 *
 *  Input  :  charCode      the wanted character code
 *            cmap0         a pointer to a cmap table in format 0
 *
 *  Output :  Glyph index into the glyphs array.
 *            0 if the glyph does not exist.
 *
 ******************************************************************/

  static UShort  code_to_index0( UShort  charCode,
                                 PCMap0  cmap0 )
  {
    if ( charCode <= 0xFF )
      return cmap0->glyphIdArray[charCode];
    else
      return 0;
  }


/*******************************************************************
 *
 *  Function    : code_to_index2
 *
 *  Description : Converts the character code into a glyph index.
 *                Uses format 2.
 *
 *  Input  :  charCode      the wanted character code
 *            cmap2         a pointer to a cmap table in format 2
 *
 *  Output :  Glyph index into the glyphs array.
 *            0 if the glyph does not exist.
 *
 ******************************************************************/

  static UShort  code_to_index2( UShort  charCode,
                                 PCMap2  cmap2 )
  {
    UShort           index1, idx, offset;
    TCMap2SubHeader  sh2;


    index1 = cmap2->subHeaderKeys[charCode <= 0xFF ?
                                  charCode : (charCode >> 8)];

    if ( index1 == 0 )
    {
      if ( charCode <= 0xFF )
        return cmap2->glyphIdArray[charCode];   /* 8bit character code */
      else
        return 0;
    }
    else                                        /* 16bit character code */
    {
      if ( charCode <= 0xFF )
        return 0;

      sh2 = cmap2->subHeaders[index1];

      if ( (charCode & 0xFF) < sh2.firstCode )
        return 0;

      if ( (charCode & 0xFF) >= (sh2.firstCode + sh2.entryCount) )
        return 0;

      offset = sh2.idRangeOffset / 2 + (charCode & 0xFF) - sh2.firstCode;
      if ( offset < cmap2->numGlyphId )
        idx = cmap2->glyphIdArray[offset];
      else
        return 0;

      if ( idx )
        return (idx + sh2.idDelta) & 0xFFFF;
      else
        return 0;
    }
  }


/*******************************************************************
 *
 *  Function    : code_to_index4
 *
 *  Description : Converts the character code into a glyph index.
 *                Uses format 4.
 *
 *  Input  :  charCode      the wanted character code
 *            cmap4         a pointer to a cmap table in format 4
 *
 *  Output :  Glyph index into the glyphs array.
 *            0 if the glyph does not exist.
 *
 ******************************************************************/

  static UShort  code_to_index4( UShort  charCode,
                                 PCMap4  cmap4 )
  {
    UShort         index1, segCount;
    UShort         i;
    TCMap4Segment  seg4;


    segCount = cmap4->segCountX2 / 2;

    for ( i = 0; i < segCount; i++ )
      if ( charCode <= cmap4->segments[i].endCount )
        break;

    /* Safety check - even though the last endCount should be 0xFFFF */
    if ( i >= segCount )
      return 0;

    seg4 = cmap4->segments[i];

    if ( charCode < seg4.startCount )
      return 0;

    if ( seg4.idRangeOffset == 0 )
      return ( charCode + seg4.idDelta ) & 0xFFFF;
    else
    {
      index1 = seg4.idRangeOffset / 2 + (charCode - seg4.startCount) -
               (segCount - i);

      if ( index1 < cmap4->numGlyphId )
      {
        if ( cmap4->glyphIdArray[index1] == 0 )
          return 0;
        else
          return ( cmap4->glyphIdArray[index1] + seg4.idDelta ) & 0xFFFF;
      }
      else
        return 0;
    }
  }


/*******************************************************************
 *
 *  Function    : code_to_index6
 *
 *  Description : Converts the character code into a glyph index.
 *                Uses format 6.
 *
 *  Input  :  charCode      the wanted character code
 *            cmap6         a pointer to a cmap table in format 6
 *
 *  Output :  Glyph index into the glyphs array.
 *            0 if the glyph does not exist (`missing character glyph').
 *
 ******************************************************************/

  static UShort  code_to_index6( UShort  charCode,
                                 PCMap6  cmap6 )
  {
    UShort firstCode;


    firstCode = cmap6->firstCode;

    if ( charCode < firstCode )
      return 0;

    if ( charCode >= (firstCode + cmap6->entryCount) )
      return 0;

    return cmap6->glyphIdArray[charCode - firstCode];
  }


/* END */
 

TTCMAP.H  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttcmap.h                                                    1.0
 *
 *    TrueType Character Mappings
 *
 *  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 TTCMAP_H
#define TTCMAP_H

#include "ttconfig.h"
#include "tttypes.h"


#ifdef __cplusplus
  extern "C" {
#endif

  /* format 0 */

  struct  TCMap0_
  {
    PByte  glyphIdArray;
  };

  typedef struct TCMap0_  TCMap0;
  typedef TCMap0*         PCMap0;


  /* format 2 */

  struct  TCMap2SubHeader_
  {
    UShort  firstCode;      /* first valid low byte         */
    UShort  entryCount;     /* number of valid low bytes    */
    Short   idDelta;        /* delta value to glyphIndex    */
    UShort  idRangeOffset;  /* offset from here to 1st code */
  };

  typedef struct TCMap2SubHeader_  TCMap2SubHeader;
  typedef TCMap2SubHeader*         PCMap2SubHeader;

  struct  TCMap2_
  {
    PUShort subHeaderKeys;
    /* high byte mapping table     */
    /* value = subHeader index * 8 */

    PCMap2SubHeader  subHeaders;
    PUShort          glyphIdArray;
    UShort           numGlyphId;        /* control value */
  };

  typedef struct TCMap2_  TCMap2;
  typedef TCMap2*         PCMap2;


  /* format 4 */

  struct  TCMap4Segment_
  {
    UShort  endCount;
    UShort  startCount;
    Short   idDelta;        /* in the specs defined as UShort but the
                               example there gives negative values... */
    UShort  idRangeOffset;
  };

  typedef struct TCMap4Segment_  TCMap4Segment;
  typedef TCMap4Segment*         PCMap4Segment;

  struct  TCMap4_
  {
    UShort  segCountX2;     /* number of segments * 2       */
    UShort  searchRange;    /* these parameters can be used */
    UShort  entrySelector;  /* for a binary search          */
    UShort  rangeShift;

    PCMap4Segment  segments;
    PUShort        glyphIdArray;
    UShort         numGlyphId;          /* control value */
  };

  typedef struct TCMap4_  TCMap4;
  typedef TCMap4*         PCMap4;


  /* format 6 */

  struct  TCMap6_
  {
    UShort   firstCode;      /* first character code of subrange      */
    UShort   entryCount;     /* number of character codes in subrange */

    PUShort  glyphIdArray;
  };

  typedef struct TCMap6_  TCMap6;
  typedef TCMap6*         PCMap6;


  /* charmap table */

  struct  TCMapTable_
  {
    UShort  platformID;
    UShort  platformEncodingID;
    UShort  format;
    UShort  length;
    UShort  version;

    Bool    loaded;
    ULong   offset;

    union
    {
      TCMap0  cmap0;
      TCMap2  cmap2;
      TCMap4  cmap4;
      TCMap6  cmap6;
    } c;
  };

  typedef struct TCMapTable_  TCMapTable;
  typedef TCMapTable*         PCMapTable;

  /* Load character mappings directory when face is loaded. */
  /* The mappings themselves are only loaded on demand.     */

  LOCAL_DEF
  TT_Error  CharMap_Load( PCMapTable  table,
                          TT_Stream  input );


  /* Destroy one character mapping table */

  LOCAL_DEF
  TT_Error  CharMap_Free( PCMapTable  table );


  /* Use character mapping table to perform mapping */

  LOCAL_DEF
  UShort  CharMap_Index( PCMapTable  cmap,
                         UShort      charCode );

  /* NOTE: The PFace type isn't defined at this point */

#ifdef __cplusplus
  }
#endif

#endif /* TTCMAP_H */


/* END */
 

TTCOMMON.H   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

    /*----------------------------
     common stand type
    ----------------------------*/
    //#define byte     unsigned char
    //#define word     unsigned short int
    //#define sword    short int
    //#define dword    unsigned int
   
TTCONFIG.H  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttconfig.h                                                1.0
 *
 *    Configuration settings header file (spec only).
 *
 *  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.
 *
 *  Notes:
 *
 *    All the configuration #define statements have been gathered in
 *    this file to allow easy check and modification.
 *
 ******************************************************************/

#ifndef TTCONFIG_H
#define TTCONFIG_H

/* ------------ auto configuration ------------------------------------- */


/*************************************************************************/
/* Here we include the file ft_conf.h for system dependent stuff.        */
/* The specific makefile is responsible for providing the right path to  */
/* this file.                                                            */

#include "ft_conf.h"


/**************************************************************************/
/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe        */
/* version of the library.                                                */

/* #define TT_CONFIG_OPTION_THREAD_SAFE */

/* ------------ general debugging -------------------------------------- */


/*************************************************************************
 *
 *  There are now three debugging modes:
 *
 *  - trace mode:
 *
 *       Error and trace messages are sent to the log file
 *       (which can be the standard error output).  Define
 *       DEBUG_LEVEL_TRACE to enable this mode.
 *
 *  - error mode:
 *
 *       Only error messages are generated.  Define
 *       DEBUG_LEVEL_ERROR to enable this mode.
 *
 *  - release mode:
 *
 *       Error messages are neither sent nor generated. The code is
 *       free from any debugging parts.
 *
 *
 * Note that you should link the engine with the 'ttdebug' component.
 * in case either DEBUG_LEVEL_TRACE or DEBUG_LEVEL_ERROR is defined.
 *
 * Please consult ttdebug.h for more details.                           */

/* #define DEBUG_LEVEL_TRACE */
/* #define DEBUG_LEVEL_ERROR */

/* ------------ special debugging -------------------------------------- */


/*************************************************************************/
/* Define this if you want to generate a special debug version of the    */
/* rasterizer.  This will progressively draw the glyphs while the        */
/* computations are done directly on the graphics screen... (with        */
/* inverted glyphs).                                                     */
/*                                                                       */
/* Use it at your own risk!  It is not maintained currently.             */
/*                                                                       */
/* IMPORTANT: This is reserved to developers willing to debug the        */
/*            rasterizer, which seems working very well in its           */
/*            current state...                                           */

/* #define DEBUG_RASTER */


/*************************************************************************/
/* Define this to have a simple debugger version of RunIns().            */
/*                                                                       */
/* Use it at your own risk!  It is not maintained currently.             */

/* #define DEBUG_INTERPRETER */


/*************************************************************************/
/* Define this to have some housekeeping of allocation and deallocation. */
/*                                                                       */
/* Please note that probably not all OS-specific versions of ttmemory.c  */
/* provide this functionality.                                           */

/* #define DEBUG_MEMORY */


/*************************************************************************/
/* Define this to have bounds checking for file buffer frames.           */
/*                                                                       */
/* Please note that probably not all OS-specific versions of ttfile.c    */
/* provide this functionality.                                           */

/* #define DEBUG_FILE */

/* ------------ arithmetic and processor support ----------------------- */


/*************************************************************************/
/* Define TT_USE_LONG_LONG if you want to enable the use of the          */
/* 'long long' 64-bit type provided by gcc and other compilers. Note     */
/* that :                                                                */
/*                                                                       */
/*   1. The type isn't ANSI, and thus will produce many warnings         */
/*      during library compilation.                                      */
/*                                                                       */
/*   2. Though the generated object files are slightly smaller, the      */
/*      resulting executables are bigger of about 4Kb! gcc must be       */
/*      linking some extra code in there!                                */
/*                                                                       */
/*   3. There is really no speed gain in doing so (but it may help       */
/*      debug the ttcalc component).                                     */
/*                                                                       */
/* IMPORTANT NOTE: You don't need to define it on 64-bits machines!      */
/*                                                                       */
/* NOTE 2 : This flag used to be _GNUC_LONG64_                           */

/* #define TT_USE_LONG_LONG */


/*************************************************************************/
/* define ALIGNMENT to your processor/environment preferred alignment    */
/* size. A value of 8 should work on all current processors, even        */
/* 64-bits ones.                                                         */

#define ALIGNMENT 8

/* --------------- miscellaneous ----------------------------------- */


/*********************************************************************/
/* The number of extensions available.  Don't change this value      */
/* except if you add new extensions to the engine.                   */

#define TT_MAX_EXTENSIONS  8

/* --------------- automatic setup -- don't touch ------------------ */


/*********************************************************************/
/* If HAVE_TT_TEXT is defined we don't provide a default typedef for */
/* defining TT_Text.                                                 */

#ifndef HAVE_TT_TEXT
#define HAVE_TT_TEXT
  typedef char  TT_Text;
#endif


/*********************************************************************/
/* We define NULL in case it's not defined yet.  The default         */
/* location is stdlib.h.                                             */

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif


/*********************************************************************/
/* Some systems can't use vfprintf for error messages on stderr; if  */
/* HAVE_PRINT_FUNCTION is defined, the Print macro must be supplied  */
/* externally (having the same parameters).                          */
/*                                                                   */
/* This is only used by the "ttdebug" component, which should be     */
/* linked to the engine only in debug mode.                          */

#if defined( DEBUG_LEVEL_TRACE ) || defined( DEBUG_LEVEL_ERROR )
#ifndef HAVE_PRINT_FUNCTION
#define Print( format, ap )  vfprintf( stderr, (format), (ap) )
#endif
#endif


/********************************************************************/
/*                                                                  */
/* I have added the ability to compile the library into a single    */
/* object file. This gets rids of all the external symbols defined  */
/* in each  component interface, and de-pollutes the name-space.    */
/*                                                                  */
/* I use two macros, namely LOCAL_FUNC and LOCAL_DEF, which only    */
/* apply to functions that are internal to the engine, and          */
/* should never be seen or linked by a client application.          */
/*                                                                  */
/*  LOCAL_DEF   used in header (.h) files, to define a function     */
/*              that will be seen by other components. This         */
/*              translates to "extern" in normal mode, and to       */
/*              "static" in single-object mode.                     */
/*                                                                  */
/*  LOCAL_FUNC  used in implementation (.c) files, just before      */
/*              the function body. This translates to nothing       */
/*              in normal mode, and to "static" in single-object    */
/*              mode.                                               */
/*                                                                  */
/*  Getting rid of un-necessary symbols makes the "ttcommon"        */
/*  renaming macros hack unnecessary. Moreover, the stripped        */
/*  single object file (freetype.o) is 52 Kb, instead of the        */
/*  previous 57 Kb (size of all combined .o files), and gives       */
/*  a better idea of the engine's real code size.                   */
/*                                                                  */
/*  It is called a "MAKE_OPTION" because the macro must be          */
/*  defined in the Makefile, rather than this one. It allows        */
/*  any developer to quickly switch from one mode to the other      */
/*  without messing with "ttconfig.h" each time.                    */
/*                                                                  */
#ifndef TT_MAKE_OPTION_SINGLE_OBJECT
#define LOCAL_FUNC  /* void */
#define LOCAL_DEF   extern
#else
#define LOCAL_FUNC  static
#define LOCAL_DEF   static
#endif


/*************************************************************************/
/* Define EXPORT_DEF and EXPORT_FUNC as needed to build e.g. a DLL.  All */
/* variables and functions visible from outside have these prefixes.     */

#ifndef EXPORT_DEF
#define EXPORT_DEF  extern
#endif

#ifndef EXPORT_FUNC
#define EXPORT_FUNC  /* void */
#endif

/* -------------- internal (developer) configuration toggles ------------ */


#undef TT_STATIC_INTERPRETER
/* Do not undefine this configuration macro. It is now a default that */
/* must be kept in all release builds.                                */


#undef TT_STATIC_RASTER
/* Define this if you want to generate a static raster.  This makes */
/* a non re-entrant version of the scan-line converter, which is    */
/* about 10% faster and 50% bigger than an indirect one!            */


#endif /* TTCONFIG_H */


/* END */
 

TTDEBUG.C   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* Simple debugging component. Temporary */

#include "ttdebug.h"
#include "tttables.h"
#include "ttobjs.h"


#ifdef DEBUG_LEVEL_TRACE
  char  tt_trace_levels[trace_max];
#endif

#if defined( DEBUG_LEVEL_ERROR ) || defined( DEBUG_LEVEL_TRACE )

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


  static String  tempStr[128];

  static const String*  OpStr[256] =
  {
    "SVTCA y",       /* Set vectors to coordinate axis y    */
    "SVTCA x",       /* Set vectors to coordinate axis x    */
    "SPvTCA y",      /* Set Proj. vec. to coord. axis y     */
    "SPvTCA x",      /* Set Proj. vec. to coord. axis x     */
    "SFvTCA y",      /* Set Free. vec. to coord. axis y     */
    "SFvTCA x",      /* Set Free. vec. to coord. axis x     */
    "SPvTL //",      /* Set Proj. vec. parallel to segment  */
    "SPvTL +",       /* Set Proj. vec. normal to segment    */
    "SFvTL //",      /* Set Free. vec. parallel to segment  */
    "SFvTL +",       /* Set Free. vec. normal to segment    */
    "SPvFS",         /* Set Proj. vec. from stack           */
    "SFvFS",         /* Set Free. vec. from stack           */
    "GPV",           /* Get projection vector               */
    "GFV",           /* Get freedom vector                  */
    "SFvTPv",        /* Set free. vec. to proj. vec.        */
    "ISECT",         /* compute intersection                */

    "SRP0",          /* Set reference point 0               */
    "SRP1",          /* Set reference point 1               */
    "SRP2",          /* Set reference point 2               */
    "SZP0",          /* Set Zone Pointer 0                  */
    "SZP1",          /* Set Zone Pointer 1                  */
    "SZP2",          /* Set Zone Pointer 2                  */
    "SZPS",          /* Set all zone pointers               */
    "SLOOP",         /* Set loop counter                    */
    "RTG",           /* Round to Grid                       */
    "RTHG",          /* Round to Half-Grid                  */
    "SMD",           /* Set Minimum Distance                */
    "ELSE",          /* Else                                */
    "JMPR",          /* Jump Relative                       */
    "SCvTCi",        /* Set CVT                             */
    "SSwCi",         /*                                     */
    "SSW",           /*                                     */

    "DUP",
    "POP",
    "CLEAR",
    "SWAP",
    "DEPTH",
    "CINDEX",
    "MINDEX",
    "AlignPTS",
    "INS_$28",
    "UTP",
    "LOOPCALL",
    "CALL",
    "FDEF",
    "ENDF",
    "MDAP[-]",
    "MDAP[r]",

    "IUP[y]",
    "IUP[x]",
    "SHP[0]",
    "SHP[1]",
    "SHC[0]",
    "SHC[1]",
    "SHZ[0]",
    "SHZ[1]",
    "SHPIX",
    "IP",
    "MSIRP[0]",
    "MSIRP[1]",
    "AlignRP",
    "RTDG",
    "MIAP[-]",
    "MIAP[r]",

    "NPushB",
    "NPushW",
    "WS",
    "RS",
    "WCvtP",
    "RCvt",
    "GC[0]",
    "GC[1]",
    "SCFS",
    "MD[0]",
    "MD[1]",
    "MPPEM",
    "MPS",
    "FlipON",
    "FlipOFF",
    "DEBUG",

    "LT",
    "LTEQ",
    "GT",
    "GTEQ",
    "EQ",
    "NEQ",
    "ODD",
    "EVEN",
    "IF",
    "EIF",
    "AND",
    "OR",
    "NOT",
    "DeltaP1",
    "SDB",
    "SDS",

    "ADD",
    "SUB",
    "DIV",
    "MUL",
    "ABS",
    "NEG",
    "FLOOR",
    "CEILING",
    "ROUND[G]",
    "ROUND[B]",
    "ROUND[W]",
    "ROUND[?]",
    "NROUND[G]",
    "NROUND[B]",
    "NROUND[W]",
    "NROUND[?]",

    "WCvtF",
    "DeltaP2",
    "DeltaP3",
    "DeltaC1",
    "DeltaC2",
    "DeltaC3",
    "SROUND",
    "S45Round",
    "JROT",
    "JROF",
    "ROFF",
    "INS_$7B",
    "RUTG",
    "RDTG",
    "SANGW",
    "AA",

    "FlipPT",
    "FlipRgON",
    "FlipRgOFF",
    "INS_$83",
    "INS_$84",
    "ScanCTRL",
    "SDPVTL[0]",
    "SDPVTL[1]",
    "GetINFO",
    "IDEF",
    "ROLL",
    "MAX",
    "MIN",
    "ScanTYPE",
    "IntCTRL",
    "INS_$8F",

    "INS_$90",
    "INS_$91",
    "INS_$92",
    "INS_$93",
    "INS_$94",
    "INS_$95",
    "INS_$96",
    "INS_$97",
    "INS_$98",
    "INS_$99",
    "INS_$9A",
    "INS_$9B",
    "INS_$9C",
    "INS_$9D",
    "INS_$9E",
    "INS_$9F",

    "INS_$A0",
    "INS_$A1",
    "INS_$A2",
    "INS_$A3",
    "INS_$A4",
    "INS_$A5",
    "INS_$A6",
    "INS_$A7",
    "INS_$A8",
    "INS_$A9",
    "INS_$AA",
    "INS_$AB",
    "INS_$AC",
    "INS_$AD",
    "INS_$AE",
    "INS_$AF",

    "PushB[0]",
    "PushB[1]",
    "PushB[2]",
    "PushB[3]",
    "PushB[4]",
    "PushB[5]",
    "PushB[6]",
    "PushB[7]",
    "PushW[0]",
    "PushW[1]",
    "PushW[2]",
    "PushW[3]",
    "PushW[4]",
    "PushW[5]",
    "PushW[6]",
    "PushW[7]",

    "MDRP[G]",
    "MDRP[B]",
    "MDRP[W]",
    "MDRP[?]",
    "MDRP[rG]",
    "MDRP[rB]",
    "MDRP[rW]",
    "MDRP[r?]",
    "MDRP[mG]",
    "MDRP[mB]",
    "MDRP[mW]",
    "MDRP[m?]",
    "MDRP[mrG]",
    "MDRP[mrB]",
    "MDRP[mrW]",
    "MDRP[mr?]",
    "MDRP[pG]",
    "MDRP[pB]",

    "MDRP[pW]",
    "MDRP[p?]",
    "MDRP[prG]",
    "MDRP[prB]",
    "MDRP[prW]",
    "MDRP[pr?]",
    "MDRP[pmG]",
    "MDRP[pmB]",
    "MDRP[pmW]",
    "MDRP[pm?]",
    "MDRP[pmrG]",
    "MDRP[pmrB]",
    "MDRP[pmrW]",
    "MDRP[pmr?]",

    "MIRP[G]",
    "MIRP[B]",
    "MIRP[W]",
    "MIRP[?]",
    "MIRP[rG]",
    "MIRP[rB]",
    "MIRP[rW]",
    "MIRP[r?]",
    "MIRP[mG]",
    "MIRP[mB]",
    "MIRP[mW]",
    "MIRP[m?]",
    "MIRP[mrG]",
    "MIRP[mrB]",
    "MIRP[mrW]",
    "MIRP[mr?]",
    "MIRP[pG]",
    "MIRP[pB]",

    "MIRP[pW]",
    "MIRP[p?]",
    "MIRP[prG]",
    "MIRP[prB]",
    "MIRP[prW]",
    "MIRP[pr?]",
    "MIRP[pmG]",
    "MIRP[pmB]",
    "MIRP[pmW]",
    "MIRP[pm?]",
    "MIRP[pmrG]",
    "MIRP[pmrB]",
    "MIRP[pmrW]",
    "MIRP[pmr?]"
  };


  const String* Cur_U_Line( void* _exec )
  {
    String  s[32];

    Int  op, i, n;

    PExecution_Context  exec;


    exec = _exec;

    op = exec->code[exec->IP];

    sprintf( tempStr, "%s", OpStr[op] );

    if ( op == 0x40 )
    {
      n = exec->code[exec->IP + 1];
      sprintf( s, "(%d)", n );
      strncat( tempStr, s, 8 );

      if ( n > 20 ) n = 20; /* limit output */

      for ( i = 0; i < n; i++ )
      {
        sprintf( s, " $%02hx", exec->code[exec->IP + i + 2] );
        strncat( tempStr, s, 8 );
      }
    }
    else if ( op == 0x41 )
    {
      n = exec->code[exec->IP + 1];
      sprintf( s, "(%d)", n );
      strncat( tempStr, s, 8 );

      if ( n > 20 ) n = 20; /* limit output */

      for ( i = 0; i < n; i++ )
      {
        sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 2],
                                    exec->code[exec->IP + i*2 + 3] );
        strncat( tempStr, s, 8 );
      }
    }
    else if ( (op & 0xF8) == 0xB0 )
    {
      n = op - 0xB0;

      for ( i = 0; i <= n; i++ )
      {
        sprintf( s, " $%02hx", exec->code[exec->IP + i + 1] );
        strncat( tempStr, s, 8 );
      }
    }
    else if ( (op & 0xF8) == 0xB8 )
    {
      n = op-0xB8;

      for ( i = 0; i <= n; i++ )
      {
        sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 1],
                                    exec->code[exec->IP + i*2 + 2] );
        strncat( tempStr, s, 8 );
      }
    }

    return (String*)tempStr;
  }


  /* the Print() function is defined in ttconfig.h;  */
  /* it defaults to vprintf on systems which have it */

  void  TT_Message( const String*  fmt, ... )
  {
    va_list  ap;

    va_start( ap, fmt );
    Print( fmt, ap );
    va_end( ap );
  }


  void  TT_Panic( const String*  fmt, ... )
  {
    va_list  ap;

    va_start( ap, fmt );
    Print( fmt, ap );
    va_end( ap );

    exit( EXIT_FAILURE );
  }

#endif /* defined( DEBUG_LEVEL_ERROR ) || defined( DEBUG_LEVEL_TRACE ) */

#if defined( DEBUG_LEVEL_TRACE )

  /* use this function to set the values of tt_trace_levels */

  void  set_tt_trace_levels( int  index, char  value )
  {
    tt_trace_levels[index] = value;
  }

#endif

/* END */
 

TTDEBUG.H   、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttdebug.h
 *
 *    Debugging and Logging component (specification)
 *
 *  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.
 *
 *
 *  This component contains various macros and functions used to
 *  ease the debugging of the FreeType engine. Its main purpose
 *  is in assertion checking, tracing, and error detection.
 *
 *  There are now three debugging modes:
 *
 *  - trace mode:
 *
 *       Error and trace messages are sent to the log file
 *       (which can be the standard error output).  Define
 *       DEBUG_LEVEL_TRACE to enable this mode.
 *
 *  - error mode:
 *
 *       Only error messages are generated.  Define
 *       DEBUG_LEVEL_ERROR to enable this mode.
 *
 *  - release mode:
 *
 *       Error messages are neither sent nor generated. The code is
 *       free from any debugging parts.
 *
 ******************************************************************/

#ifndef TTDEBUG_H
#define TTDEBUG_H

#include "ttconfig.h"
#include "tttypes.h"


#ifdef __cplusplus
  extern "C" {
#endif


#if defined( DEBUG_LEVEL_TRACE )

  typedef enum Trace_Component_
  {
    trace_any = 0,
    trace_api,
    trace_interp,
    trace_load,
    trace_gload,
    trace_memory,
    trace_file,
    trace_mutex,
    trace_cache,
    trace_calc,
    trace_cmap,
    trace_extend,
    trace_objs,
    trace_raster,

    trace_bitmap,
    trace_max

  } Trace_Component;


  /* Here we define an array to hold the trace levels per component. */
  /* Since it is globally defined, all array members are set to 0.   */
  /* You should set the values in this array either in your program  */
  /* or with your debugger.                                          */
  /*                                                                 */
  /* Currently, up to eight levels (PTRACE0-PTRACE7, see below) are  */
  /* used in some parts of the engine.                               */
  /*                                                                 */
  /* For example, to have all tracing messages in the raster         */
  /* component, say                                                  */
  /*                                                                 */
  /*   #define DEBUG_LEVEL_TRACE                                     */
  /*   #include "ttdebug.h"                                          */
  /*                                                                 */
  /*   ...                                                           */
  /*   set_tt_trace_levels( trace_raster, 7 )                        */
  /*                                                                 */
  /* in your code before initializing the FreeType engine.           */
  /*                                                                 */
  /* Maybe it is better to define DEBUG_LEVEL_TRACE in ttconfig.h... */

  extern char  tt_trace_levels[trace_max];

  /* IMPORTANT:                                                 */
  /*                                                            */
  /*  Each component must define the macro TT_COMPONENT         */
  /*  to a valid Trace_Component value before using any         */
  /*  PTRACEx macro.                                            */
  /*                                                            */

#define  PTRACE( level, varformat )  \
         if ( tt_trace_levels[TT_COMPONENT] >= level ) TT_Message##varformat

#elif defined( DEBUG_LEVEL_ERROR )

#define  PTRACE( level, varformat )  /* nothing */

#else  /* RELEASE MODE */

#define TT_Assert( condition, action )  /* nothing */

#define PTRACE( level, varformat )      /* nothing */
#define PERROR( varformat )             /* nothing */
#define PANIC( varformat )              /* nothing */

#endif


/************************************************************************/
/*                                                                      */
/*  Define macros and fuctions that are common to the debug and trace   */
/*  modes.                                                              */
/*                                                                      */

#if defined( DEBUG_LEVEL_TRACE ) || defined( DEBUG_LEVEL_ERROR )


#define TT_Assert( condition, action )  if ( !(condition) ) ( action )

  void  TT_Message( const String*  fmt, ... );
  void  TT_Panic  ( const String*  fmt, ... );
  /* print a message and exit */

  const String*  Cur_U_Line( void*  exec );

#define PERROR( varformat )  TT_Message##varformat
#define PANIC( varformat )   TT_Panic##varformat

#endif

#if defined( DEBUG_LEVEL_TRACE )

  void  set_tt_trace_levels( int  index, char  value );

#endif


#define  PTRACE0( varformat )  PTRACE( 0, varformat )
#define  PTRACE1( varformat )  PTRACE( 1, varformat )
#define  PTRACE2( varformat )  PTRACE( 2, varformat )
#define  PTRACE3( varformat )  PTRACE( 3, varformat )
#define  PTRACE4( varformat )  PTRACE( 4, varformat )
#define  PTRACE5( varformat )  PTRACE( 5, varformat )
#define  PTRACE6( varformat )  PTRACE( 6, varformat )
#define  PTRACE7( varformat )  PTRACE( 7, varformat )


#ifdef __cplusplus
  }
#endif


#endif /* TTDEBUG_H */
 

TTENGINE.H  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttengine.h                                                   1.1
 *
 *    Engine instance structure definition.
 *
 *  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.
 *
 *  New in 1.1 :
 *
 *    - added the 'raster_lock' mutex field to synchronize
 *      scan-line conversion in thread-safe and re-entrant builds.
 *
 ******************************************************************/

#ifndef TTENGINE_H
#define TTENGINE_H

#include "tttypes.h"
#include "ttconfig.h"
#include "freetype.h"
#include "ttmutex.h"

#ifdef __cplusplus
  extern "C" {
#endif

  /********************************************************************/
  /*                                                                  */
  /*  The freetype engine instance structure.                         */
  /*                                                                  */
  /*  This structure holds all the data that is necessary to run      */
  /*  one instance of the freetype engine.  It is needed to get a     */
  /*  completely re-entrant version of the library.                   */
  /*                                                                  */
  /*  The goal is to move _all_ component-specific variables, either  */
  /*  static or global in the structure; the component initializers   */
  /*  and finalizers will all be called with the address of a valid   */
  /*  TEngine_Instance.                                               */
  /*                                                                  */
  /********************************************************************/

  struct  TEngine_Instance_
  {
     TMutex  lock;               /* engine lock */

     void*   list_free_elements;

     void*   objs_face_class;       /* the face cache class     */
     void*   objs_instance_class;   /* the instance cache class */
     void*   objs_execution_class;  /* the context cache class  */
     void*   objs_glyph_class;      /* the glyph cache class    */

     void*   objs_face_cache;  /* these caches are used to track */
     void*   objs_exec_cache;  /* the current face and execution */
                               /* context objects                */

     void*   file_component;    /* ttfile implementation dependent   */

     TMutex  raster_lock;       /* mutex for this engine's render pool   */
     void*   raster_component;  /* ttraster implementation depedent      */
     Byte    raster_palette[5]; /* gray-levels palette for anti-aliasing */

     void*   extension_component;  /* extensions dependent */

#if 0
     TT_Glyph_Loader_Callback  glCallback; /* glyph loader callback, if any */
#endif
  };

  /* NOTE : The raster's lock is only acquired by the Render_Glyph and     */
  /*        Render_Gray_Glyph functions, which always release it on exit   */
  /*        They do not lock the engine mutex. This means you shouldn't    */
  /*        be concerned about deadlocks between the two mutexes, as these */
  /*        should never appear..                                          */

  typedef struct TEngine_Instance_  TEngine_Instance;
  typedef TEngine_Instance*         PEngine_Instance;


#ifdef TT_CONFIG_OPTION_THREAD_SAFE  /* for re-entrant builds */

#define ENGINE_ARG    TEngine_Instance*  _engine
#define ENGINE_ARGS   TEngine_Instance*  _engine,

#define ENGINE_VAR   _engine
#define ENGINE_VARS  _engine,

#define ENGINE  _engine

#else                       /* for thread-safe builds */

#define ENGINE_ARG    /* void */
#define ENGINE_ARGS

#define ENGINE_VAR
#define ENGINE_VARS

#endif /* TT_CONFIG_OPTION_THREAD_SAFE */

#ifdef __cplusplus
  }
#endif

#endif /* TTENGINE_H */


/* END */
 

TTEXTEND.C   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttextend.h                                                   2.0
 *
 *    Extensions Interface
 *
 *  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.
 *
 *  This is an updated version of the extension component, now
 *  located in the main library's source directory.  It allows
 *  the dynamic registration/use of various face object extensions
 *  through a simple API.
 *
 ******************************************************************/

#include "ttextend.h"
#include "ttengine.h"
#include "ttmemory.h"

/* required by the tracing mode */
#undef  TT_COMPONENT
#define TT_COMPONENT      trace_extend


  struct TExtension_Registry_
  {
    Int               num_extensions;
    Long              cur_offset;
    TExtension_Class  classes[TT_MAX_EXTENSIONS];
  };

  typedef struct TExtension_Registry_  TExtension_Registry;
  typedef TExtension_Registry*         PExtension_Registry;

  /* Initialize the extension component */

  LOCAL_FUNC
  TT_Error  TTExtend_Init( PEngine_Instance  engine )
  {
    TT_Error             error;
    PExtension_Registry  exts;


    if ( ALLOC( exts, sizeof ( TExtension_Registry ) ) )
      return error;

    exts->num_extensions        = 0;
    exts->cur_offset            = 0;
    engine->extension_component = (void*)exts;

    return TT_Err_Ok;
  }


  /* Finalize the extension component */

  LOCAL_FUNC
  TT_Error  TTExtend_Done( PEngine_Instance  engine )
  {
    FREE( engine->extension_component );
    return TT_Err_Ok;
  }


  /* Register a new extension */

  EXPORT_FUNC
  TT_Error  TT_Register_Extension( PEngine_Instance  engine,
                                   Long              id,
                                   Long              size,
                                   PExt_Constructor  create,
                                   PExt_Destructor   destroy )
  {
    PExtension_Registry  exts;
    PExtension_Class     clazz;
    Int                  p;


    exts = (PExtension_Registry)engine->extension_component;
    if ( !exts )
      return TT_Err_Ok;

    p = exts->num_extensions;

    if ( p >= TT_MAX_EXTENSIONS )
      return TT_Err_Too_Many_Extensions;

    clazz          = exts->classes + p;
    clazz->id      = id;
    clazz->size    = size;
    clazz->build   = create;
    clazz->destroy = destroy;

    clazz->offset  = exts->cur_offset;

    exts->num_extensions++;
    exts->cur_offset += ( size + ALIGNMENT-1 ) & -ALIGNMENT;

    return TT_Err_Ok;
  }


  /* Query an extension block by extension_ID */

  EXPORT_FUNC
  TT_Error  TT_Extension_Get( PFace   face,
                              Long    extension_id,
                              void**  extension_block )
  {
    PExtension_Registry  registry;
    PExtension_Class     clazz;
    Int                  n;


    if ( !face->extension )
      return TT_Err_Extensions_Unsupported;

    registry = (PExtension_Registry)face->engine->extension_component;

    for ( n = 0; n < face->n_extensions; n++ )
    {
      clazz = registry->classes + n;
      if ( clazz->id == extension_id )
      {
        *extension_block = (PByte)face->extension + clazz->offset;
        return TT_Err_Ok;
      }
    }

    return TT_Err_Invalid_Extension_Id;
  }


  /* Destroy all extensions within a face object.  Called by the */
  /* face object destructor.                                     */

  LOCAL_FUNC
  TT_Error  Extension_Destroy( PFace  face )
  {
    PEngine_Instance     engine = face->engine;
    PExtension_Registry  registry;
    PExtension_Class     clazz;
    Int                  n;
    PByte                ext;


    registry = (PExtension_Registry)engine->extension_component;

    for ( n = 0; n < face->n_extensions; n++ )
    {
      clazz = registry->classes + n;
      ext   = (PByte)face->extension + clazz->offset;

      /* the destructor is optional */
      if ( clazz->destroy )
        clazz->destroy( (void*)ext, face );
    }

    /* destroy the face's extension block too */
    FREE( face->extension );
    face->n_extensions = 0;

    return TT_Err_Ok;
  }


  /* Create an extension within a face object.  Called by the */
  /* face object constructor.                                 */

  LOCAL_FUNC
  TT_Error  Extension_Create( PFace  face )
  {
    PEngine_Instance     engine = face->engine;
    PExtension_Registry  registry;
    PExtension_Class     clazz;
    TT_Error             error;
    Int                  n;
    PByte                ext;


    registry = (PExtension_Registry)engine->extension_component;

    face->n_extensions = registry->num_extensions;
    if ( ALLOC( face->extension, registry->cur_offset ) )
      return error;

    for ( n = 0; n < face->n_extensions; n++ )
    {
      clazz = registry->classes + n;
      ext   = (PByte)face->extension + clazz->offset;
      error = clazz->build( (void*)ext, face );
      if ( error )
        goto Fail;
    }
    return TT_Err_Ok;

  Fail:
    Extension_Destroy( face );
    return error;
  }


/* END */
 

TTEXTEND.H     、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttextend.h                                                   2.0
 *
 *    Extensions Interface.
 *
 *  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.
 *
 *  This is an updated version of the extension component, now
 *  located in the main library's source directory.  It allows
 *  the dynamic registration/use of various face object extensions
 *  through a simple API.
 *
 ******************************************************************/

#ifndef TTEXTEND_H
#define TTEXTEND_H

#include "ttconfig.h"
#include "tttypes.h"
#include "ttobjs.h"


#ifdef __cplusplus
  extern "C" {
#endif

  /* The extensions don't need to be integrated at compile time into */
  /* the engine, only at link time.                                  */


  /* When a new face object is created, the face constructor calls */
  /* the extension constructor with the following arguments:       */
  /*                                                               */
  /*   ext  : typeless pointer to the face's extension block.      */
  /*          Its size is the one given at registration time       */
  /*          in the extension class's 'size' field.               */
  /*                                                               */
  /*   face : the parent face object.  Note that the extension     */
  /*          constructor is called when the face object is        */
  /*          built.                                               */

  typedef TT_Error  TExt_Constructor( void*  ext, PFace  face );


  /* When a face object is destroyed, the face destructor calls    */
  /* the extension destructor with the following arguments.        */
  /*                                                               */
  /*   ext  : typeless pointer to the face's extension block.      */
  /*          Its size is the one given at registration time       */
  /*          in the extension class's 'size' field.               */
  /*                                                               */
  /*   face : the parent face object.  Note that the extension     */
  /*          destructor is called before the actual face object   */
  /*          is destroyed.                                        */

  typedef TT_Error  TExt_Destructor ( void*  ext, PFace  face );

  typedef TExt_Constructor*  PExt_Constructor;
  typedef TExt_Destructor*   PExt_Destructor;


  struct TExtension_Class_
  {
    Long              id;      /* extension id                      */
    Long              size;    /* size in bytes of extension record */
    PExt_Constructor  build;   /* the extension's class constructor */
    PExt_Destructor   destroy; /* the extension's class destructor  */

    Long              offset;  /* offset of ext. record in face obj */
                               /* (set by the engine)               */
  };

  typedef struct TExtension_Class_  TExtension_Class;
  typedef TExtension_Class*         PExtension_Class;


#define Build_Extension_ID( a, b, c, d ) \
           ( ((ULong)(a) << 24) |        \
             ((ULong)(b) << 16) |        \
             ((ULong)(c) << 8 ) |        \
              (ULong)(d) )

  /*  A note regarding extensions and the single-object compilation    */
  /*  mode :                                                           */
  /*                                                                   */
  /*  When the engine is compiled as a single object file, extensions  */
  /*  must remain linkable *after* compile time. In order to do this,  */
  /*  we need to export the functions that an extension may need.      */
  /*  Fortunately, we can limit ourselves to :                         */
  /*                                                                   */
  /*  o TT_Register_Extension (previously called Extension_Register)   */
  /*        which is to be called by each extension on within          */
  /*        it TT_Init_XXXX_Extension initializer.                     */
  /*                                                                   */
  /*  o File and frame access functions. Fortunately, these already    */
  /*    have their names prefixed by "TT_", so no change was needed    */
  /*    except replacing the LOCAL_DEF keyword with EXPORT_DEF         */
  /*                                                                   */
  /*  o Memory access functions, i.e. TT_Alloc and TT_Free. Again,     */
  /*    the change is minimal                                          */
  /*                                                                   */
  /*  o the table-lookup function : TT_LookUp_Table, formerly known    */
  /*    as Load_TrueType_Table in ttload.c.                            */
  /*                                                                   */
  /*                                                                   */
  /*  Other than that, an extension should be able to #include all     */
  /*  relevant header files to get access to internal types, but       */
  /*  should not call engine internal functions..                      */
  /*                                                                   */
  /*  If there is a need for a specific internal function call, let    */
  /*  me known to see if we need to export it by default..             */
  /*                                                         - DavidT  */
  /*                                                                   */

  /* Register a new extension.  Called by extension */
  /* service initializers.                          */
  EXPORT_DEF
  TT_Error  TT_Register_Extension( PEngine_Instance  engine,
                                   Long              id,
                                   Long              size,
                                   PExt_Constructor  create,
                                   PExt_Destructor   destroy );


#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
  /* Initialize the extension component */
  LOCAL_DEF
  TT_Error  TTExtend_Init( PEngine_Instance  engine );

  /* Finalize the extension component */
  LOCAL_DEF
  TT_Error  TTExtend_Done( PEngine_Instance  engine );

  /* Create an extension within a face object.  Called by the */
  /* face object constructor.                                 */
  LOCAL_DEF
  TT_Error  Extension_Create( PFace  face );

  /* Destroy all extensions within a face object.  Called by the */
  /* face object destructor.                                     */
  LOCAL_DEF
  TT_Error  Extension_Destroy( PFace  face );
#endif

  /* Query an extension block by extension_ID.  Called by extension */
  /* service routines.                                              */
  EXPORT_DEF
  TT_Error  TT_Extension_Get( PFace   face,
                              Long    extension_id,
                              void**  extension_block );

#ifdef __cplusplus
  }
#endif


#endif /* TTEXTEND_H */


/* END */
 

ttextout.c   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、


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

#include <stdlib.h>   
#include "XText.h"
#include "XComm.h"
#include "XGraphic.h"
#include "XCodePage.h"

#undef error
#define error error_

#include "freetype.h"
#include "ttobjs.h" 

#define UNICODE 1 
#define BIG5    4

#define LID_BIG5        0x404
#define LID_SHIFTJIS    0x411
#define LID_GB            0x408
#define LID_KOREA        0x412
#define LID_ENGLISH        0x409

    #define CODEPAGE_USE 0
    #define CODEPAGE_BRI 1
    #define CODEPAGE_GER 2
    #define CODEPAGE_FRE 3
    #define CODEPAGE_DAN 4
    #define CODEPAGE_ITA 5
    #define CODEPAGE_SPA 6
    #define CODEPAGE_SWE 7
    #define CODEPAGE_SWI 8
    #define CODEPAGE_437 9
    #define CODEPAGE_850 10
    #define CODEPAGE_852 11
    #define CODEPAGE_860 12
    #define CODEPAGE_863 13
    #define CODEPAGE_865 14
    #define CODEPAGE_857 15


    #if defined( TPH_DPI_200 )
    #define RESOLUTION 200
    #elif defined( TPH_DPI_300 )
    #define RESOLUTION 300
    #elif defined( TPH_DPI_600 )
    #define RESOLUTION 600
    #endif

  //char  Header[128];
    TT_Engine    engine={NULL};
    TT_Face      face={NULL};
    TT_Instance  instance;
    TT_Glyph     glyph;
    TT_CharMap   char_map;

    TT_Glyph_Metrics      ttf_metrics;
    TT_Outline            outline;
    TT_Face_Properties    properties;
    TT_Instance_Metrics    imetrics;
    TT_Matrix              matrix;
    TT_Raster_Map          Bit; 

    int    num_glyphs;

    int    ptsize;
    int    hinted;

    int    Fail;
    int    Num;

    int    gray_render;

    short  glyph_code[128];
    unsigned short  char_unicode[128];
    int    num_codes;         
    int    BearingY;                          
//  char    FaceName[13]="";
    int LanguageID;
  
    INT                (*lpTTFGetData)(BYTE * , INT);        // Get Data Function
    VOID            (*lpTTFSetDataPoint)(INT);            // Set Data Point Function
    LONG            (*lpTTFGetDataPoint)(VOID);
    LONG            (*lpTTFGetSize)(VOID);

//
// Convert an ASCII string to a string of glyph indexes.              
//                                                                    
  static void  CharToUnicode(_TextAttr* psTextAttr , int CodePage)
  {
    unsigned short  i, n, char_idx, *pCodePage;
    unsigned short  platform, encoding;
    TT_Error  error;
    BYTE* source;

    switch(CodePage)
    {
        case  CODEPAGE_437:
            pCodePage = (unsigned short *)CodePage437ToUnicode;
            break;
        case  CODEPAGE_850:
            pCodePage = (unsigned short *)CodePage850ToUnicode;
            break;
        case  CODEPAGE_852:
            pCodePage = (unsigned short *)CodePage852ToUnicode;
            break;
        case  CODEPAGE_860:
            pCodePage = (unsigned short *)CodePage860ToUnicode;
            break;
        case  CODEPAGE_863:
            pCodePage = (unsigned short *)CodePage863ToUnicode;
            break;
        case  CODEPAGE_865:
            pCodePage = (unsigned short *)CodePage865ToUnicode;
            break;
        case  CODEPAGE_857:
            pCodePage = (unsigned short *)CodePage857ToUnicode;
            break;
        default:
            pCodePage = (unsigned short *)CodePage850ToUnicode;
            break;
    }

    source = psTextAttr->pExp;
    
    // First, look for a Unicode charmap
    n = properties.num_CharMaps;
       LanguageID = LID_ENGLISH;

    for ( i = 0; i < n; i++ )
    {
      error = TT_Get_CharMap_ID( face, i, &platform, &encoding );
      if (  (platform == 3 && encoding == BIG5) || 
              (platform == 3 && encoding == UNICODE))
//              (encoding == UNICODE || encoding == BIG5))
      {
        TT_Get_CharMap( face, i, &char_map );
        i = n + 1;
        if(encoding == BIG5)
            LanguageID = LID_BIG5;
      }
    }

    //not suppose to happen
    //But it the font does not have unicode map, we display error here
    if ( i == n )
    {
        //  Panic( "Sorry, but this font doesn't contain any Unicode mapping table\n" );
        //    #if defined( LCD_MODEL )    
        //    ShowFont(0, 48, (BYTE *)"No Unicode map");
        //    #endif
            glyph_code[0]=0x20;glyph_code[1]=0x21;glyph_code[2]=0x22;
            glyph_code[3]=0x23;glyph_code[4]=0x24;
            num_codes = n;
            return;
    }

    i=0;

    for ( n = 0; n < 128 && source[n]; n++ )
    {
        if(source[n]&0x80 )
        {
            if(LanguageID == LID_BIG5 && encoding == UNICODE )
            {   
                //calc BIG5 table index
                //hi byte
                char_idx = (int)(source[n] - 0xA1) * 157;
                //lo byte
                if(source[n+1] >= 0xA1)
                    char_idx += source[n+1] - 0xA1 + 0x3f;
                else
                    char_idx += source[n+1] - 0x40;
                char_idx = BIG5ToUnicode[char_idx];
                n++;
            }
            else if(LanguageID == LID_GB && encoding == UNICODE )
            {
                char_idx = (int)(source[n] - 0x81) * 192;
                if(source[n+1] >= 0xA1)
                    char_idx += source[n+1] - 0xA1 + 0x3f;
                else
                    char_idx += source[n+1] - 0x40;
//                char_idx = GBToUnicode[char_idx];
                n++;
            }
            
            else
            {
                    char_idx = pCodePage[source[n] & 0xff];
            }
             glyph_code[i] = TT_Char_Index( char_map, char_idx );
        }
        else 
        {
            //char_idx = (short)source[n];
            char_idx = pCodePage[source[n] & 0xff];
            if( platform == 3 && encoding == 1 ) //unicode
                glyph_code[i] = TT_Char_Index( char_map, char_idx );
            else
                glyph_code[i] = char_idx + 1 ;
        }
      char_unicode[i] = char_idx;
      i++;
        
    }


    //for ( n = 0; n < 128 && source[n]; n++ )
    //{
    //  glyph_code[n] = TT_Char_Index( char_map, source[n]);
    //}
    num_codes = i;
  }


  TT_Error  Reset_Scale( int  pointSize )
  {
    TT_Error  error;

    if ( (error = TT_Set_Instance_PointSize( instance, pointSize )) )
    {
//      RestoreScreen();
//      printf( "error = 0x%x\n", (int)error );
//      Panic( "could not reset instance\n" );
    }

    TT_Get_Instance_Metrics( instance, &imetrics );

    return TT_Err_Ok;
  }


  static TT_Error  LoadTrueTypeChar( int  idx, int  hint )
  {
    int  flags;


    flags = TTLOAD_SCALE_GLYPH;
    if ( hint )
      flags |= TTLOAD_HINT_GLYPH;

    return TT_Load_Glyph( instance, glyph, idx, flags );
  }

  TT_Error   Render_0_Glyph(    TT_Glyph  glyph,
                                 int       x_offset,
                                 int       y_offset )
  {
    TT_Error  error;

      TT_Get_Glyph_Outline( glyph, &outline );
      
      matrix.xx = (TT_Fixed)(1 * (1L<<16));
      matrix.xy = (TT_Fixed)(0 * (1L<<16));
      matrix.yx = -matrix.xy;
      matrix.yy = -matrix.xx;

      TT_Transform_Outline( &outline, &matrix );
      TT_Translate_Outline( &outline, 0, BearingY);

      error =  TT_Get_Glyph_Bitmap( glyph, &Bit,
                                  (long)x_offset*64, (long)y_offset*64 );

    return error;                                  
  }


  TT_Error  Render_180_Glyph(    TT_Glyph  glyph,
                                 int       x_offset,
                                 int       y_offset )
  {
    TT_Error  error;

      TT_Get_Glyph_Outline( glyph, &outline );
      //TT_Translate_Outline( &outline, -xcenter*64L, -ycenter*64L );
      //0
      //matrix.xx = (TT_Fixed)(1 * (1L<<16));
      //matrix.xy = (TT_Fixed)(0 * (1L<<16));
      //matrix.yx = -matrix.xy;
      //matrix.yy = matrix.xx;
      //180
      matrix.xx = -(TT_Fixed)(1 * (1L<<16));
      matrix.xy = (TT_Fixed)(0 * (1L<<16));
      matrix.yx = -matrix.xy;
      matrix.yy = -matrix.xx;

      TT_Transform_Outline( &outline, &matrix );
      TT_Translate_Outline( &outline, 0, -BearingY);

      error = TT_Get_Glyph_Bitmap( glyph, &Bit,
                                  (long)x_offset*64, (long)y_offset*64 );
    return error;                                  
  }

  TT_Error  Render_90_Glyph(TT_Glyph  glyph,
                            int       x_offset,
                            int       y_offset )
  {
    TT_Error  error;

      TT_Get_Glyph_Outline( glyph, &outline );
      //TT_Translate_Outline( &outline, -xcenter*64L, -ycenter*64L );
      //0
      matrix.xx = (TT_Fixed)(0 * (1L<<16));
      matrix.xy = (TT_Fixed)(1 * (1L<<16));
      matrix.yx = matrix.xy;
      matrix.yy = matrix.xx;

      TT_Transform_Outline( &outline, &matrix );
      TT_Translate_Outline( &outline, -BearingY,0);

      error = TT_Get_Glyph_Bitmap( glyph, &Bit,
                                  (long)x_offset*64, (long)y_offset*64 );
    return error;                                  
  }


  TT_Error  Render_270_Glyph(    TT_Glyph  glyph,
                                 int       x_offset,
                                 int       y_offset )
  {
    TT_Error  error;
    
      TT_Get_Glyph_Outline( glyph, &outline );
      //TT_Translate_Outline( &outline, -xcenter*64L, -ycenter*64L );
      //0
      matrix.xx = (TT_Fixed)(0 * (1L<<16));
      matrix.xy = -(TT_Fixed)(1 * (1L<<16));
      matrix.yx = matrix.xy;
      matrix.yy = matrix.xx;

      TT_Transform_Outline( &outline, &matrix );
      TT_Translate_Outline( &outline, BearingY,0);

      error =  TT_Get_Glyph_Bitmap( glyph, &Bit,
                                  (long)x_offset*64, (long)y_offset*64 );
    return error;                                  
  }

extern char *_mnext;
extern MEMT  _pool;
extern MEMT  _memt;
char *pBuf;

/*============================================================*/
//#pragma section Image
/*============================================================*/
//char OurMemorySpace[POOL_SIZE];

/*============================================================*/
//#pragma section 
/*============================================================*/
void Display_Error(BYTE *FunctionName, TT_Error error)
{                          
  char buf[20];
  long j;
  
//    #if defined( LCD_MODEL )        
//    ShowFont(0, 0, FunctionName);
//    #endif
    if(error == TT_Err_Ok)
    {
    //    #if defined( LCD_MODEL )    
    //    ShowFont(0, 16, (BYTE *)"return OK    ");
    //    #endif
    }    
    else
    {
    //    #if defined( LCD_MODEL )    
    //    ShowFont(0, 16, (BYTE *)"return FAIL  ");
    //    #endif
        buf[0]='E'; buf[1]='R';buf[2]='R';buf[3]=':';
        buf[4] = error /256;
        if(buf[4] > 10)buf[4]+=0x41;
        else buf[4]+='0';
        buf[5] = (error & 0xff) / 16;
        if(buf[5] > 10)buf[5]+=0x41;
        else buf[5]+='0';
        buf[6] = (error & 0xf);
        if(buf[6] > 10)buf[6]+=0x41;
        else buf[6]+='0';
        buf[7] = buf[8] = ' '; buf[9] = 0;

    //    #if defined( LCD_MODEL )    
    //    ShowFont(0, 32, buf);
    //    #endif
    }
    j=0;
    while(j<95000000L)j++; 
}


MakeInt(char *buf,int num)
{
buf[3] = (num & 0xf);
if(buf[3] > 9) buf[3] += 'A' - 10;
else buf[3] += '0'; 
buf[2] = (num>>4) & 0xf;
if(buf[2] > 9) buf[2] += 'A'- 10;
else buf[2] += '0'; 
buf[1] = (num>>8) & 0xf;
if(buf[1] > 9) buf[1] += 'A'- 10;
else buf[1] += '0'; 
buf[0] = (num>>12) & 0xf;
if(buf[0] > 9) buf[0] += 'A'- 10;
else buf[0] += '0'; 
buf[4] = 0;
}


Bool Init_Engine( void )
{                    
    TT_Error  error;
    
//    //if initialized, simply return
//    if(engine.z)
//        return TRUE;
    
    //initialize memory pool management
    _pool.size = _memt.size = 0;
    _pool.top = _memt.top = NULL;

    if ( ( pBuf = malloc( POOL_SIZE ) ) == _NULL )
        return FALSE;
    _mnext = pBuf;
    _msize=POOL_SIZE;
    // Initialize engine 
    error = TT_Init_FreeType( &engine );

    if(error)
        return FALSE;
    else
        return TRUE;
        
}


int  TTOutText(_TextAttr* psTextAttr, _FontAttr* pFontAttr)
{
    int i;
    TT_F26Dot6  x, y;
    TT_Error  error;
    int Hodify_iY, Hodify_Height;

    char buf[20]; 
    int        iEraseHeight = 0;
    int     iEraseWidth = 0;

    if(!Init_Engine())
    {
        free ( pBuf );
        SendString("TTF malloc error");
        return FALSE;
    }
    
    lpTTFGetData = pFontAttr->lpGetData;
    lpTTFSetDataPoint = pFontAttr->lpSetDataPoint;
    lpTTFGetDataPoint = pFontAttr->lpGetDataPoint;
    lpTTFGetSize = pFontAttr->lpGetSize;
    
    //initialize our own image buffer attributes                           
    Bit.rows = psTextAttr->psImageBuffer->iHeight;
    Bit.cols = psTextAttr->psImageBuffer->iByteWidth;
    Bit.width = psTextAttr->psImageBuffer->iWidth;
    Bit.flow = TT_Flow_Up;//TT_Flow_Down;
    Bit.bitmap = psTextAttr->psImageBuffer->pBuffer;
    Bit.size = Bit.rows * Bit.cols;
               
    //hinted always
    hinted = 1;
    
//    if(strcmp(FaceName,psTextAttr->pFont))
//    {
//        //if some other font been used, close the font face
//        if(face.z)
//            TT_Close_Face(face);                           
                    
//        strcpy(FaceName,(char *)psTextAttr->pFont);
        // Load new face 
        error = TT_Open_Face( engine, (char *)psTextAttr->pFont, &face );
        if(error)
        {
            SendPrintf("TT_Open_Face:%d\r\n", error);
            free ( pBuf );
            return FALSE;
        }

        // get face properties and allocate preload arrays 
        TT_Get_Face_Properties( face, &properties );

        // create glyph 
        error = TT_New_Glyph( face, &glyph );
/*        if(error)
        {
            Send_String("TT_New_Glyph:");
            Send_Num(error);
            Send_String("\r\n");
            return -1;
        }*/

        // create instance
        error = TT_New_Instance( face, &instance );
/*        if(error)
        {
            Send_String("TT_New_Instance:");
            Send_Num(error);
            Send_String("\r\n");
            return -1;
        }*/

        // set resolution, we could use this to expand width
        error = TT_Set_Instance_Resolutions( instance, RESOLUTION, RESOLUTION );
/*        if(error)
        {
            Send_String("TT_Set_Instance_Resolution:");
            Send_Num(error);
            Send_String("\r\n");
            return -1;
        }*/

        // kcmark
        // set point size
        //if( psTextAttr->iRotation == 90 || psTextAttr->iRotation == 270)
        //    ptsize = psTextAttr->iHoriMulti;
        //else    
            ptsize = psTextAttr->iVertMulti;
        
        error = TT_Set_Instance_PointSize( instance, ptsize );
        if(error)
        {
            SendPrintf("TT_Set_Instance_PointSize:%d\r\n", error);
            free ( pBuf );
            return FALSE;
        }
        
//    }
//    else    //it's the same font
//    {
//        if(ptsize != psTextAttr->iVertMulti)
//        {
//            ptsize = psTextAttr->iVertMulti;
//            error = TT_Set_Instance_PointSize( instance, ptsize );
//        }
//    }
    
    // get glyph index for every byte in the input string
    CharToUnicode(psTextAttr, pFontAttr->iCodePage);
                 
    //get (x,y)
    x = psTextAttr->sCoord.iX;
    y = psTextAttr->sCoord.iY;
 

    i = TT_Char_Index( char_map, 'A'); //
    LoadTrueTypeChar( i, hinted );
    TT_Get_Glyph_Metrics( glyph, &ttf_metrics );
    BearingY = ttf_metrics.bbox.yMax;

    i = TT_Char_Index( char_map, 'y'); //
    LoadTrueTypeChar( i, hinted );
    TT_Get_Glyph_Metrics( glyph, &ttf_metrics );

    //for erase box
    iEraseHeight = (BearingY - ttf_metrics.bbox.yMin) >> 6;
    iEraseWidth = 0;

    //check OB (  )
    

    
    for ( i = 0; i < num_codes; i++ )
    {
      error = LoadTrueTypeChar( glyph_code[i], hinted );

      if(!error)
      {
        TT_Get_Glyph_Metrics( glyph, &ttf_metrics );

            switch(psTextAttr->iRotation)
            {
                case 0:
                    if(error = Render_0_Glyph  ( glyph, x, y ))
                    {
                    //    #if defined( LCD_MODEL )        
                    //        ShowFont(0, 32,"Glyph Error");
                    //    #endif
                        MakeInt(buf,error);
                    //    #if defined( LCD_MODEL )        
                    //    ShowFont(0, 48,buf);
                    //    #endif
                        //j=0;while(j<80000000L)j++;
                    }
                    if(LanguageID == LID_BIG5 &&  
                        char_unicode[i] < 256)
                        x += ttf_metrics.advance/64/2;
                    else
                        x += ttf_metrics.advance/64;
                    break;
                case 90:
                    Render_90_Glyph ( glyph, x, y );
                    if(LanguageID == LID_BIG5 &&  
                        char_unicode[i] < 256)
                        y += ttf_metrics.advance/64/2;
                    else
                        y += ttf_metrics.advance/64;
                    break;
                case 180:
                    Render_180_Glyph( glyph, x, y );
                    if(LanguageID == LID_BIG5 &&  
                        char_unicode[i] < 256)
                        x -= ttf_metrics.advance/64/2;
                    else
                        x -= ttf_metrics.advance/64;
                    break;
                case 270:
                    Render_270_Glyph( glyph, x, y );
                    if(LanguageID == LID_BIG5 &&  
                        char_unicode[i] < 256)
                        y -= ttf_metrics.advance/64/2;
                    else
                        y -= ttf_metrics.advance/64;
                    break;
            }
        
            //inc bounding box width
            if(LanguageID == LID_BIG5 &&  
                   char_unicode[i] < 256)
                iEraseWidth += ttf_metrics.advance/64/2;
            else
                iEraseWidth += ttf_metrics.advance/64;
        }
    }
    // kcmark
    iEraseWidth += ( ptsize >> 1 );
    

    //get last line and firstline
    switch( psTextAttr->iRotation )
    {
        case 0:
            Hodify_iY = psTextAttr->sCoord.iY;
            Hodify_Height = y + iEraseHeight - Hodify_iY;

        //    // Get the iFirstLine
        //    if ( psTextAttr->sCoord.iY  < psTextAttr->psImageBuffer->iFirstLine )
        //        psTextAttr->psImageBuffer->iFirstLine = psTextAttr->sCoord.iY;
        //    // get iLastLine
        //    if ( y + iEraseHeight > psTextAttr->psImageBuffer->iLastLine )
        //        psTextAttr->psImageBuffer->iLastLine = y + iEraseHeight - 1;
            break;        
        
        case 90:
            Hodify_iY = psTextAttr->sCoord.iY;
            Hodify_Height = y - Hodify_iY;

            // Get the iFirstLine
        //    if ( psTextAttr->sCoord.iY  < psTextAttr->psImageBuffer->iFirstLine )
        //        psTextAttr->psImageBuffer->iFirstLine = psTextAttr->sCoord.iY;
        //    // get iLastLine
        //    if ( y > psTextAttr->psImageBuffer->iLastLine )
        //        psTextAttr->psImageBuffer->iLastLine = y - 1;
            break;        
        
        case 180:
            Hodify_iY = y - iEraseHeight + 1;
            Hodify_Height = y - Hodify_iY;

        //    // Get the iFirstLine
        //    if ( (y - iEraseHeight)  < psTextAttr->psImageBuffer->iFirstLine )
        //        psTextAttr->psImageBuffer->iFirstLine = y - iEraseHeight + 1;
        //    // get iLastLine
        //    if ( y > psTextAttr->psImageBuffer->iLastLine )
        //        psTextAttr->psImageBuffer->iLastLine = y;
            break;        
        
        case 270:
            Hodify_iY = y - 1;
            Hodify_Height = psTextAttr->sCoord.iY - Hodify_iY;

        //    // Get the iFirstLine
        //    if ( y < psTextAttr->psImageBuffer->iFirstLine )
        //        psTextAttr->psImageBuffer->iFirstLine = y - 1;
        //    // get iLastLine
        //    if ( y > psTextAttr->psImageBuffer->iLastLine )
        //        psTextAttr->psImageBuffer->iLastLine = psTextAttr->sCoord.iY;
            break;
    }
    pFontAttr->iRealWidth = iEraseWidth;
    pFontAttr->iRealHeight = iEraseHeight;
    ModifyImgSection(Hodify_iY, Hodify_Height, psTextAttr->psImageBuffer);  
    
    TT_Close_Face(face);                           
    free ( pBuf );
    return TRUE;

}


int  PreviewTTOutText(_TextAttr* psTextAttr, _FontAttr* pFontAttr)
{
    int i;
    TT_F26Dot6  x, y;
    TT_Error  error;
    int        iEraseHeight;
    int     iEraseWidth;

    if(!Init_Engine())
    {
        free ( pBuf );
        SendString("TTF malloc error");
        return FALSE;
    }

    lpTTFGetData = pFontAttr->lpGetData;
    lpTTFSetDataPoint = pFontAttr->lpSetDataPoint;
    lpTTFGetDataPoint = pFontAttr->lpGetDataPoint;
    lpTTFGetSize = pFontAttr->lpGetSize;
    
    //initialize our own image buffer attributes                           
    Bit.rows = psTextAttr->psImageBuffer->iHeight;
    Bit.cols = psTextAttr->psImageBuffer->iByteWidth;
    Bit.width = psTextAttr->psImageBuffer->iWidth;
    Bit.flow = TT_Flow_Up;//TT_Flow_Down;
    Bit.bitmap = psTextAttr->psImageBuffer->pBuffer;
    Bit.size = Bit.rows * Bit.cols;
               
    //hinted always
    hinted = 1;
    
    // Load new face 
    error = TT_Open_Face( engine, (char *)psTextAttr->pFont, &face );
    if(error)
    {
        SendPrintf("TT_Open_Face:%d\r\n", error);
        free ( pBuf );
        return FALSE;
    }

    // get face properties and allocate preload arrays 
    TT_Get_Face_Properties( face, &properties );

    // create glyph 
    error = TT_New_Glyph( face, &glyph );

    // create instance
    error = TT_New_Instance( face, &instance );

    // set resolution, we could use this to expand width
    error = TT_Set_Instance_Resolutions( instance, RESOLUTION, RESOLUTION );
        ptsize = psTextAttr->iVertMulti;
    
    error = TT_Set_Instance_PointSize( instance, ptsize );
    if(error)
    {
        SendPrintf("TT_Set_Instance_PointSize:%d\r\n", error);
        free ( pBuf );
        return FALSE;
    }
        
    
    // get glyph index for every byte in the input string
    CharToUnicode(psTextAttr, pFontAttr->iCodePage);
                 
    //get (x,y)
    x = psTextAttr->sCoord.iX;
    y = psTextAttr->sCoord.iY;
 

    i = TT_Char_Index( char_map, 'A'); //
    LoadTrueTypeChar( i, hinted );
    TT_Get_Glyph_Metrics( glyph, &ttf_metrics );
    BearingY = ttf_metrics.bbox.yMax;

    i = TT_Char_Index( char_map, 'y'); //
    LoadTrueTypeChar( i, hinted );
    TT_Get_Glyph_Metrics( glyph, &ttf_metrics );

    //for erase box
    iEraseHeight = (BearingY - ttf_metrics.bbox.yMin) >> 6;
    iEraseWidth = 0;
    //check OB (  )
    
    for ( i = 0; i < num_codes; i++ )
    {
        error = LoadTrueTypeChar( glyph_code[i], hinted );

        if(!error)
        {
            TT_Get_Glyph_Metrics( glyph, &ttf_metrics );
            //inc bounding box width
            if(LanguageID == LID_BIG5 &&  
                   char_unicode[i] < 256)
                iEraseWidth += ttf_metrics.advance/64/2;
            else
                iEraseWidth += ttf_metrics.advance/64;
        }
    }
    // kcmark
    iEraseWidth += ( ptsize >> 1 );
    
    pFontAttr->iRealWidth = iEraseWidth;
    pFontAttr->iRealHeight = iEraseHeight;

    TT_Close_Face(face);                           
    free ( pBuf );
    return TRUE;
}


ttfile.c    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/*******************************************************************
 *
 *  ttfile.c (extended version)                                 2.1
 *
 *    File I/O Component (body).
 *
 *  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.
 *
 *  NOTES:
 *
 *   This implementation relies on the ANSI libc.  You may wish to
 *   modify it to get rid of libc and go straight to the your
 *   platform's stream routines.
 *
 *   The same source code can be used for thread-safe and re-entrant
 *   builds of the library.
 *
 *  Changes between 2.0 and 2.1 :
 *
 *  - it is now possible to close a stream's file handle explicitely
 *    through the new API "TT_Flush_Stream". This will simply close
 *    a stream's file handle (useful to save system resources when
 *    dealing with lots of opened fonts). Of course, the function
 *    "TT_Use_Stream" will automatically re-open a stream's handle if
 *    necessary.
 *
 *  - added "TT_Stream_Size" to replace "TT_File_Size" which wasn't
 *    used anyway. This one returns the size of any stream, even
 *    flushed one (when the previous TT_File_Size could only return
 *    the size of the current working stream). This is used by the
 *    new "Load_TrueType_Any" function in the tables loader.
 *
 ******************************************************************/

#include "ttconfig.h"

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

#ifdef HAVE_UNISTD_H
//#include <unistd.h>
#endif


// #include "..\file.h"
#include "freetype.h"
#include "tttypes.h"
#include "ttdebug.h"
#include "ttengine.h"
#include "ttmutex.h"
#include "ttmemory.h"
#include "ttfile.h"     /* our prototypes */
#include "XFileSys.h"

/* required by the tracing mode */
#undef  TT_COMPONENT
#define TT_COMPONENT  trace_file


/* For now, we don't define additional error messages in the core library */
/* to report open-on demand errors. Define these error as standard ones   */

#define TT_Err_Could_Not_ReOpen_File  TT_Err_Could_Not_Open_File
#define TT_Err_Could_Not_ReSeek_File  TT_Err_Could_Not_Open_File

  /* This definition is mandatory for each file component! */
  EXPORT_FUNC
  const TFileFrame  TT_Null_FileFrame = { NULL, 0, 0 };

/* It has proven useful to do some bounds checks during development phase. */
/* They should probably be undefined for speed reasons in a later release. */

#if defined (DEBUG_FILE)
#define CHECK_FRAME( frame, n )                          \
  do {                                                   \
    if ( frame.cursor + n > frame.address + frame.size ) \
      Panic( "Frame boundary error!\n" );                \
  } while ( 0 )
#else
#define CHECK_FRAME( frame, n )  /* nothing */
#endif

  /* Because a stream can be flushed, i.e. its file handle can be      */
  /* closed to save system resources, we must keep the stream's file   */
  /* pathname to be able to re-open it on demand when it is flushed    */

  struct  TStream_Rec_;
  typedef struct TStream_Rec_  TStream_Rec;
  typedef TStream_Rec*         PStream_Rec;

  struct  TStream_Rec_
  {
    Bool      opened;                  /* is the stream handle opened ?    */
    TT_Text*  name;                    /* the file's pathname              */
    Long      position;                /* current position within the file */

    //FILE*      file;
    _FileHandle*     file;                    /* file handle                      */
    Long      base;                    /* stream base in file              */
    Long      size;                    /* stream size in file              */
  };

  /* We support embedded TrueType files by allowing them to be       */
  /* inside any file, at any location, hence the 'base' argument.    */
  /* Note however that the current implementation does not allow you */
  /* to specify a 'base' index when opening a file.                  */
  /* (will come later)                                               */
  /* I still don't know if this will turn out useful ??   - DavidT   */

#define STREAM2REC( x )  ( (TStream_Rec*)HANDLE_Val( x ) )

  static  TT_Error  Stream_Activate  ( PStream_Rec  stream );
  static  TT_Error  Stream_Deactivate( PStream_Rec  stream );


#ifndef TT_CONFIG_OPTION_THREAD_SAFE

  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/
  /****                                                           ****/
  /****  N O N   R E E N T R A N T   I M P L E M E N T A T I O N  ****/
  /****                                                           ****/
  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/

  /* in non-rentrant builds, we allocate a single block where we'll  */
  /* place all the frames smaller than FRAME_CACHE_SIZE, rather than */
  /* allocating a new block on each access.  Bigger frames will be   */
  /* malloced normally in the heap.                                  */
  /*                                                                 */
  /* See TT_Access_Frame() and TT_Forget_Frame() for details.        */

#define FRAME_CACHE_SIZE  2048

  /* The TFile_Component structure holds all the data that was */
  /* previously declared static or global in this component.   */
  /*                                                           */
  /* It is accessible through the 'engine.file_component'      */
  /* variable in re-entrant builds, or directly through the    */
  /* static 'files' variable in other builds.                  */

  struct  TFile_Component_
  {
    TMutex       lock;        /* used by the thread-safe build only */
    Byte*        frame_cache; /* frame cache     */
    PStream_Rec  stream;      /* current stream  */
    TFileFrame   frame;       /* current frame   */
  };

  typedef struct TFile_Component_  TFile_Component;

  static TFile_Component  files;

#define CUR_Stream  files.stream
#define CUR_Frame   files.frame

#define STREAM_VARS  /* void */
#define STREAM_VAR   /* void */

/* The macro CUR_Stream denotes the current input stream.            */
/* Note that for the re-entrant version, the 'stream' name has been  */
/* chosen according to the macro STREAM_ARGS.                        */

/* The macro CUR_Frame denotes the current file frame.              */
/* Note that for the re-entrant version, the 'frame' name has been  */
/* chosen according to the macro FRAME_ARGS.                        */

/* The macro STREAM_VAR is used when calling public functions */
/* that need an 'optional' stream argument.                   */


/*******************************************************************
 *
 *  Function    :  TTFile_Init
 *
 *  Description :  Initializes the File component.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TTFile_Init( PEngine_Instance  engine )
  {
    TT_Error  error;


    MUTEX_Create( files.lock );
    files.stream = NULL;
    ZERO_Frame( files.frame );

    if ( ALLOC( files.frame_cache, FRAME_CACHE_SIZE ) )
      return error;

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TTFile_Done
 *
 *  Description :  Finalizes the File component.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TTFile_Done( PEngine_Instance  engine )
  {
    FREE( files.frame_cache );
    MUTEX_Destroy( files.lock );

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    : TT_Use_Stream
 *
 *  Description : Copies or duplicates a given stream.
 *
 *  Input  :  org_stream   original stream
 *            stream       target stream (copy or duplicate)
 *
 *  Output :  Error code.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Use_Stream( TT_Stream   org_stream,
                           TT_Stream*  stream )
  {
     MUTEX_Lock( files.lock );                /* lock file mutex    */

     *stream = org_stream;                    /* copy the stream    */
     files.stream = STREAM2REC(org_stream);   /* set current stream */

     Stream_Activate( files.stream );

     return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    : TT_Done_Stream
 *
 *  Description : Releases a given stream.
 *
 *  Input  :  stream  target stream
 *
 *  Output :  Error code.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Done_Stream( TT_Stream*  stream )
  {
     HANDLE_Set( *stream, NULL );
     MUTEX_Release( files.lock );

     return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TT_Access_Frame
 *
 *  Description :  Notifies the component that we're going to read
 *                 'size' bytes from the current file position.
 *                 This function should load/cache/map these bytes
 *                 so that they will be addressed by the GET_xxx
 *                 functions easily.
 *
 *  Input  :  size   number of bytes to access.
 *
 *  Output :  SUCCESS on success. FAILURE on error.
 *
 *  Notes:    The function fails if the byte range is not within the
 *            the file, or if there is not enough memory to cache
 *            the bytes properly (which usually means that `size' is
 *            too big in both cases).
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long  size )
  {
    TT_Error  error;


    if ( CUR_Frame.address != NULL )
      return TT_Err_Nested_Frame_Access;

    if ( size <= FRAME_CACHE_SIZE )
    {
      /* use the cache */
      CUR_Frame.address = files.frame_cache;
      CUR_Frame.size    = FRAME_CACHE_SIZE;
    }
    else
    {
      if ( ALLOC( CUR_Frame.address, size ) )
        return error;
      CUR_Frame.size    = size;
    }

    error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
    if (error)
    {
      if ( size > FRAME_CACHE_SIZE )
        FREE( CUR_Frame.address );
      CUR_Frame.address = NULL;
      CUR_Frame.size    = 0;
    }

    CUR_Frame.cursor = CUR_Frame.address;
    return error;
  }


/*******************************************************************
 *
 *  Function    :  TT_Check_And_Access_Frame
 *
 *  Description :  Notifies the component that we're going to read
 *                 `size' bytes from the current file position.
 *                 This function should load/cache/map these bytes
 *                 so that they will be addressed by the GET_xxx
 *                 functions easily.
 *
 *  Input  :  size   number of bytes to access.
 *
 *  Output :  SUCCESS on success. FAILURE on error.
 *
 *  Notes:    The function truncates `size' if the byte range is not
 *            within the file.
 *
 *            It will fail if there is not enough memory to cache
 *            the bytes properly (which usually means that `size' is
 *            too big).
 *
 *            It will fail if you make two consecutive calls
 *            to TT_Access_Frame(), without a TT_Forget_Frame() between
 *            them.
 *
 *            The only difference with TT_Access_Frame() is that we
 *            check that the frame is within the current file.  We
 *            otherwise truncate it.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long  size )
  {
    TT_Error  error;
    Long      readBytes, requested;


    if ( CUR_Frame.address != NULL )
      return TT_Err_Nested_Frame_Access;

    if ( size <= FRAME_CACHE_SIZE )
    {
      /* use the cache */
      CUR_Frame.address = files.frame_cache;
      CUR_Frame.size    = FRAME_CACHE_SIZE;
    }
    else
    {
      if ( ALLOC( CUR_Frame.address, size ) )
        return error;
      CUR_Frame.size    = size;
    }

    requested = size;
    readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR );
    if ( size > readBytes )
      size = readBytes;

    error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
    if (error)
    {
      if ( requested > FRAME_CACHE_SIZE )
        FREE( CUR_Frame.address );
      CUR_Frame.address = NULL;
      CUR_Frame.size    = 0;
    }

    CUR_Frame.cursor = CUR_Frame.address;
    return error;
  }


/*******************************************************************
 *
 *  Function    :  TT_Forget_Frame
 *
 *  Description :  Releases a cached frame after reading.
 *
 *  Input  :  None
 *
 *  Output :  SUCCESS on success. FAILURE on error.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Forget_Frame( FRAME_ARG )
  {
    if ( CUR_Frame.address == NULL )
      return TT_Err_Nested_Frame_Access;

    if ( CUR_Frame.size > FRAME_CACHE_SIZE )
      FREE( CUR_Frame.address );

    ZERO_Frame( CUR_Frame );

    return TT_Err_Ok;
  }


#else /* TT_CONFIG_OPTION_THREAD_SAFE */

  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/
  /********                                                   ********/
  /********  R E E N T R A N T   I M P L E M E N T A T I O N  ********/
  /********                                                   ********/
  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/

/* a simple macro to access the file component's data */
#define files  ( *((TFile_Component*)engine.file_component) )

#define CUR_Stream   STREAM2REC( stream )    /* re-entrant macros */
#define CUR_Frame    (*frame)

#define STREAM_VARS  stream,
#define STREAM_VAR   stream


/*******************************************************************
 *
 *  Function    :  TTFile_Init
 *
 *  Description :  Initializes the File component.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TTFile_Init( PEngine_Instance  engine )
  {
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TTFile_Done
 *
 *  Description :  Finalizes the File component.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TTFile_Done( PEngine_Instance  engine )
  {
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TT_Use_Stream
 *
 *  Description :  Duplicates a stream for a new usage.
 *
 *  Input  :  input_stream   source stream to duplicate
 *            copy           address of target duplicate stream
 *
 *  Output :  error code.
 *            The target stream is set to NULL in case of failure.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Use_Stream( TT_Stream   input_stream,
                           TT_Stream*  copy )
  {
    PStream_Rec  rec = STREAM2REC( input_stream );

    return TT_Open_Stream( rec->name, copy );
  }


/*******************************************************************
 *
 *  Function    : TT_Done_Stream
 *
 *  Description : Releases a given stream.
 *
 *  Input  :  stream  target stream
 *
 *  Output :
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Done_Stream( TT_Stream*  stream )
  {
    return TT_Close_Stream( stream );
  }


/*******************************************************************
 *
 *  Function    :  TT_Access_Frame
 *
 *  Description :  Notifies the component that we're going to read
 *                 'size' bytes from the current file position.
 *                 This function should load/cache/map these bytes
 *                 so that they will be addressed by the GET_xxx
 *                 functions easily.
 *
 *  Input  :  size   number of bytes to access.
 *
 *  Output :  SUCCESS on success. FAILURE on error.
 *
 *  Notes:    The function fails if the byte range is not within the
 *            the file, or if there is not enough memory to cache
 *            the bytes properly (which usually means that `size' is
 *            too big in both cases).
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long  size )
  {
    TT_Error  error;


    if ( CUR_Frame.address != NULL )
      return TT_Err_Nested_Frame_Access;

    if ( ALLOC( CUR_Frame.address, size ) )
      return error;
    CUR_Frame.size    = size;

    error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
    if ( error )
    {
      FREE( CUR_Frame.address );
      CUR_Frame.size    = 0;
    }

    CUR_Frame.cursor = CUR_Frame.address;
    return error;
  }


/*******************************************************************
 *
 *  Function    :  TT_Check_And_Access_Frame
 *
 *  Description :  Notifies the component that we're going to read
 *                 `size' bytes from the current file position.
 *                 This function should load/cache/map these bytes
 *                 so that they will be addressed by the GET_xxx
 *                 functions easily.
 *
 *  Input  :  size   number of bytes to access.
 *
 *  Output :  SUCCESS on success. FAILURE on error.
 *
 *  Notes:    The function truncates `size' if the byte range is not
 *            within the file.
 *
 *            It will fail if there is not enough memory to cache
 *            the bytes properly (which usually means that `size' is
 *            too big).
 *
 *            It will fail if you make two consecutive calls
 *            to TT_Access_Frame(), without a TT_Forget_Frame() between
 *            them.
 *
 *            The only difference with TT_Access_Frame() is that we
 *            check that the frame is within the current file.  We
 *            otherwise truncate it.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long  size )
  {
    TT_Error  error;
    Long      readBytes;


    if ( CUR_Frame.address != NULL )
      return TT_Err_Nested_Frame_Access;

    if ( ALLOC( CUR_Frame.address, size ) )
      return error;
    CUR_Frame.size    = size;

    readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR );
    if ( size > readBytes )
      size = readBytes;

    error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size );
    if ( error )
    {
      FREE( CUR_Frame.address );
      CUR_Frame.size    = 0;
    }

    CUR_Frame.cursor = CUR_Frame.address;
    return error;
  }


/*******************************************************************
 *
 *  Function    :  TT_Forget_Frame
 *
 *  Description :  Releases a cached frame after reading.
 *
 *  Input  :  None
 *
 *  Output :  SUCCESS on success.  FAILURE on error.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Forget_Frame( FRAME_ARG )
  {
    if ( CUR_Frame.address == NULL )
      return TT_Err_Nested_Frame_Access;

    FREE( CUR_Frame.address );
    ZERO_Frame( CUR_Frame );

    return TT_Err_Ok;
  }

#endif /* TT_CONFIG_OPTION_THREAD_SAFE */


  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/
  /***********                                             ***********/
  /***********  C O M M O N   I M P L E M E N T A T I O N  ***********/
  /***********                                             ***********/
  /*******************************************************************/
  /*******************************************************************/
  /*******************************************************************/

/*******************************************************************
 *
 *  Function    :  Stream_Activate
 *
 *  Description :  activates a stream, this will either:
 *                   - open a new file handle if the stream is closed
 *                   - move the stream to the head of the linked list
 *
 *  Input  :  stream   the stream to activate
 *
 *  Output :  error condition.
 *
 *  Note   :  This function is also called with fresh new streams
 *            created by TT_Open_Stream().  They have their 'size'
 *            field set to -1.
 *
 ******************************************************************/

  static  TT_Error  Stream_Activate( PStream_Rec  stream )
  {
    if ( !stream->opened )
    {
//    if ( (stream->file = fopen( (TT_Text*)stream->name, "rb" )) == 0 ) 
//    if ( (stream->file = fopen( FLASH_DEVICE,(byte *)stream->name)) == 0 ) 
//    if ( (stream->file = fopen( NO_SELECT_DEVICE,(unsigned char *)stream->name)) == 0 )         return TT_Err_Could_Not_ReOpen_File;
      stream->opened = TRUE;

      /* A newly created stream has a size field of -1 */
      if ( stream->size < 0 )
      {
        //fseek( stream->file, 0, SEEK_END );
        //stream->size = ftell( stream->file );
        //fseek( stream->file, 0, SEEK_SET );
//        stream->size = stream->file->Size;
        stream->size = lpTTFGetSize();
      }

      /* Reset cursor in file */
      if ( stream->position )
      {
//        if ( fseek( stream->file, stream->position, SEEK_SET ) != 0 )
//        if ( fseek( stream->file, stream->position ) != 0 )
//        {
//          /* error during seek */
//          fclose( stream->file );
//          stream->opened = FALSE;
//          return TT_Err_Could_Not_ReSeek_File;
//        }
        fseek( stream->file, stream->position ) ;
      }
    }
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  Stream_DeActivate
 *
 *  Description :  deactivates a stream, this will :
 *                   - close its file handle if it was opened
 *                   - remove it from the opened list if necessary
 *
 *  Input  :  stream   the stream to deactivate
 *
 *  Output :  Error condition
 *
 *  Note   :  the function is called whenever a stream is deleted
 *            (_not_ when a stream handle's is closed due to an
 *             activation). However, the stream record isn't
 *            destroyed by it..
 *
 ******************************************************************/

  static  TT_Error  Stream_Deactivate( PStream_Rec  stream )
  {
    if ( stream->opened )
    {
      /* Save its current position within the file */
      stream->position = ftell( stream->file );
      fclose( stream->file );
      stream->file   = 0;
      stream->opened = FALSE;
    }

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TT_Stream_Size
 *
 *  Description :  Returns the length of a given stream, even if it
 *                 is flushed.
 *
 *  Input  :  stream     the stream
 *
 *  Output :  Length of stream in bytes.
 *
 ******************************************************************/

  EXPORT_FUNC
  Long  TT_Stream_Size( TT_Stream  stream )
  {
    PStream_Rec  rec = STREAM2REC( stream );


    if ( rec )
      return rec->size;
    else
      return 0;  /* invalid stream - return 0 */
  }


/*******************************************************************
 *
 *  Function    :  TT_Open_Stream
 *
 *  Description :  Opens the font file and saves the total file size.
 *
 *  Input  :  error          address of stream's error variable
 *                           (re-entrant build only)
 *            filepathname   pathname of the file to open
 *            stream         address of target TT_Stream structure
 *
 *  Output :  SUCCESS on sucess, FAILURE on error.
 *            The target stream is set to -1 in case of failure.
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TT_Open_Stream( const TT_Text*  filepathname,
                            TT_Stream*      stream )
  {
    Int          len;
    TT_Error     error;
    PStream_Rec  stream_rec;

    if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) )
      return error;

    stream_rec = STREAM2REC( *stream );

    stream_rec->file     = NULL;
    stream_rec->size     = -1L;
    stream_rec->base     = 0;
    stream_rec->opened   = FALSE;
    stream_rec->position = 0;

    len = strlen( filepathname ) + 1;
    if ( ALLOC( stream_rec->name, len ) )
      goto Fail;

    strncpy( stream_rec->name, filepathname, len );

    error = Stream_Activate( stream_rec );
    if ( error )
      goto Fail_Activate;

#ifndef TT_CONFIG_OPTION_THREAD_SAFE
    CUR_Stream = stream_rec;
#endif

    return TT_Err_Ok;

  Fail_Activate:
    FREE( stream_rec->name );
  Fail:
    FREE( stream_rec );
    return error;
  }


/*******************************************************************
 *
 *  Function    : TT_Close_Stream
 *
 *  Description : Closes a stream.
 *
 *  Input  :  stream         address of target TT_Stream structure
 *
 *  Output :  SUCCESS (always).
 *
 ******************************************************************/

  LOCAL_FUNC
  TT_Error  TT_Close_Stream( TT_Stream*  stream )
  {
    PStream_Rec  rec = STREAM2REC( *stream );


    Stream_Deactivate( rec );
    FREE( rec->name );
    FREE( rec );

    HANDLE_Set( *stream, NULL );
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    : TT_Flush_Stream
 *
 *  Description : Flushes a stream, i.e., closes its file handle.
 *
 *  Input  :  stream         address of target TT_Stream structure
 *
 *  Output :  Error code
 *
 *  NOTE : Never flush the current opened stream.  This means that
 *         you should _never_ call this function between a
 *         TT_Use_Stream() and a TT_Done_Stream()!
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Flush_Stream( TT_Stream*  stream )
  {
    PStream_Rec  rec = STREAM2REC( *stream );


    if ( rec )
    {
      Stream_Deactivate( rec );
      return TT_Err_Ok;
    }
    else
      return TT_Err_Invalid_Argument;
  }


/*******************************************************************
 *
 *  Function    : TT_Seek_File
 *
 *  Description : Seeks the file cursor to a different position.
 *
 *  Input  :  position     new position in file
 *
 *  Output :  SUCCESS on success.  FAILURE if out of range.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Seek_File( STREAM_ARGS Long  position )
  {
    position += CUR_Stream->base;

//    if ( fseek( CUR_Stream->file, position, SEEK_SET ) )
//    if ( fseek( CUR_Stream->file, position) )
//      return TT_Err_Invalid_File_Offset;
    fseek( CUR_Stream->file, position);
    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    : TT_Skip_File
 *
 *  Description : Skips forward the file cursor.
 *
 *  Input  :  distance    number of bytes to skip
 *
 *  Output :  see TT_Seek_File()
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Skip_File( STREAM_ARGS Long  distance )
  {
    return TT_Seek_File( STREAM_VARS lpTTFGetDataPoint() -
                                     CUR_Stream->base + distance );
  }


/*******************************************************************
 *
 *  Function    : TT_Read_File
 *
 *  Description : Reads a chunk of the file and copies it to memory.
 *
 *  Input  :  buffer    target buffer
 *            count     length in bytes to read
 *
 *  Output :  SUCCESS on success.  FAILURE if out of range.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Read_File( STREAM_ARGS void*  buffer, Long  count )
  {
        lpTTFGetData(buffer, count);
          
//    if ( fread( buffer, 1, count, CUR_Stream->file ) != (ULong)count )
//      return TT_Err_Invalid_File_Read;

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    : TT_Read_At_File
 *
 *  Description : Reads file at a specified position.
 *
 *  Input  :  position  position to seek to before read
 *            buffer    target buffer
 *            count     number of bytes to read
 *
 *  Output :  SUCCESS on success.  FAILURE if error.
 *
 ******************************************************************/

  EXPORT_FUNC
  TT_Error  TT_Read_At_File( STREAM_ARGS Long   position,
                                         void*  buffer,
                                         Long   count )
  {
    TT_Error  error;


    if ( (error = TT_Seek_File( STREAM_VARS position ))      != TT_Err_Ok ||
         (error = TT_Read_File( STREAM_VARS buffer, count )) != TT_Err_Ok )
      return error;

    return TT_Err_Ok;
  }


/*******************************************************************
 *
 *  Function    :  TT_File_Pos
 *
 *  Description :  Returns current file seek pointer.
 *
 *  Input  :  none
 *
 *  Output :  Current file position.
 *
 ******************************************************************/

  EXPORT_FUNC
  Long  TT_File_Pos( STREAM_ARG )
  {
    return lpTTFGetDataPoint() - CUR_Stream->base;
  }


/*******************************************************************
 *
 *  Function    :  GET_Byte
 *
 *  Description :  Extracts a byte from the current file frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted Byte.
 *
 ******************************************************************/
#if 0
  EXPORT_FUNC
  Byte  TT_Get_Byte( FRAME_ARG )
  {
    CHECK_FRAME( CUR_Frame, 1 );

    return (Byte)(*CUR_Frame.cursor++);
  }
#endif


/*******************************************************************
 *
 *  Function    :  GET_Char
 *
 *  Description :  Extracts a signed byte from the current file frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted char.
 *
 ******************************************************************/
  EXPORT_FUNC
  Char  TT_Get_Char( FRAME_ARG )
  {
    CHECK_FRAME( CUR_Frame, 1 );

    return (Char)(*CUR_Frame.cursor++);
  }


/*******************************************************************
 *
 *  Function    :  GET_Short
 *
 *  Description :  Extracts a short from the current file frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted short.
 *
 ******************************************************************/

  EXPORT_FUNC
  Short  TT_Get_Short( FRAME_ARG )
  {
    Short  getshort;


    CHECK_FRAME( CUR_Frame, 2 );

    getshort = (Short)((CUR_Frame.cursor[0] << 8) |
                        CUR_Frame.cursor[1]);

    CUR_Frame.cursor += 2;

    return getshort;
  }


/*******************************************************************
 *
 *  Function    :  GET_UShort
 *
 *  Description :  Extracts an unsigned short from the frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted ushort.
 *
 ******************************************************************/
#if 0
  EXPORT_FUNC
  UShort  TT_Get_UShort( FRAME_ARG )
  {
    UShort  getshort;


    CHECK_FRAME( CUR_Frame, 2 );

    getshort = (UShort)((CUR_Frame.cursor[0] << 8) |
                         CUR_Frame.cursor[1]);

    CUR_Frame.cursor += 2;

    return getshort;
  }
#endif


/*******************************************************************
 *
 *  Function    :  GET_Long
 *
 *  Description :  Extracts a long from the frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted long.
 *
 ******************************************************************/

  EXPORT_FUNC
  Long  TT_Get_Long( FRAME_ARG )
  {
    Long  getlong;


    CHECK_FRAME( CUR_Frame, 4 );

    getlong = ((Long)CUR_Frame.cursor[0] << 24) |
              ((Long)CUR_Frame.cursor[1] << 16) |
              ((Long)CUR_Frame.cursor[2] << 8 ) |
               (Long)CUR_Frame.cursor[3];

    CUR_Frame.cursor += 4;

    return getlong;
  }


/*******************************************************************
 *
 *  Function    :  GET_ULong
 *
 *  Description :  Extracts an unsigned long from the frame.
 *
 *  Input  :  None or current frame
 *
 *  Output :  Extracted ulong.
 *
 ******************************************************************/
#if 0
  EXPORT_FUNC
  ULong  TT_Get_ULong( FRAME_ARG )
  {
    ULong  getlong;


    CHECK_FRAME( CUR_Frame, 4 );

    getlong = ( ((ULong)CUR_Frame.cursor[0] << 24) |
                ((ULong)CUR_Frame.cursor[1] << 16) |
                ((ULong)CUR_Frame.cursor[2] << 8 ) |
                 (ULong)CUR_Frame.cursor[3] );

    CUR_Frame.cursor += 4;

    return getlong;
  }
#endif


/* END */
 

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值