-/***************************************************************************/\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 */