/modules/freetype2/src/cache/ftccmap.c
http://github.com/zpao/v8monkey · C · 430 lines · 249 code · 106 blank · 75 comment · 25 complexity · 2835e7f54b7ddf52e7b85d7a451731d5 MD5 · raw file
- /***************************************************************************/
- /* */
- /* ftccmap.c */
- /* */
- /* FreeType CharMap cache (body) */
- /* */
- /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
- /* 2010 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_FREETYPE_H
- #include FT_CACHE_H
- #include "ftcmanag.h"
- #include FT_INTERNAL_MEMORY_H
- #include FT_INTERNAL_DEBUG_H
- #include "ftccback.h"
- #include "ftcerror.h"
- #undef FT_COMPONENT
- #define FT_COMPONENT trace_cache
- #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
- typedef enum FTC_OldCMapType_
- {
- FTC_OLD_CMAP_BY_INDEX = 0,
- FTC_OLD_CMAP_BY_ENCODING = 1,
- FTC_OLD_CMAP_BY_ID = 2
- } FTC_OldCMapType;
- typedef struct FTC_OldCMapIdRec_
- {
- FT_UInt platform;
- FT_UInt encoding;
- } FTC_OldCMapIdRec, *FTC_OldCMapId;
- typedef struct FTC_OldCMapDescRec_
- {
- FTC_FaceID face_id;
- FTC_OldCMapType type;
- union
- {
- FT_UInt index;
- FT_Encoding encoding;
- FTC_OldCMapIdRec id;
- } u;
- } FTC_OldCMapDescRec, *FTC_OldCMapDesc;
- #endif /* FT_CONFIG_OLD_INTERNALS */
- /*************************************************************************/
- /* */
- /* Each FTC_CMapNode contains a simple array to map a range of character */
- /* codes to equivalent glyph indices. */
- /* */
- /* For now, the implementation is very basic: Each node maps a range of */
- /* 128 consecutive character codes to their corresponding glyph indices. */
- /* */
- /* We could do more complex things, but I don't think it is really very */
- /* useful. */
- /* */
- /*************************************************************************/
- /* number of glyph indices / character code per node */
- #define FTC_CMAP_INDICES_MAX 128
- /* compute a query/node hash */
- #define FTC_CMAP_HASH( faceid, index, charcode ) \
- ( FTC_FACE_ID_HASH( faceid ) + 211 * (index) + \
- ( (charcode) / FTC_CMAP_INDICES_MAX ) )
- /* the charmap query */
- typedef struct FTC_CMapQueryRec_
- {
- FTC_FaceID face_id;
- FT_UInt cmap_index;
- FT_UInt32 char_code;
- } FTC_CMapQueryRec, *FTC_CMapQuery;
- #define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
- #define FTC_CMAP_QUERY_HASH( x ) \
- FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
- /* the cmap cache node */
- typedef struct FTC_CMapNodeRec_
- {
- FTC_NodeRec node;
- FTC_FaceID face_id;
- FT_UInt cmap_index;
- FT_UInt32 first; /* first character in node */
- FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
- } FTC_CMapNodeRec, *FTC_CMapNode;
- #define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
- #define FTC_CMAP_NODE_HASH( x ) \
- FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
- /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
- /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
- #define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHARMAP NODES *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- FT_CALLBACK_DEF( void )
- ftc_cmap_node_free( FTC_Node ftcnode,
- FTC_Cache cache )
- {
- FTC_CMapNode node = (FTC_CMapNode)ftcnode;
- FT_Memory memory = cache->memory;
- FT_FREE( node );
- }
- /* initialize a new cmap node */
- FT_CALLBACK_DEF( FT_Error )
- ftc_cmap_node_new( FTC_Node *ftcanode,
- FT_Pointer ftcquery,
- FTC_Cache cache )
- {
- FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;
- FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
- FT_Error error;
- FT_Memory memory = cache->memory;
- FTC_CMapNode node = NULL;
- FT_UInt nn;
- if ( !FT_NEW( node ) )
- {
- node->face_id = query->face_id;
- node->cmap_index = query->cmap_index;
- node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
- FTC_CMAP_INDICES_MAX;
- for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
- node->indices[nn] = FTC_CMAP_UNKNOWN;
- }
- *anode = node;
- return error;
- }
- /* compute the weight of a given cmap node */
- FT_CALLBACK_DEF( FT_Offset )
- ftc_cmap_node_weight( FTC_Node cnode,
- FTC_Cache cache )
- {
- FT_UNUSED( cnode );
- FT_UNUSED( cache );
- return sizeof ( *cnode );
- }
- /* compare a cmap node to a given query */
- FT_CALLBACK_DEF( FT_Bool )
- ftc_cmap_node_compare( FTC_Node ftcnode,
- FT_Pointer ftcquery,
- FTC_Cache cache )
- {
- FTC_CMapNode node = (FTC_CMapNode)ftcnode;
- FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
- FT_UNUSED( cache );
- if ( node->face_id == query->face_id &&
- node->cmap_index == query->cmap_index )
- {
- FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
- return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
- }
- return 0;
- }
- FT_CALLBACK_DEF( FT_Bool )
- ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
- FT_Pointer ftcface_id,
- FTC_Cache cache )
- {
- FTC_CMapNode node = (FTC_CMapNode)ftcnode;
- FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
- FT_UNUSED( cache );
- return FT_BOOL( node->face_id == face_id );
- }
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** GLYPH IMAGE CACHE *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- FT_CALLBACK_TABLE_DEF
- const FTC_CacheClassRec ftc_cmap_cache_class =
- {
- ftc_cmap_node_new,
- ftc_cmap_node_weight,
- ftc_cmap_node_compare,
- ftc_cmap_node_remove_faceid,
- ftc_cmap_node_free,
- sizeof ( FTC_CacheRec ),
- ftc_cache_init,
- ftc_cache_done,
- };
- /* documentation is in ftcache.h */
- FT_EXPORT_DEF( FT_Error )
- FTC_CMapCache_New( FTC_Manager manager,
- FTC_CMapCache *acache )
- {
- return FTC_Manager_RegisterCache( manager,
- &ftc_cmap_cache_class,
- FTC_CACHE_P( acache ) );
- }
- #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
- /*
- * Unfortunately, it is not possible to support binary backwards
- * compatibility in the cmap cache. The FTC_CMapCache_Lookup signature
- * changes were too deep, and there is no clever hackish way to detect
- * what kind of structure we are being passed.
- *
- * On the other hand it seems that no production code is using this
- * function on Unix distributions.
- */
- #endif
- /* documentation is in ftcache.h */
- FT_EXPORT_DEF( FT_UInt )
- FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
- FTC_FaceID face_id,
- FT_Int cmap_index,
- FT_UInt32 char_code )
- {
- FTC_Cache cache = FTC_CACHE( cmap_cache );
- FTC_CMapQueryRec query;
- FTC_Node node;
- FT_Error error;
- FT_UInt gindex = 0;
- FT_UInt32 hash;
- FT_Int no_cmap_change = 0;
- if ( cmap_index < 0 )
- {
- /* Treat a negative cmap index as a special value, meaning that you */
- /* don't want to change the FT_Face's character map through this */
- /* call. This can be useful if the face requester callback already */
- /* sets the face's charmap to the appropriate value. */
- no_cmap_change = 1;
- cmap_index = 0;
- }
- if ( !cache )
- {
- FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));
- return 0;
- }
- #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
- /*
- * If cmap_index is greater than the maximum number of cachable
- * charmaps, we assume the request is from a legacy rogue client
- * using old internal header. See include/config/ftoption.h.
- */
- if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE && !no_cmap_change )
- {
- FTC_OldCMapDesc desc = (FTC_OldCMapDesc) face_id;
- char_code = (FT_UInt32)cmap_index;
- query.face_id = desc->face_id;
- switch ( desc->type )
- {
- case FTC_OLD_CMAP_BY_INDEX:
- query.cmap_index = desc->u.index;
- query.char_code = (FT_UInt32)cmap_index;
- break;
- case FTC_OLD_CMAP_BY_ENCODING:
- {
- FT_Face face;
- error = FTC_Manager_LookupFace( cache->manager, desc->face_id,
- &face );
- if ( error )
- return 0;
- FT_Select_Charmap( face, desc->u.encoding );
- return FT_Get_Char_Index( face, char_code );
- }
- default:
- return 0;
- }
- }
- else
- #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
- {
- query.face_id = face_id;
- query.cmap_index = (FT_UInt)cmap_index;
- query.char_code = char_code;
- }
- hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
- #if 1
- FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
- node, error );
- #else
- error = FTC_Cache_Lookup( cache, hash, &query, &node );
- #endif
- if ( error )
- goto Exit;
- FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <
- FTC_CMAP_INDICES_MAX );
- /* something rotten can happen with rogue clients */
- if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
- FTC_CMAP_INDICES_MAX ) )
- return 0; /* XXX: should return appropriate error */
- gindex = FTC_CMAP_NODE( node )->indices[char_code -
- FTC_CMAP_NODE( node )->first];
- if ( gindex == FTC_CMAP_UNKNOWN )
- {
- FT_Face face;
- gindex = 0;
- error = FTC_Manager_LookupFace( cache->manager,
- FTC_CMAP_NODE( node )->face_id,
- &face );
- if ( error )
- goto Exit;
- #ifdef FT_MAX_CHARMAP_CACHEABLE
- /* something rotten can happen with rogue clients */
- if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
- return 0; /* XXX: should return appropriate error */
- #endif
- if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
- {
- FT_CharMap old, cmap = NULL;
- old = face->charmap;
- cmap = face->charmaps[cmap_index];
- if ( old != cmap && !no_cmap_change )
- FT_Set_Charmap( face, cmap );
- gindex = FT_Get_Char_Index( face, char_code );
- if ( old != cmap && !no_cmap_change )
- FT_Set_Charmap( face, old );
- }
- FTC_CMAP_NODE( node )->indices[char_code -
- FTC_CMAP_NODE( node )->first]
- = (FT_UShort)gindex;
- }
- Exit:
- return gindex;
- }
- /* END */