misc/libfreetype/src/cache/ftcbasic.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     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 */