Home | History | Annotate | Download | only in cache
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftcbasic.c                                                             */
      4 /*                                                                         */
      5 /*    The FreeType basic cache interface (body).                           */
      6 /*                                                                         */
      7 /*  Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 by            */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_OBJECTS_H
     21 #include FT_INTERNAL_DEBUG_H
     22 #include FT_CACHE_H
     23 #include "ftcglyph.h"
     24 #include "ftcimage.h"
     25 #include "ftcsbits.h"
     26 
     27 #include "ftccback.h"
     28 #include "ftcerror.h"
     29 
     30 #define FT_COMPONENT  trace_cache
     31 
     32 
     33 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
     34 
     35   /*
     36    *  These structures correspond to the FTC_Font and FTC_ImageDesc types
     37    *  that were defined in version 2.1.7.
     38    */
     39   typedef struct  FTC_OldFontRec_
     40   {
     41     FTC_FaceID  face_id;
     42     FT_UShort   pix_width;
     43     FT_UShort   pix_height;
     44 
     45   } FTC_OldFontRec, *FTC_OldFont;
     46 
     47 
     48   typedef struct  FTC_OldImageDescRec_
     49   {
     50     FTC_OldFontRec  font;
     51     FT_UInt32       flags;
     52 
     53   } FTC_OldImageDescRec, *FTC_OldImageDesc;
     54 
     55 
     56   /*
     57    *  Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly
     58    *  identical, bit-wise.  The only difference is that the `width' and
     59    *  `height' fields are expressed as 16-bit integers in the old structure,
     60    *  and as normal `int' in the new one.
     61    *
     62    *  We are going to perform a weird hack to detect which structure is
     63    *  being passed to the image and sbit caches.  If the new structure's
     64    *  `width' is larger than 0x10000, we assume that we are really receiving
     65    *  an FTC_OldImageDesc.
     66    */
     67 
     68 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
     69 
     70 
     71   /*
     72    *  Basic Families
     73    *
     74    */
     75   typedef struct  FTC_BasicAttrRec_
     76   {
     77     FTC_ScalerRec  scaler;
     78     FT_UInt        load_flags;
     79 
     80   } FTC_BasicAttrRec, *FTC_BasicAttrs;
     81 
     82 #define FTC_BASIC_ATTR_COMPARE( a, b )                                 \
     83           FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
     84                    (a)->load_flags == (b)->load_flags               )
     85 
     86 #define FTC_BASIC_ATTR_HASH( a )                                   \
     87           ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
     88 
     89 
     90   typedef struct  FTC_BasicQueryRec_
     91   {
     92     FTC_GQueryRec     gquery;
     93     FTC_BasicAttrRec  attrs;
     94 
     95   } FTC_BasicQueryRec, *FTC_BasicQuery;
     96 
     97 
     98   typedef struct  FTC_BasicFamilyRec_
     99   {
    100     FTC_FamilyRec     family;
    101     FTC_BasicAttrRec  attrs;
    102 
    103   } FTC_BasicFamilyRec, *FTC_BasicFamily;
    104 
    105 
    106   FT_CALLBACK_DEF( FT_Bool )
    107   ftc_basic_family_compare( FTC_MruNode  ftcfamily,
    108                             FT_Pointer   ftcquery )
    109   {
    110     FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
    111     FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
    112 
    113 
    114     return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
    115   }
    116 
    117 
    118   FT_CALLBACK_DEF( FT_Error )
    119   ftc_basic_family_init( FTC_MruNode  ftcfamily,
    120                          FT_Pointer   ftcquery,
    121                          FT_Pointer   ftccache )
    122   {
    123     FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
    124     FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
    125     FTC_Cache        cache  = (FTC_Cache)ftccache;
    126 
    127 
    128     FTC_Family_Init( FTC_FAMILY( family ), cache );
    129     family->attrs = query->attrs;
    130     return 0;
    131   }
    132 
    133 
    134   FT_CALLBACK_DEF( FT_UInt )
    135   ftc_basic_family_get_count( FTC_Family   ftcfamily,
    136                               FTC_Manager  manager )
    137   {
    138     FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
    139     FT_Error         error;
    140     FT_Face          face;
    141     FT_UInt          result = 0;
    142 
    143 
    144     error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
    145                                     &face );
    146 
    147     if ( error || !face )
    148       return result;
    149 
    150     if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
    151     {
    152       FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
    153       FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
    154     }
    155 
    156     if ( !error )
    157       result = (FT_UInt)face->num_glyphs;
    158 
    159     return result;
    160   }
    161 
    162 
    163   FT_CALLBACK_DEF( FT_Error )
    164   ftc_basic_family_load_bitmap( FTC_Family   ftcfamily,
    165                                 FT_UInt      gindex,
    166                                 FTC_Manager  manager,
    167                                 FT_Face     *aface )
    168   {
    169     FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
    170     FT_Error         error;
    171     FT_Size          size;
    172 
    173 
    174     error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
    175     if ( !error )
    176     {
    177       FT_Face  face = size->face;
    178 
    179 
    180       error = FT_Load_Glyph( face, gindex,
    181                              family->attrs.load_flags | FT_LOAD_RENDER );
    182       if ( !error )
    183         *aface = face;
    184     }
    185 
    186     return error;
    187   }
    188 
    189 
    190   FT_CALLBACK_DEF( FT_Error )
    191   ftc_basic_family_load_glyph( FTC_Family  ftcfamily,
    192                                FT_UInt     gindex,
    193                                FTC_Cache   cache,
    194                                FT_Glyph   *aglyph )
    195   {
    196     FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
    197     FT_Error         error;
    198     FTC_Scaler       scaler = &family->attrs.scaler;
    199     FT_Face          face;
    200     FT_Size          size;
    201 
    202 
    203     /* we will now load the glyph image */
    204     error = FTC_Manager_LookupSize( cache->manager,
    205                                     scaler,
    206                                     &size );
    207     if ( !error )
    208     {
    209       face = size->face;
    210 
    211       error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
    212       if ( !error )
    213       {
    214         if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
    215              face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
    216         {
    217           /* ok, copy it */
    218           FT_Glyph  glyph;
    219 
    220 
    221           error = FT_Get_Glyph( face->glyph, &glyph );
    222           if ( !error )
    223           {
    224             *aglyph = glyph;
    225             goto Exit;
    226           }
    227         }
    228         else
    229           error = FTC_Err_Invalid_Argument;
    230       }
    231     }
    232 
    233   Exit:
    234     return error;
    235   }
    236 
    237 
    238   FT_CALLBACK_DEF( FT_Bool )
    239   ftc_basic_gnode_compare_faceid( FTC_Node    ftcgnode,
    240                                   FT_Pointer  ftcface_id,
    241                                   FTC_Cache   cache,
    242                                   FT_Bool*    list_changed )
    243   {
    244     FTC_GNode        gnode   = (FTC_GNode)ftcgnode;
    245     FTC_FaceID       face_id = (FTC_FaceID)ftcface_id;
    246     FTC_BasicFamily  family  = (FTC_BasicFamily)gnode->family;
    247     FT_Bool          result;
    248 
    249 
    250     if ( list_changed )
    251       *list_changed = FALSE;
    252     result = FT_BOOL( family->attrs.scaler.face_id == face_id );
    253     if ( result )
    254     {
    255       /* we must call this function to avoid this node from appearing
    256        * in later lookups with the same face_id!
    257        */
    258       FTC_GNode_UnselectFamily( gnode, cache );
    259     }
    260     return result;
    261   }
    262 
    263 
    264  /*
    265   *
    266   * basic image cache
    267   *
    268   */
    269 
    270   FT_CALLBACK_TABLE_DEF
    271   const FTC_IFamilyClassRec  ftc_basic_image_family_class =
    272   {
    273     {
    274       sizeof ( FTC_BasicFamilyRec ),
    275       ftc_basic_family_compare,
    276       ftc_basic_family_init,
    277       0,                        /* FTC_MruNode_ResetFunc */
    278       0                         /* FTC_MruNode_DoneFunc  */
    279     },
    280     ftc_basic_family_load_glyph
    281   };
    282 
    283 
    284   FT_CALLBACK_TABLE_DEF
    285   const FTC_GCacheClassRec  ftc_basic_image_cache_class =
    286   {
    287     {
    288       ftc_inode_new,
    289       ftc_inode_weight,
    290       ftc_gnode_compare,
    291       ftc_basic_gnode_compare_faceid,
    292       ftc_inode_free,
    293 
    294       sizeof ( FTC_GCacheRec ),
    295       ftc_gcache_init,
    296       ftc_gcache_done
    297     },
    298     (FTC_MruListClass)&ftc_basic_image_family_class
    299   };
    300 
    301 
    302   /* documentation is in ftcache.h */
    303 
    304   FT_EXPORT_DEF( FT_Error )
    305   FTC_ImageCache_New( FTC_Manager      manager,
    306                       FTC_ImageCache  *acache )
    307   {
    308     return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
    309                            (FTC_GCache*)acache );
    310   }
    311 
    312 
    313   /* documentation is in ftcache.h */
    314 
    315   FT_EXPORT_DEF( FT_Error )
    316   FTC_ImageCache_Lookup( FTC_ImageCache  cache,
    317                          FTC_ImageType   type,
    318                          FT_UInt         gindex,
    319                          FT_Glyph       *aglyph,
    320                          FTC_Node       *anode )
    321   {
    322     FTC_BasicQueryRec  query;
    323     FTC_Node           node = 0; /* make compiler happy */
    324     FT_Error           error;
    325     FT_PtrDist         hash;
    326 
    327 
    328     /* some argument checks are delayed to FTC_Cache_Lookup */
    329     if ( !aglyph )
    330     {
    331       error = FTC_Err_Invalid_Argument;
    332       goto Exit;
    333     }
    334 
    335     *aglyph = NULL;
    336     if ( anode )
    337       *anode  = NULL;
    338 
    339 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )
    340 
    341     /*
    342      *  This one is a major hack used to detect whether we are passed a
    343      *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
    344      */
    345     if ( (FT_ULong)type->width >= 0x10000L )
    346     {
    347       FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;
    348 
    349 
    350       query.attrs.scaler.face_id = desc->font.face_id;
    351       query.attrs.scaler.width   = desc->font.pix_width;
    352       query.attrs.scaler.height  = desc->font.pix_height;
    353       query.attrs.load_flags     = desc->flags;
    354     }
    355     else
    356 
    357 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
    358 
    359     {
    360       if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
    361       {
    362         FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
    363         FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
    364       }
    365 
    366       query.attrs.scaler.face_id = type->face_id;
    367       query.attrs.scaler.width   = type->width;
    368       query.attrs.scaler.height  = type->height;
    369       query.attrs.load_flags     = (FT_UInt)type->flags;
    370     }
    371 
    372     query.attrs.scaler.pixel = 1;
    373     query.attrs.scaler.x_res = 0;  /* make compilers happy */
    374     query.attrs.scaler.y_res = 0;
    375 
    376     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
    377 
    378 #if 1  /* inlining is about 50% faster! */
    379     FTC_GCACHE_LOOKUP_CMP( cache,
    380                            ftc_basic_family_compare,
    381                            FTC_GNode_Compare,
    382                            hash, gindex,
    383                            &query,
    384                            node,
    385                            error );
    386 #else
    387     error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
    388                                hash, gindex,
    389                                FTC_GQUERY( &query ),
    390                                &node );
    391 #endif
    392     if ( !error )
    393     {
    394       *aglyph = FTC_INODE( node )->glyph;
    395 
    396       if ( anode )
    397       {
    398         *anode = node;
    399         node->ref_count++;
    400       }
    401     }
    402 
    403   Exit:
    404     return error;
    405   }
    406 
    407 
    408   /* documentation is in ftcache.h */
    409 
    410   FT_EXPORT_DEF( FT_Error )
    411   FTC_ImageCache_LookupScaler( FTC_ImageCache  cache,
    412                                FTC_Scaler      scaler,
    413                                FT_ULong        load_flags,
    414                                FT_UInt         gindex,
    415                                FT_Glyph       *aglyph,
    416                                FTC_Node       *anode )
    417   {
    418     FTC_BasicQueryRec  query;
    419     FTC_Node           node = 0; /* make compiler happy */
    420     FT_Error           error;
    421     FT_PtrDist         hash;
    422 
    423 
    424     /* some argument checks are delayed to FTC_Cache_Lookup */
    425     if ( !aglyph || !scaler )
    426     {
    427       error = FTC_Err_Invalid_Argument;
    428       goto Exit;
    429     }
    430 
    431     *aglyph = NULL;
    432     if ( anode )
    433       *anode  = NULL;
    434 
    435     /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
    436     if ( load_flags > FT_UINT_MAX )
    437     {
    438       FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
    439       FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
    440     }
    441 
    442     query.attrs.scaler     = scaler[0];
    443     query.attrs.load_flags = (FT_UInt)load_flags;
    444 
    445     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
    446 
    447     FTC_GCACHE_LOOKUP_CMP( cache,
    448                            ftc_basic_family_compare,
    449                            FTC_GNode_Compare,
    450                            hash, gindex,
    451                            &query,
    452                            node,
    453                            error );
    454     if ( !error )
    455     {
    456       *aglyph = FTC_INODE( node )->glyph;
    457 
    458       if ( anode )
    459       {
    460         *anode = node;
    461         node->ref_count++;
    462       }
    463     }
    464 
    465   Exit:
    466     return error;
    467   }
    468 
    469 
    470 
    471 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
    472 
    473   /* yet another backwards-legacy structure */
    474   typedef struct  FTC_OldImage_Desc_
    475   {
    476     FTC_FontRec  font;
    477     FT_UInt      image_type;
    478 
    479   } FTC_OldImage_Desc;
    480 
    481 
    482 #define FTC_OLD_IMAGE_FORMAT( x )  ( (x) & 7 )
    483 
    484 
    485 #define ftc_old_image_format_bitmap    0x0000
    486 #define ftc_old_image_format_outline   0x0001
    487 
    488 #define ftc_old_image_format_mask      0x000F
    489 
    490 #define ftc_old_image_flag_monochrome  0x0010
    491 #define ftc_old_image_flag_unhinted    0x0020
    492 #define ftc_old_image_flag_autohinted  0x0040
    493 #define ftc_old_image_flag_unscaled    0x0080
    494 #define ftc_old_image_flag_no_sbits    0x0100
    495 
    496   /* monochrome bitmap */
    497 #define ftc_old_image_mono             ftc_old_image_format_bitmap   | \
    498                                        ftc_old_image_flag_monochrome
    499 
    500   /* anti-aliased bitmap */
    501 #define ftc_old_image_grays            ftc_old_image_format_bitmap
    502 
    503   /* scaled outline */
    504 #define ftc_old_image_outline          ftc_old_image_format_outline
    505 
    506 
    507   static void
    508   ftc_image_type_from_old_desc( FTC_ImageType       typ,
    509                                 FTC_OldImage_Desc*  desc )
    510   {
    511     typ->face_id = desc->font.face_id;
    512     typ->width   = desc->font.pix_width;
    513     typ->height  = desc->font.pix_height;
    514 
    515     /* convert image type flags to load flags */
    516     {
    517       FT_UInt  load_flags = FT_LOAD_DEFAULT;
    518       FT_UInt  type       = desc->image_type;
    519 
    520 
    521       /* determine load flags, depending on the font description's */
    522       /* image type                                                */
    523 
    524       if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )
    525       {
    526         if ( type & ftc_old_image_flag_monochrome )
    527           load_flags |= FT_LOAD_MONOCHROME;
    528 
    529         /* disable embedded bitmaps loading if necessary */
    530         if ( type & ftc_old_image_flag_no_sbits )
    531           load_flags |= FT_LOAD_NO_BITMAP;
    532       }
    533       else
    534       {
    535         /* we want an outline, don't load embedded bitmaps */
    536         load_flags |= FT_LOAD_NO_BITMAP;
    537 
    538         if ( type & ftc_old_image_flag_unscaled )
    539           load_flags |= FT_LOAD_NO_SCALE;
    540       }
    541 
    542       /* always render glyphs to bitmaps */
    543       load_flags |= FT_LOAD_RENDER;
    544 
    545       if ( type & ftc_old_image_flag_unhinted )
    546         load_flags |= FT_LOAD_NO_HINTING;
    547 
    548       if ( type & ftc_old_image_flag_autohinted )
    549         load_flags |= FT_LOAD_FORCE_AUTOHINT;
    550 
    551       typ->flags = load_flags;
    552     }
    553   }
    554 
    555 
    556   FT_EXPORT( FT_Error )
    557   FTC_Image_Cache_New( FTC_Manager      manager,
    558                        FTC_ImageCache  *acache );
    559 
    560   FT_EXPORT( FT_Error )
    561   FTC_Image_Cache_Lookup( FTC_ImageCache      icache,
    562                           FTC_OldImage_Desc*  desc,
    563                           FT_UInt             gindex,
    564                           FT_Glyph           *aglyph );
    565 
    566 
    567   FT_EXPORT_DEF( FT_Error )
    568   FTC_Image_Cache_New( FTC_Manager      manager,
    569                        FTC_ImageCache  *acache )
    570   {
    571     return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
    572   }
    573 
    574 
    575 
    576   FT_EXPORT_DEF( FT_Error )
    577   FTC_Image_Cache_Lookup( FTC_ImageCache      icache,
    578                           FTC_OldImage_Desc*  desc,
    579                           FT_UInt             gindex,
    580                           FT_Glyph           *aglyph )
    581   {
    582     FTC_ImageTypeRec  type0;
    583 
    584 
    585     if ( !desc )
    586       return FTC_Err_Invalid_Argument;
    587 
    588     ftc_image_type_from_old_desc( &type0, desc );
    589 
    590     return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
    591                                    &type0,
    592                                    gindex,
    593                                    aglyph,
    594                                    NULL );
    595   }
    596 
    597 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
    598 
    599 
    600  /*
    601   *
    602   * basic small bitmap cache
    603   *
    604   */
    605 
    606 
    607   FT_CALLBACK_TABLE_DEF
    608   const FTC_SFamilyClassRec  ftc_basic_sbit_family_class =
    609   {
    610     {
    611       sizeof ( FTC_BasicFamilyRec ),
    612       ftc_basic_family_compare,
    613       ftc_basic_family_init,
    614       0,                            /* FTC_MruNode_ResetFunc */
    615       0                             /* FTC_MruNode_DoneFunc  */
    616     },
    617     ftc_basic_family_get_count,
    618     ftc_basic_family_load_bitmap
    619   };
    620 
    621 
    622   FT_CALLBACK_TABLE_DEF
    623   const FTC_GCacheClassRec  ftc_basic_sbit_cache_class =
    624   {
    625     {
    626       ftc_snode_new,
    627       ftc_snode_weight,
    628       ftc_snode_compare,
    629       ftc_basic_gnode_compare_faceid,
    630       ftc_snode_free,
    631 
    632       sizeof ( FTC_GCacheRec ),
    633       ftc_gcache_init,
    634       ftc_gcache_done
    635     },
    636     (FTC_MruListClass)&ftc_basic_sbit_family_class
    637   };
    638 
    639 
    640   /* documentation is in ftcache.h */
    641 
    642   FT_EXPORT_DEF( FT_Error )
    643   FTC_SBitCache_New( FTC_Manager     manager,
    644                      FTC_SBitCache  *acache )
    645   {
    646     return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
    647                            (FTC_GCache*)acache );
    648   }
    649 
    650 
    651   /* documentation is in ftcache.h */
    652 
    653   FT_EXPORT_DEF( FT_Error )
    654   FTC_SBitCache_Lookup( FTC_SBitCache  cache,
    655                         FTC_ImageType  type,
    656                         FT_UInt        gindex,
    657                         FTC_SBit      *ansbit,
    658                         FTC_Node      *anode )
    659   {
    660     FT_Error           error;
    661     FTC_BasicQueryRec  query;
    662     FTC_Node           node = 0; /* make compiler happy */
    663     FT_PtrDist         hash;
    664 
    665 
    666     if ( anode )
    667       *anode = NULL;
    668 
    669     /* other argument checks delayed to FTC_Cache_Lookup */
    670     if ( !ansbit )
    671       return FTC_Err_Invalid_Argument;
    672 
    673     *ansbit = NULL;
    674 
    675 #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )
    676 
    677     /*  This one is a major hack used to detect whether we are passed a
    678      *  regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.
    679      */
    680     if ( (FT_ULong)type->width >= 0x10000L )
    681     {
    682       FTC_OldImageDesc  desc = (FTC_OldImageDesc)type;
    683 
    684 
    685       query.attrs.scaler.face_id = desc->font.face_id;
    686       query.attrs.scaler.width   = desc->font.pix_width;
    687       query.attrs.scaler.height  = desc->font.pix_height;
    688       query.attrs.load_flags     = desc->flags;
    689     }
    690     else
    691 
    692 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
    693 
    694     {
    695       if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
    696       {
    697         FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
    698         FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
    699       }
    700 
    701       query.attrs.scaler.face_id = type->face_id;
    702       query.attrs.scaler.width   = type->width;
    703       query.attrs.scaler.height  = type->height;
    704       query.attrs.load_flags     = (FT_UInt)type->flags;
    705     }
    706 
    707     query.attrs.scaler.pixel = 1;
    708     query.attrs.scaler.x_res = 0;  /* make compilers happy */
    709     query.attrs.scaler.y_res = 0;
    710 
    711     /* beware, the hash must be the same for all glyph ranges! */
    712     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
    713            gindex / FTC_SBIT_ITEMS_PER_NODE;
    714 
    715 #if 1  /* inlining is about 50% faster! */
    716     FTC_GCACHE_LOOKUP_CMP( cache,
    717                            ftc_basic_family_compare,
    718                            FTC_SNode_Compare,
    719                            hash, gindex,
    720                            &query,
    721                            node,
    722                            error );
    723 #else
    724     error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
    725                                hash,
    726                                gindex,
    727                                FTC_GQUERY( &query ),
    728                                &node );
    729 #endif
    730     if ( error )
    731       goto Exit;
    732 
    733     *ansbit = FTC_SNODE( node )->sbits +
    734               ( gindex - FTC_GNODE( node )->gindex );
    735 
    736     if ( anode )
    737     {
    738       *anode = node;
    739       node->ref_count++;
    740     }
    741 
    742   Exit:
    743     return error;
    744   }
    745 
    746 
    747   /* documentation is in ftcache.h */
    748 
    749   FT_EXPORT_DEF( FT_Error )
    750   FTC_SBitCache_LookupScaler( FTC_SBitCache  cache,
    751                               FTC_Scaler     scaler,
    752                               FT_ULong       load_flags,
    753                               FT_UInt        gindex,
    754                               FTC_SBit      *ansbit,
    755                               FTC_Node      *anode )
    756   {
    757     FT_Error           error;
    758     FTC_BasicQueryRec  query;
    759     FTC_Node           node = 0; /* make compiler happy */
    760     FT_PtrDist         hash;
    761 
    762 
    763     if ( anode )
    764         *anode = NULL;
    765 
    766     /* other argument checks delayed to FTC_Cache_Lookup */
    767     if ( !ansbit || !scaler )
    768         return FTC_Err_Invalid_Argument;
    769 
    770     *ansbit = NULL;
    771 
    772     /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
    773     if ( load_flags > FT_UINT_MAX )
    774     {
    775       FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
    776       FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
    777     }
    778 
    779     query.attrs.scaler     = scaler[0];
    780     query.attrs.load_flags = (FT_UInt)load_flags;
    781 
    782     /* beware, the hash must be the same for all glyph ranges! */
    783     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
    784              gindex / FTC_SBIT_ITEMS_PER_NODE;
    785 
    786     FTC_GCACHE_LOOKUP_CMP( cache,
    787                            ftc_basic_family_compare,
    788                            FTC_SNode_Compare,
    789                            hash, gindex,
    790                            &query,
    791                            node,
    792                            error );
    793     if ( error )
    794       goto Exit;
    795 
    796     *ansbit = FTC_SNODE( node )->sbits +
    797               ( gindex - FTC_GNODE( node )->gindex );
    798 
    799     if ( anode )
    800     {
    801       *anode = node;
    802       node->ref_count++;
    803     }
    804 
    805   Exit:
    806     return error;
    807   }
    808 
    809 
    810 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
    811 
    812   FT_EXPORT( FT_Error )
    813   FTC_SBit_Cache_New( FTC_Manager     manager,
    814                       FTC_SBitCache  *acache );
    815 
    816   FT_EXPORT( FT_Error )
    817   FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,
    818                          FTC_OldImage_Desc*  desc,
    819                          FT_UInt             gindex,
    820                          FTC_SBit           *ansbit );
    821 
    822 
    823   FT_EXPORT_DEF( FT_Error )
    824   FTC_SBit_Cache_New( FTC_Manager     manager,
    825                       FTC_SBitCache  *acache )
    826   {
    827     return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
    828   }
    829 
    830 
    831   FT_EXPORT_DEF( FT_Error )
    832   FTC_SBit_Cache_Lookup( FTC_SBitCache       cache,
    833                          FTC_OldImage_Desc*  desc,
    834                          FT_UInt             gindex,
    835                          FTC_SBit           *ansbit )
    836   {
    837     FTC_ImageTypeRec  type0;
    838 
    839 
    840     if ( !desc )
    841       return FTC_Err_Invalid_Argument;
    842 
    843     ftc_image_type_from_old_desc( &type0, desc );
    844 
    845     return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
    846                                   &type0,
    847                                   gindex,
    848                                   ansbit,
    849                                   NULL );
    850   }
    851 
    852 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
    853 
    854 
    855 /* END */
    856