- Remove svn:needs-lock, svn:eol-type, and svn:eol-tyle properties.
[reactos.git] / reactos / lib / 3rdparty / freetype / src / cache / ftcbasic.c
index b2155ff..f2e6229 100644 (file)
-/***************************************************************************/\r
-/*                                                                         */\r
-/*  ftcbasic.c                                                             */\r
-/*                                                                         */\r
-/*    The FreeType basic cache interface (body).                           */\r
-/*                                                                         */\r
-/*  Copyright 2003, 2004, 2005, 2006, 2007 by                              */\r
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\r
-/*                                                                         */\r
-/*  This file is part of the FreeType project, and may only be used,       */\r
-/*  modified, and distributed under the terms of the FreeType project      */\r
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */\r
-/*  this file you indicate that you have read the license and              */\r
-/*  understand and accept it fully.                                        */\r
-/*                                                                         */\r
-/***************************************************************************/\r
-\r
-\r
-#include <ft2build.h>\r
-#include FT_CACHE_H\r
-#include "ftcglyph.h"\r
-#include "ftcimage.h"\r
-#include "ftcsbits.h"\r
-#include FT_INTERNAL_MEMORY_H\r
-\r
-#include "ftccback.h"\r
-#include "ftcerror.h"\r
-\r
-\r
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS\r
-\r
-  /*\r
-   *  These structures correspond to the FTC_Font and FTC_ImageDesc types\r
-   *  that were defined in version 2.1.7.\r
-   */\r
-  typedef struct  FTC_OldFontRec_\r
-  {\r
-    FTC_FaceID  face_id;\r
-    FT_UShort   pix_width;\r
-    FT_UShort   pix_height;\r
-\r
-  } FTC_OldFontRec, *FTC_OldFont;\r
-\r
-\r
-  typedef struct  FTC_OldImageDescRec_\r
-  {\r
-    FTC_OldFontRec  font;\r
-    FT_UInt32       flags;\r
-\r
-  } FTC_OldImageDescRec, *FTC_OldImageDesc;\r
-\r
-\r
-  /*\r
-   *  Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly\r
-   *  identical, bit-wise.  The only difference is that the `width' and\r
-   *  `height' fields are expressed as 16-bit integers in the old structure,\r
-   *  and as normal `int' in the new one.\r
-   *\r
-   *  We are going to perform a weird hack to detect which structure is\r
-   *  being passed to the image and sbit caches.  If the new structure's\r
-   *  `width' is larger than 0x10000, we assume that we are really receiving\r
-   *  an FTC_OldImageDesc.\r
-   */\r
-\r
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */\r
-\r
-\r
-  /*\r
-   *  Basic Families\r
-   *\r
-   */\r
-  typedef struct  FTC_BasicAttrRec_\r
-  {\r
-    FTC_ScalerRec  scaler;\r
-    FT_UInt        load_flags;\r
-\r
-  } FTC_BasicAttrRec, *FTC_BasicAttrs;\r
-\r
-#define FTC_BASIC_ATTR_COMPARE( a, b )                                 \\r
-          FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \\r
-                   (a)->load_flags == (b)->load_flags               )\r
-\r
-#define FTC_BASIC_ATTR_HASH( a )                                   \\r
-          ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )\r
-\r
-\r
-  typedef struct  FTC_BasicQueryRec_\r
-  {\r
-    FTC_GQueryRec     gquery;\r
-    FTC_BasicAttrRec  attrs;\r
-\r
-  } FTC_BasicQueryRec, *FTC_BasicQuery;\r
-\r
-\r
-  typedef struct  FTC_BasicFamilyRec_\r
-  {\r
-    FTC_FamilyRec     family;\r
-    FTC_BasicAttrRec  attrs;\r
-\r
-  } FTC_BasicFamilyRec, *FTC_BasicFamily;\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_Bool )\r
-  ftc_basic_family_compare( FTC_MruNode  ftcfamily,\r
-                            FT_Pointer   ftcquery )\r
-  {\r
-    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;\r
-    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;\r
-\r
-\r
-    return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );\r
-  }\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_Error )\r
-  ftc_basic_family_init( FTC_MruNode  ftcfamily,\r
-                         FT_Pointer   ftcquery,\r
-                         FT_Pointer   ftccache )\r
-  {\r
-    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;\r
-    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;\r
-    FTC_Cache        cache  = (FTC_Cache)ftccache;\r
-\r
-\r
-    FTC_Family_Init( FTC_FAMILY( family ), cache );\r
-    family->attrs = query->attrs;\r
-    return 0;\r
-  }\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_UInt )\r
-  ftc_basic_family_get_count( FTC_Family   ftcfamily,\r
-                              FTC_Manager  manager )\r
-  {\r
-    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;\r
-    FT_Error         error;\r
-    FT_Face          face;\r
-    FT_UInt          result = 0;\r
-\r
-\r
-    error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,\r
-                                    &face );\r
-    if ( !error )\r
-      result = face->num_glyphs;\r
-\r
-    return result;\r
-  }\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_Error )\r
-  ftc_basic_family_load_bitmap( FTC_Family   ftcfamily,\r
-                                FT_UInt      gindex,\r
-                                FTC_Manager  manager,\r
-                                FT_Face     *aface )\r
-  {\r
-    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;\r
-    FT_Error         error;\r
-    FT_Size          size;\r
-\r
-\r
-    error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );\r
-    if ( !error )\r
-    {\r
-      FT_Face  face = size->face;\r
-\r
-\r
-      error = FT_Load_Glyph( face, gindex,\r
-                             family->attrs.load_flags | FT_LOAD_RENDER );\r
-      if ( !error )\r
-        *aface = face;\r
-    }\r
-\r
-    return error;\r
-  }\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_Error )\r
-  ftc_basic_family_load_glyph( FTC_Family  ftcfamily,\r
-                               FT_UInt     gindex,\r
-                               FTC_Cache   cache,\r
-                               FT_Glyph   *aglyph )\r
-  {\r
-    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;\r
-    FT_Error         error;\r
-    FTC_Scaler       scaler = &family->attrs.scaler;\r
-    FT_Face          face;\r
-    FT_Size          size;\r
-\r
-\r
-    /* we will now load the glyph image */\r
-    error = FTC_Manager_LookupSize( cache->manager,\r
-                                    scaler,\r
-                                    &size );\r
-    if ( !error )\r
-    {\r
-      face = size->face;\r
-\r
-      error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );\r
-      if ( !error )\r
-      {\r
-        if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||\r
-             face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )\r
-        {\r
-          /* ok, copy it */\r
-          FT_Glyph  glyph;\r
-\r
-\r
-          error = FT_Get_Glyph( face->glyph, &glyph );\r
-          if ( !error )\r
-          {\r
-            *aglyph = glyph;\r
-            goto Exit;\r
-          }\r
-        }\r
-        else\r
-          error = FTC_Err_Invalid_Argument;\r
-      }\r
-    }\r
-\r
-  Exit:\r
-    return error;\r
-  }\r
-\r
-\r
-  FT_CALLBACK_DEF( FT_Bool )\r
-  ftc_basic_gnode_compare_faceid( FTC_Node    ftcgnode,\r
-                                  FT_Pointer  ftcface_id,\r
-                                  FTC_Cache   cache )\r
-  {\r
-    FTC_GNode        gnode   = (FTC_GNode)ftcgnode;\r
-    FTC_FaceID       face_id = (FTC_FaceID)ftcface_id;\r
-    FTC_BasicFamily  family  = (FTC_BasicFamily)gnode->family;\r
-    FT_Bool          result;\r
-\r
-\r
-    result = FT_BOOL( family->attrs.scaler.face_id == face_id );\r
-    if ( result )\r
-    {\r
-      /* we must call this function to avoid this node from appearing\r
-       * in later lookups with the same face_id!\r
-       */\r
-      FTC_GNode_UnselectFamily( gnode, cache );\r
-    }\r
-    return result;\r
-  }\r
-\r
-\r
- /*\r
-  *\r
-  * basic image cache\r
-  *\r
-  */\r
-\r
-  FT_CALLBACK_TABLE_DEF\r
-  const FTC_IFamilyClassRec  ftc_basic_image_family_class =\r
-  {\r
-    {\r
-      sizeof ( FTC_BasicFamilyRec ),\r
-      ftc_basic_family_compare,\r
-      ftc_basic_family_init,\r
-      0,                        /* FTC_MruNode_ResetFunc */\r
-      0                         /* FTC_MruNode_DoneFunc  */\r
-    },\r
-    ftc_basic_family_load_glyph\r
-  };\r
-\r
-\r
-  FT_CALLBACK_TABLE_DEF\r
-  const FTC_GCacheClassRec  ftc_basic_image_cache_class =\r
-  {\r
-    {\r
-      ftc_inode_new,\r
-      ftc_inode_weight,\r
-      ftc_gnode_compare,\r
-      ftc_basic_gnode_compare_faceid,\r
-      ftc_inode_free,\r
-\r
-      sizeof ( FTC_GCacheRec ),\r
-      ftc_gcache_init,\r
-      ftc_gcache_done\r
-    },\r
-    (FTC_MruListClass)&ftc_basic_image_family_class\r
-  };\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_ImageCache_New( FTC_Manager      manager,\r
-                      FTC_ImageCache  *acache )\r
-  {\r
-    return FTC_GCache_New( manager, &ftc_basic_image_cache_class,\r
-                           (FTC_GCache*)acache );\r
-  }\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_ImageCache_Lookup( FTC_ImageCache  cache,\r
-                         FTC_ImageType   type,\r
-                         FT_UInt         gindex,\r
-                         FT_Glyph       *aglyph,\r
-                         FTC_Node       *anode )\r
-  {\r
-    FTC_BasicQueryRec  query;\r
-    FTC_INode          node = 0;  /* make compiler happy */\r
-    FT_Error           error;\r
-    FT_UInt32          hash;\r
-\r
-\r
-    /* some argument checks are delayed to FTC_Cache_Lookup */\r
-    if ( !aglyph )\r
-    {\r
-      error = FTC_Err_Invalid_Argument;\r
-      goto Exit;\r
-    }\r
-\r
-    *aglyph = NULL;\r
-    if ( anode )\r
-      *anode  = NULL;\r
-\r
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS\r
-\r
-    /*\r
-     *  This one is a major hack used to detect whether we are passed a\r
-     *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.\r
-     */\r
-    if ( type->width >= 0x10000 )\r
-    {\r
-      FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;\r
-\r
-\r
-      query.attrs.scaler.face_id = desc->font.face_id;\r
-      query.attrs.scaler.width   = desc->font.pix_width;\r
-      query.attrs.scaler.height  = desc->font.pix_height;\r
-      query.attrs.load_flags     = desc->flags;\r
-    }\r
-    else\r
-\r
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */\r
-\r
-    {\r
-      query.attrs.scaler.face_id = type->face_id;\r
-      query.attrs.scaler.width   = type->width;\r
-      query.attrs.scaler.height  = type->height;\r
-      query.attrs.load_flags     = type->flags;\r
-    }\r
-\r
-    query.attrs.scaler.pixel = 1;\r
-    query.attrs.scaler.x_res = 0;  /* make compilers happy */\r
-    query.attrs.scaler.y_res = 0;\r
-\r
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;\r
-\r
-#if 1  /* inlining is about 50% faster! */\r
-    FTC_GCACHE_LOOKUP_CMP( cache,\r
-                           ftc_basic_family_compare,\r
-                           FTC_GNode_Compare,\r
-                           hash, gindex,\r
-                           &query,\r
-                           node,\r
-                           error );\r
-#else\r
-    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),\r
-                               hash, gindex,\r
-                               FTC_GQUERY( &query ),\r
-                               (FTC_Node*) &node );\r
-#endif\r
-    if ( !error )\r
-    {\r
-      *aglyph = FTC_INODE( node )->glyph;\r
-\r
-      if ( anode )\r
-      {\r
-        *anode = FTC_NODE( node );\r
-        FTC_NODE( node )->ref_count++;\r
-      }\r
-    }\r
-\r
-  Exit:\r
-    return error;\r
-  }\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_ImageCache_LookupScaler( FTC_ImageCache  cache,\r
-                               FTC_Scaler      scaler,\r
-                               FT_ULong        load_flags,\r
-                               FT_UInt         gindex,\r
-                               FT_Glyph       *aglyph,\r
-                               FTC_Node       *anode )\r
-  {\r
-    FTC_BasicQueryRec  query;\r
-    FTC_INode          node = 0;  /* make compiler happy */\r
-    FT_Error           error;\r
-    FT_UInt32          hash;\r
-\r
-\r
-    /* some argument checks are delayed to FTC_Cache_Lookup */\r
-    if ( !aglyph || !scaler )\r
-    {\r
-      error = FTC_Err_Invalid_Argument;\r
-      goto Exit;\r
-    }\r
-\r
-    *aglyph = NULL;\r
-    if ( anode )\r
-      *anode  = NULL;\r
-\r
-    query.attrs.scaler     = scaler[0];\r
-    query.attrs.load_flags = load_flags;\r
-\r
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;\r
-\r
-    FTC_GCACHE_LOOKUP_CMP( cache,\r
-                           ftc_basic_family_compare,\r
-                           FTC_GNode_Compare,\r
-                           hash, gindex,\r
-                           &query,\r
-                           node,\r
-                           error );\r
-    if ( !error )\r
-    {\r
-      *aglyph = FTC_INODE( node )->glyph;\r
-\r
-      if ( anode )\r
-      {\r
-        *anode = FTC_NODE( node );\r
-        FTC_NODE( node )->ref_count++;\r
-      }\r
-    }\r
-\r
-  Exit:\r
-    return error;\r
-  }\r
-\r
-\r
-\r
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS\r
-\r
-  /* yet another backwards-legacy structure */\r
-  typedef struct  FTC_OldImage_Desc_\r
-  {\r
-    FTC_FontRec  font;\r
-    FT_UInt      image_type;\r
-\r
-  } FTC_OldImage_Desc;\r
-\r
-\r
-#define FTC_OLD_IMAGE_FORMAT( x )  ( (x) & 7 )\r
-\r
-\r
-#define ftc_old_image_format_bitmap    0x0000\r
-#define ftc_old_image_format_outline   0x0001\r
-\r
-#define ftc_old_image_format_mask      0x000F\r
-\r
-#define ftc_old_image_flag_monochrome  0x0010\r
-#define ftc_old_image_flag_unhinted    0x0020\r
-#define ftc_old_image_flag_autohinted  0x0040\r
-#define ftc_old_image_flag_unscaled    0x0080\r
-#define ftc_old_image_flag_no_sbits    0x0100\r
-\r
-  /* monochrome bitmap */\r
-#define ftc_old_image_mono             ftc_old_image_format_bitmap   | \\r
-                                       ftc_old_image_flag_monochrome\r
-\r
-  /* anti-aliased bitmap */\r
-#define ftc_old_image_grays            ftc_old_image_format_bitmap\r
-\r
-  /* scaled outline */\r
-#define ftc_old_image_outline          ftc_old_image_format_outline\r
-\r
-\r
-  static void\r
-  ftc_image_type_from_old_desc( FTC_ImageType       typ,\r
-                                FTC_OldImage_Desc*  desc )\r
-  {\r
-    typ->face_id = desc->font.face_id;\r
-    typ->width   = desc->font.pix_width;\r
-    typ->height  = desc->font.pix_height;\r
-\r
-    /* convert image type flags to load flags */\r
-    {\r
-      FT_UInt  load_flags = FT_LOAD_DEFAULT;\r
-      FT_UInt  type       = desc->image_type;\r
-\r
-\r
-      /* determine load flags, depending on the font description's */\r
-      /* image type                                                */\r
-\r
-      if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )\r
-      {\r
-        if ( type & ftc_old_image_flag_monochrome )\r
-          load_flags |= FT_LOAD_MONOCHROME;\r
-\r
-        /* disable embedded bitmaps loading if necessary */\r
-        if ( type & ftc_old_image_flag_no_sbits )\r
-          load_flags |= FT_LOAD_NO_BITMAP;\r
-      }\r
-      else\r
-      {\r
-        /* we want an outline, don't load embedded bitmaps */\r
-        load_flags |= FT_LOAD_NO_BITMAP;\r
-\r
-        if ( type & ftc_old_image_flag_unscaled )\r
-          load_flags |= FT_LOAD_NO_SCALE;\r
-      }\r
-\r
-      /* always render glyphs to bitmaps */\r
-      load_flags |= FT_LOAD_RENDER;\r
-\r
-      if ( type & ftc_old_image_flag_unhinted )\r
-        load_flags |= FT_LOAD_NO_HINTING;\r
-\r
-      if ( type & ftc_old_image_flag_autohinted )\r
-        load_flags |= FT_LOAD_FORCE_AUTOHINT;\r
-\r
-      typ->flags = load_flags;\r
-    }\r
-  }\r
-\r
-\r
-  FT_EXPORT( FT_Error )\r
-  FTC_Image_Cache_New( FTC_Manager      manager,\r
-                       FTC_ImageCache  *acache );\r
-\r
-  FT_EXPORT( FT_Error )\r
-  FTC_Image_Cache_Lookup( FTC_ImageCache      icache,\r
-                          FTC_OldImage_Desc*  desc,\r
-                          FT_UInt             gindex,\r
-                          FT_Glyph           *aglyph );\r
-\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_Image_Cache_New( FTC_Manager      manager,\r
-                       FTC_ImageCache  *acache )\r
-  {\r
-    return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );\r
-  }\r
-\r
-\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_Image_Cache_Lookup( FTC_ImageCache      icache,\r
-                          FTC_OldImage_Desc*  desc,\r
-                          FT_UInt             gindex,\r
-                          FT_Glyph           *aglyph )\r
-  {\r
-    FTC_ImageTypeRec  type0;\r
-\r
-\r
-    if ( !desc )\r
-      return FTC_Err_Invalid_Argument;\r
-\r
-    ftc_image_type_from_old_desc( &type0, desc );\r
-\r
-    return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,\r
-                                   &type0,\r
-                                   gindex,\r
-                                   aglyph,\r
-                                   NULL );\r
-  }\r
-\r
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */\r
-\r
-\r
- /*\r
-  *\r
-  * basic small bitmap cache\r
-  *\r
-  */\r
-\r
-\r
-  FT_CALLBACK_TABLE_DEF\r
-  const FTC_SFamilyClassRec  ftc_basic_sbit_family_class =\r
-  {\r
-    {\r
-      sizeof( FTC_BasicFamilyRec ),\r
-      ftc_basic_family_compare,\r
-      ftc_basic_family_init,\r
-      0,                            /* FTC_MruNode_ResetFunc */\r
-      0                             /* FTC_MruNode_DoneFunc  */\r
-    },\r
-    ftc_basic_family_get_count,\r
-    ftc_basic_family_load_bitmap\r
-  };\r
-\r
-\r
-  FT_CALLBACK_TABLE_DEF\r
-  const FTC_GCacheClassRec  ftc_basic_sbit_cache_class =\r
-  {\r
-    {\r
-      ftc_snode_new,\r
-      ftc_snode_weight,\r
-      ftc_snode_compare,\r
-      ftc_basic_gnode_compare_faceid,\r
-      ftc_snode_free,\r
-\r
-      sizeof ( FTC_GCacheRec ),\r
-      ftc_gcache_init,\r
-      ftc_gcache_done\r
-    },\r
-    (FTC_MruListClass)&ftc_basic_sbit_family_class\r
-  };\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_SBitCache_New( FTC_Manager     manager,\r
-                     FTC_SBitCache  *acache )\r
-  {\r
-    return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,\r
-                           (FTC_GCache*)acache );\r
-  }\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_SBitCache_Lookup( FTC_SBitCache  cache,\r
-                        FTC_ImageType  type,\r
-                        FT_UInt        gindex,\r
-                        FTC_SBit      *ansbit,\r
-                        FTC_Node      *anode )\r
-  {\r
-    FT_Error           error;\r
-    FTC_BasicQueryRec  query;\r
-    FTC_SNode          node = 0; /* make compiler happy */\r
-    FT_UInt32          hash;\r
-\r
-\r
-    if ( anode )\r
-      *anode = NULL;\r
-\r
-    /* other argument checks delayed to FTC_Cache_Lookup */\r
-    if ( !ansbit )\r
-      return FTC_Err_Invalid_Argument;\r
-\r
-    *ansbit = NULL;\r
-\r
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS\r
-\r
-    /*  This one is a major hack used to detect whether we are passed a\r
-     *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.\r
-     */\r
-    if ( type->width >= 0x10000 )\r
-    {\r
-      FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;\r
-\r
-\r
-      query.attrs.scaler.face_id = desc->font.face_id;\r
-      query.attrs.scaler.width   = desc->font.pix_width;\r
-      query.attrs.scaler.height  = desc->font.pix_height;\r
-      query.attrs.load_flags     = desc->flags;\r
-    }\r
-    else\r
-\r
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */\r
-\r
-    {\r
-      query.attrs.scaler.face_id = type->face_id;\r
-      query.attrs.scaler.width   = type->width;\r
-      query.attrs.scaler.height  = type->height;\r
-      query.attrs.load_flags     = type->flags;\r
-    }\r
-\r
-    query.attrs.scaler.pixel = 1;\r
-    query.attrs.scaler.x_res = 0;  /* make compilers happy */\r
-    query.attrs.scaler.y_res = 0;\r
-\r
-    /* beware, the hash must be the same for all glyph ranges! */\r
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +\r
-           gindex / FTC_SBIT_ITEMS_PER_NODE;\r
-\r
-#if 1  /* inlining is about 50% faster! */\r
-    FTC_GCACHE_LOOKUP_CMP( cache,\r
-                           ftc_basic_family_compare,\r
-                           FTC_SNode_Compare,\r
-                           hash, gindex,\r
-                           &query,\r
-                           node,\r
-                           error );\r
-#else\r
-    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),\r
-                               hash,\r
-                               gindex,\r
-                               FTC_GQUERY( &query ),\r
-                               (FTC_Node*)&node );\r
-#endif\r
-    if ( error )\r
-      goto Exit;\r
-\r
-    *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );\r
-\r
-    if ( anode )\r
-    {\r
-      *anode = FTC_NODE( node );\r
-      FTC_NODE( node )->ref_count++;\r
-    }\r
-\r
-  Exit:\r
-    return error;\r
-  }\r
-\r
-\r
-  /* documentation is in ftcache.h */\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_SBitCache_LookupScaler( FTC_SBitCache  cache,\r
-                              FTC_Scaler     scaler,\r
-                              FT_ULong       load_flags,\r
-                              FT_UInt        gindex,\r
-                              FTC_SBit      *ansbit,\r
-                              FTC_Node      *anode )\r
-  {\r
-    FT_Error           error;\r
-    FTC_BasicQueryRec  query;\r
-    FTC_SNode          node = 0; /* make compiler happy */\r
-    FT_UInt32          hash;\r
-\r
-\r
-    if ( anode )\r
-        *anode = NULL;\r
-\r
-    /* other argument checks delayed to FTC_Cache_Lookup */\r
-    if ( !ansbit || !scaler )\r
-        return FTC_Err_Invalid_Argument;\r
-\r
-    *ansbit = NULL;\r
-\r
-    query.attrs.scaler     = scaler[0];\r
-    query.attrs.load_flags = load_flags;\r
-\r
-    /* beware, the hash must be the same for all glyph ranges! */\r
-    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +\r
-             gindex / FTC_SBIT_ITEMS_PER_NODE;\r
-\r
-    FTC_GCACHE_LOOKUP_CMP( cache,\r
-                           ftc_basic_family_compare,\r
-                           FTC_SNode_Compare,\r
-                           hash, gindex,\r
-                           &query,\r
-                           node,\r
-                           error );\r
-    if ( error )\r
-      goto Exit;\r
-\r
-    *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );\r
-\r
-    if ( anode )\r
-    {\r
-      *anode = FTC_NODE( node );\r
-      FTC_NODE( node )->ref_count++;\r
-    }\r
-\r
-  Exit:\r
-    return error;\r
-  }\r
-\r
-\r
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS\r
-\r
-  FT_EXPORT( FT_Error )\r
-  FTC_SBit_Cache_New( FTC_Manager     manager,\r
-                      FTC_SBitCache  *acache );\r
-\r
-  FT_EXPORT( FT_Error )\r
-  FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,\r
-                         FTC_OldImage_Desc*  desc,\r
-                         FT_UInt             gindex,\r
-                         FTC_SBit           *ansbit );\r
-\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_SBit_Cache_New( FTC_Manager     manager,\r
-                      FTC_SBitCache  *acache )\r
-  {\r
-    return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );\r
-  }\r
-\r
-\r
-  FT_EXPORT_DEF( FT_Error )\r
-  FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,\r
-                         FTC_OldImage_Desc*  desc,\r
-                         FT_UInt             gindex,\r
-                         FTC_SBit           *ansbit )\r
-  {\r
-    FTC_ImageTypeRec  type0;\r
-\r
-\r
-    if ( !desc )\r
-      return FT_Err_Invalid_Argument;\r
-\r
-    ftc_image_type_from_old_desc( &type0, desc );\r
-\r
-    return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,\r
-                                  &type0,\r
-                                  gindex,\r
-                                  ansbit,\r
-                                  NULL );\r
-  }\r
-\r
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */\r
-\r
-\r
-/* END */\r
+/***************************************************************************/
+/*                                                                         */
+/*  ftcbasic.c                                                             */
+/*                                                                         */
+/*    The FreeType basic cache interface (body).                           */
+/*                                                                         */
+/*  Copyright 2003, 2004, 2005, 2006, 2007 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 <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+#include "ftcimage.h"
+#include "ftcsbits.h"
+#include FT_INTERNAL_MEMORY_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+  /*
+   *  These structures correspond to the FTC_Font and FTC_ImageDesc types
+   *  that were defined in version 2.1.7.
+   */
+  typedef struct  FTC_OldFontRec_
+  {
+    FTC_FaceID  face_id;
+    FT_UShort   pix_width;
+    FT_UShort   pix_height;
+
+  } FTC_OldFontRec, *FTC_OldFont;
+
+
+  typedef struct  FTC_OldImageDescRec_
+  {
+    FTC_OldFontRec  font;
+    FT_UInt32       flags;
+
+  } FTC_OldImageDescRec, *FTC_OldImageDesc;
+
+
+  /*
+   *  Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly
+   *  identical, bit-wise.  The only difference is that the `width' and
+   *  `height' fields are expressed as 16-bit integers in the old structure,
+   *  and as normal `int' in the new one.
+   *
+   *  We are going to perform a weird hack to detect which structure is
+   *  being passed to the image and sbit caches.  If the new structure's
+   *  `width' is larger than 0x10000, we assume that we are really receiving
+   *  an FTC_OldImageDesc.
+   */
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+  /*
+   *  Basic Families
+   *
+   */
+  typedef struct  FTC_BasicAttrRec_
+  {
+    FTC_ScalerRec  scaler;
+    FT_UInt        load_flags;
+
+  } FTC_BasicAttrRec, *FTC_BasicAttrs;
+
+#define FTC_BASIC_ATTR_COMPARE( a, b )                                 \
+          FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
+                   (a)->load_flags == (b)->load_flags               )
+
+#define FTC_BASIC_ATTR_HASH( a )                                   \
+          ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
+
+
+  typedef struct  FTC_BasicQueryRec_
+  {
+    FTC_GQueryRec     gquery;
+    FTC_BasicAttrRec  attrs;
+
+  } FTC_BasicQueryRec, *FTC_BasicQuery;
+
+
+  typedef struct  FTC_BasicFamilyRec_
+  {
+    FTC_FamilyRec     family;
+    FTC_BasicAttrRec  attrs;
+
+  } FTC_BasicFamilyRec, *FTC_BasicFamily;
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_basic_family_compare( FTC_MruNode  ftcfamily,
+                            FT_Pointer   ftcquery )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
+
+
+    return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_init( FTC_MruNode  ftcfamily,
+                         FT_Pointer   ftcquery,
+                         FT_Pointer   ftccache )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
+    FTC_Cache        cache  = (FTC_Cache)ftccache;
+
+
+    FTC_Family_Init( FTC_FAMILY( family ), cache );
+    family->attrs = query->attrs;
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  ftc_basic_family_get_count( FTC_Family   ftcfamily,
+                              FTC_Manager  manager )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FT_Face          face;
+    FT_UInt          result = 0;
+
+
+    error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
+                                    &face );
+    if ( !error )
+      result = face->num_glyphs;
+
+    return result;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_load_bitmap( FTC_Family   ftcfamily,
+                                FT_UInt      gindex,
+                                FTC_Manager  manager,
+                                FT_Face     *aface )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FT_Size          size;
+
+
+    error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
+    if ( !error )
+    {
+      FT_Face  face = size->face;
+
+
+      error = FT_Load_Glyph( face, gindex,
+                             family->attrs.load_flags | FT_LOAD_RENDER );
+      if ( !error )
+        *aface = face;
+    }
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_load_glyph( FTC_Family  ftcfamily,
+                               FT_UInt     gindex,
+                               FTC_Cache   cache,
+                               FT_Glyph   *aglyph )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FTC_Scaler       scaler = &family->attrs.scaler;
+    FT_Face          face;
+    FT_Size          size;
+
+
+    /* we will now load the glyph image */
+    error = FTC_Manager_LookupSize( cache->manager,
+                                    scaler,
+                                    &size );
+    if ( !error )
+    {
+      face = size->face;
+
+      error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
+      if ( !error )
+      {
+        if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
+             face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+        {
+          /* ok, copy it */
+          FT_Glyph  glyph;
+
+
+          error = FT_Get_Glyph( face->glyph, &glyph );
+          if ( !error )
+          {
+            *aglyph = glyph;
+            goto Exit;
+          }
+        }
+        else
+          error = FTC_Err_Invalid_Argument;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_basic_gnode_compare_faceid( FTC_Node    ftcgnode,
+                                  FT_Pointer  ftcface_id,
+                                  FTC_Cache   cache )
+  {
+    FTC_GNode        gnode   = (FTC_GNode)ftcgnode;
+    FTC_FaceID       face_id = (FTC_FaceID)ftcface_id;
+    FTC_BasicFamily  family  = (FTC_BasicFamily)gnode->family;
+    FT_Bool          result;
+
+
+    result = FT_BOOL( family->attrs.scaler.face_id == face_id );
+    if ( result )
+    {
+      /* we must call this function to avoid this node from appearing
+       * in later lookups with the same face_id!
+       */
+      FTC_GNode_UnselectFamily( gnode, cache );
+    }
+    return result;
+  }
+
+
+ /*
+  *
+  * basic image cache
+  *
+  */
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_IFamilyClassRec  ftc_basic_image_family_class =
+  {
+    {
+      sizeof ( FTC_BasicFamilyRec ),
+      ftc_basic_family_compare,
+      ftc_basic_family_init,
+      0,                        /* FTC_MruNode_ResetFunc */
+      0                         /* FTC_MruNode_DoneFunc  */
+    },
+    ftc_basic_family_load_glyph
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_GCacheClassRec  ftc_basic_image_cache_class =
+  {
+    {
+      ftc_inode_new,
+      ftc_inode_weight,
+      ftc_gnode_compare,
+      ftc_basic_gnode_compare_faceid,
+      ftc_inode_free,
+
+      sizeof ( FTC_GCacheRec ),
+      ftc_gcache_init,
+      ftc_gcache_done
+    },
+    (FTC_MruListClass)&ftc_basic_image_family_class
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_New( FTC_Manager      manager,
+                      FTC_ImageCache  *acache )
+  {
+    return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
+                           (FTC_GCache*)acache );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_Lookup( FTC_ImageCache  cache,
+                         FTC_ImageType   type,
+                         FT_UInt         gindex,
+                         FT_Glyph       *aglyph,
+                         FTC_Node       *anode )
+  {
+    FTC_BasicQueryRec  query;
+    FTC_INode          node = 0;  /* make compiler happy */
+    FT_Error           error;
+    FT_UInt32          hash;
+
+
+    /* some argument checks are delayed to FTC_Cache_Lookup */
+    if ( !aglyph )
+    {
+      error = FTC_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    *aglyph = NULL;
+    if ( anode )
+      *anode  = NULL;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+    /*
+     *  This one is a major hack used to detect whether we are passed a
+     *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
+     */
+    if ( type->width >= 0x10000 )
+    {
+      FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;
+
+
+      query.attrs.scaler.face_id = desc->font.face_id;
+      query.attrs.scaler.width   = desc->font.pix_width;
+      query.attrs.scaler.height  = desc->font.pix_height;
+      query.attrs.load_flags     = desc->flags;
+    }
+    else
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+    {
+      query.attrs.scaler.face_id = type->face_id;
+      query.attrs.scaler.width   = type->width;
+      query.attrs.scaler.height  = type->height;
+      query.attrs.load_flags     = type->flags;
+    }
+
+    query.attrs.scaler.pixel = 1;
+    query.attrs.scaler.x_res = 0;  /* make compilers happy */
+    query.attrs.scaler.y_res = 0;
+
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
+
+#if 1  /* inlining is about 50% faster! */
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_GNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+#else
+    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+                               hash, gindex,
+                               FTC_GQUERY( &query ),
+                               (FTC_Node*) &node );
+#endif
+    if ( !error )
+    {
+      *aglyph = FTC_INODE( node )->glyph;
+
+      if ( anode )
+      {
+        *anode = FTC_NODE( node );
+        FTC_NODE( node )->ref_count++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_LookupScaler( FTC_ImageCache  cache,
+                               FTC_Scaler      scaler,
+                               FT_ULong        load_flags,
+                               FT_UInt         gindex,
+                               FT_Glyph       *aglyph,
+                               FTC_Node       *anode )
+  {
+    FTC_BasicQueryRec  query;
+    FTC_INode          node = 0;  /* make compiler happy */
+    FT_Error           error;
+    FT_UInt32          hash;
+
+
+    /* some argument checks are delayed to FTC_Cache_Lookup */
+    if ( !aglyph || !scaler )
+    {
+      error = FTC_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    *aglyph = NULL;
+    if ( anode )
+      *anode  = NULL;
+
+    query.attrs.scaler     = scaler[0];
+    query.attrs.load_flags = load_flags;
+
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
+
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_GNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+    if ( !error )
+    {
+      *aglyph = FTC_INODE( node )->glyph;
+
+      if ( anode )
+      {
+        *anode = FTC_NODE( node );
+        FTC_NODE( node )->ref_count++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+  /* yet another backwards-legacy structure */
+  typedef struct  FTC_OldImage_Desc_
+  {
+    FTC_FontRec  font;
+    FT_UInt      image_type;
+
+  } FTC_OldImage_Desc;
+
+
+#define FTC_OLD_IMAGE_FORMAT( x )  ( (x) & 7 )
+
+
+#define ftc_old_image_format_bitmap    0x0000
+#define ftc_old_image_format_outline   0x0001
+
+#define ftc_old_image_format_mask      0x000F
+
+#define ftc_old_image_flag_monochrome  0x0010
+#define ftc_old_image_flag_unhinted    0x0020
+#define ftc_old_image_flag_autohinted  0x0040
+#define ftc_old_image_flag_unscaled    0x0080
+#define ftc_old_image_flag_no_sbits    0x0100
+
+  /* monochrome bitmap */
+#define ftc_old_image_mono             ftc_old_image_format_bitmap   | \
+                                       ftc_old_image_flag_monochrome
+
+  /* anti-aliased bitmap */
+#define ftc_old_image_grays            ftc_old_image_format_bitmap
+
+  /* scaled outline */
+#define ftc_old_image_outline          ftc_old_image_format_outline
+
+
+  static void
+  ftc_image_type_from_old_desc( FTC_ImageType       typ,
+                                FTC_OldImage_Desc*  desc )
+  {
+    typ->face_id = desc->font.face_id;
+    typ->width   = desc->font.pix_width;
+    typ->height  = desc->font.pix_height;
+
+    /* convert image type flags to load flags */
+    {
+      FT_UInt  load_flags = FT_LOAD_DEFAULT;
+      FT_UInt  type       = desc->image_type;
+
+
+      /* determine load flags, depending on the font description's */
+      /* image type                                                */
+
+      if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )
+      {
+        if ( type & ftc_old_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( type & ftc_old_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else
+      {
+        /* we want an outline, don't load embedded bitmaps */
+        load_flags |= FT_LOAD_NO_BITMAP;
+
+        if ( type & ftc_old_image_flag_unscaled )
+          load_flags |= FT_LOAD_NO_SCALE;
+      }
+
+      /* always render glyphs to bitmaps */
+      load_flags |= FT_LOAD_RENDER;
+
+      if ( type & ftc_old_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( type & ftc_old_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+      typ->flags = load_flags;
+    }
+  }
+
+
+  FT_EXPORT( FT_Error )
+  FTC_Image_Cache_New( FTC_Manager      manager,
+                       FTC_ImageCache  *acache );
+
+  FT_EXPORT( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_ImageCache      icache,
+                          FTC_OldImage_Desc*  desc,
+                          FT_UInt             gindex,
+                          FT_Glyph           *aglyph );
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_New( FTC_Manager      manager,
+                       FTC_ImageCache  *acache )
+  {
+    return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
+  }
+
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_ImageCache      icache,
+                          FTC_OldImage_Desc*  desc,
+                          FT_UInt             gindex,
+                          FT_Glyph           *aglyph )
+  {
+    FTC_ImageTypeRec  type0;
+
+
+    if ( !desc )
+      return FTC_Err_Invalid_Argument;
+
+    ftc_image_type_from_old_desc( &type0, desc );
+
+    return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
+                                   &type0,
+                                   gindex,
+                                   aglyph,
+                                   NULL );
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*
+  *
+  * basic small bitmap cache
+  *
+  */
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_SFamilyClassRec  ftc_basic_sbit_family_class =
+  {
+    {
+      sizeof( FTC_BasicFamilyRec ),
+      ftc_basic_family_compare,
+      ftc_basic_family_init,
+      0,                            /* FTC_MruNode_ResetFunc */
+      0                             /* FTC_MruNode_DoneFunc  */
+    },
+    ftc_basic_family_get_count,
+    ftc_basic_family_load_bitmap
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_GCacheClassRec  ftc_basic_sbit_cache_class =
+  {
+    {
+      ftc_snode_new,
+      ftc_snode_weight,
+      ftc_snode_compare,
+      ftc_basic_gnode_compare_faceid,
+      ftc_snode_free,
+
+      sizeof ( FTC_GCacheRec ),
+      ftc_gcache_init,
+      ftc_gcache_done
+    },
+    (FTC_MruListClass)&ftc_basic_sbit_family_class
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_New( FTC_Manager     manager,
+                     FTC_SBitCache  *acache )
+  {
+    return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
+                           (FTC_GCache*)acache );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_Lookup( FTC_SBitCache  cache,
+                        FTC_ImageType  type,
+                        FT_UInt        gindex,
+                        FTC_SBit      *ansbit,
+                        FTC_Node      *anode )
+  {
+    FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_SNode          node = 0; /* make compiler happy */
+    FT_UInt32          hash;
+
+
+    if ( anode )
+      *anode = NULL;
+
+    /* other argument checks delayed to FTC_Cache_Lookup */
+    if ( !ansbit )
+      return FTC_Err_Invalid_Argument;
+
+    *ansbit = NULL;
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+    /*  This one is a major hack used to detect whether we are passed a
+     *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
+     */
+    if ( type->width >= 0x10000 )
+    {
+      FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;
+
+
+      query.attrs.scaler.face_id = desc->font.face_id;
+      query.attrs.scaler.width   = desc->font.pix_width;
+      query.attrs.scaler.height  = desc->font.pix_height;
+      query.attrs.load_flags     = desc->flags;
+    }
+    else
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+    {
+      query.attrs.scaler.face_id = type->face_id;
+      query.attrs.scaler.width   = type->width;
+      query.attrs.scaler.height  = type->height;
+      query.attrs.load_flags     = type->flags;
+    }
+
+    query.attrs.scaler.pixel = 1;
+    query.attrs.scaler.x_res = 0;  /* make compilers happy */
+    query.attrs.scaler.y_res = 0;
+
+    /* beware, the hash must be the same for all glyph ranges! */
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
+           gindex / FTC_SBIT_ITEMS_PER_NODE;
+
+#if 1  /* inlining is about 50% faster! */
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_SNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+#else
+    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+                               hash,
+                               gindex,
+                               FTC_GQUERY( &query ),
+                               (FTC_Node*)&node );
+#endif
+    if ( error )
+      goto Exit;
+
+    *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
+
+    if ( anode )
+    {
+      *anode = FTC_NODE( node );
+      FTC_NODE( node )->ref_count++;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_LookupScaler( FTC_SBitCache  cache,
+                              FTC_Scaler     scaler,
+                              FT_ULong       load_flags,
+                              FT_UInt        gindex,
+                              FTC_SBit      *ansbit,
+                              FTC_Node      *anode )
+  {
+    FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_SNode          node = 0; /* make compiler happy */
+    FT_UInt32          hash;
+
+
+    if ( anode )
+        *anode = NULL;
+
+    /* other argument checks delayed to FTC_Cache_Lookup */
+    if ( !ansbit || !scaler )
+        return FTC_Err_Invalid_Argument;
+
+    *ansbit = NULL;
+
+    query.attrs.scaler     = scaler[0];
+    query.attrs.load_flags = load_flags;
+
+    /* beware, the hash must be the same for all glyph ranges! */
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
+             gindex / FTC_SBIT_ITEMS_PER_NODE;
+
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_SNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+    if ( error )
+      goto Exit;
+
+    *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
+
+    if ( anode )
+    {
+      *anode = FTC_NODE( node );
+      FTC_NODE( node )->ref_count++;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+  FT_EXPORT( FT_Error )
+  FTC_SBit_Cache_New( FTC_Manager     manager,
+                      FTC_SBitCache  *acache );
+
+  FT_EXPORT( FT_Error )
+  FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,
+                         FTC_OldImage_Desc*  desc,
+                         FT_UInt             gindex,
+                         FTC_SBit           *ansbit );
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_New( FTC_Manager     manager,
+                      FTC_SBitCache  *acache )
+  {
+    return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,
+                         FTC_OldImage_Desc*  desc,
+                         FT_UInt             gindex,
+                         FTC_SBit           *ansbit )
+  {
+    FTC_ImageTypeRec  type0;
+
+
+    if ( !desc )
+      return FT_Err_Invalid_Argument;
+
+    ftc_image_type_from_old_desc( &type0, desc );
+
+    return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
+                                  &type0,
+                                  gindex,
+                                  ansbit,
+                                  NULL );
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+/* END */