123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- /***************************************************************************/
- /* */
- /* ftccmap.c */
- /* */
- /* FreeType CharMap cache (body) */
- /* */
- /* Copyright 2000-2001, 2002 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 FT_CACHE_CHARMAP_H
- #include FT_CACHE_MANAGER_H
- #include FT_INTERNAL_MEMORY_H
- #include FT_INTERNAL_DEBUG_H
- #include "ftcerror.h"
- /*************************************************************************/
- /* */
- /* 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
- typedef struct FTC_CMapNodeRec_
- {
- FTC_NodeRec node;
- 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 ) )
- /* compute node hash value from cmap family and "requested" glyph index */
- #define FTC_CMAP_HASH( cfam, cquery ) \
- ( (cfam)->hash + ( (cquery)->char_code / FTC_CMAP_INDICES_MAX ) )
- /* 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 )
- /* the charmap query */
- typedef struct FTC_CMapQueryRec_
- {
- FTC_QueryRec query;
- FTC_CMapDesc desc;
- FT_UInt32 char_code;
- } FTC_CMapQueryRec, *FTC_CMapQuery;
- #define FTC_CMAP_QUERY( x ) ( (FTC_CMapQuery)( x ) )
- /* the charmap family */
- typedef struct FTC_CMapFamilyRec_
- {
- FTC_FamilyRec family;
- FT_UInt32 hash;
- FTC_CMapDescRec desc;
- FT_UInt index;
- } FTC_CMapFamilyRec, *FTC_CMapFamily;
- #define FTC_CMAP_FAMILY( x ) ( (FTC_CMapFamily)( x ) )
- #define FTC_CMAP_FAMILY_MEMORY( x ) FTC_FAMILY( x )->memory
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHARMAP NODES *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- /* no need for specific finalizer; we use "ftc_node_done" directly */
- /* initialize a new cmap node */
- FT_CALLBACK_DEF( FT_Error )
- ftc_cmap_node_init( FTC_CMapNode cnode,
- FTC_CMapQuery cquery,
- FTC_Cache cache )
- {
- FT_UInt32 first;
- FT_UInt n;
- FT_UNUSED( cache );
- first = ( cquery->char_code / FTC_CMAP_INDICES_MAX ) *
- FTC_CMAP_INDICES_MAX;
- cnode->first = first;
- for ( n = 0; n < FTC_CMAP_INDICES_MAX; n++ )
- cnode->indices[n] = FTC_CMAP_UNKNOWN;
- return 0;
- }
- /* compute the weight of a given cmap node */
- FT_CALLBACK_DEF( FT_ULong )
- ftc_cmap_node_weight( FTC_CMapNode cnode )
- {
- FT_UNUSED( cnode );
-
- return sizeof ( *cnode );
- }
- /* compare a cmap node to a given query */
- FT_CALLBACK_DEF( FT_Bool )
- ftc_cmap_node_compare( FTC_CMapNode cnode,
- FTC_CMapQuery cquery )
- {
- FT_UInt32 offset = (FT_UInt32)( cquery->char_code - cnode->first );
- return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
- }
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHARMAP FAMILY *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- FT_CALLBACK_DEF( FT_Error )
- ftc_cmap_family_init( FTC_CMapFamily cfam,
- FTC_CMapQuery cquery,
- FTC_Cache cache )
- {
- FTC_Manager manager = cache->manager;
- FTC_CMapDesc desc = cquery->desc;
- FT_UInt32 hash = 0;
- FT_Error error;
- FT_Face face;
- /* setup charmap descriptor */
- cfam->desc = *desc;
- /* let's see whether the rest is correct too */
- error = FTC_Manager_Lookup_Face( manager, desc->face_id, &face );
- if ( !error )
- {
- FT_UInt count = face->num_charmaps;
- FT_UInt idx = count;
- FT_CharMap* cur = face->charmaps;
- switch ( desc->type )
- {
- case FTC_CMAP_BY_INDEX:
- idx = desc->u.index;
- hash = idx * 33;
- break;
- case FTC_CMAP_BY_ENCODING:
- for ( idx = 0; idx < count; idx++, cur++ )
- if ( cur[0]->encoding == desc->u.encoding )
- break;
- hash = idx * 67;
- break;
- case FTC_CMAP_BY_ID:
- for ( idx = 0; idx < count; idx++, cur++ )
- {
- if ( (FT_UInt)cur[0]->platform_id == desc->u.id.platform &&
- (FT_UInt)cur[0]->encoding_id == desc->u.id.encoding )
- {
- hash = ( ( desc->u.id.platform << 8 ) | desc->u.id.encoding ) * 7;
- break;
- }
- }
- break;
- default:
- ;
- }
- if ( idx >= count )
- goto Bad_Descriptor;
- /* compute hash value, both in family and query */
- cfam->index = idx;
- cfam->hash = hash ^ FTC_FACE_ID_HASH( desc->face_id );
- FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
- error = ftc_family_init( FTC_FAMILY( cfam ),
- FTC_QUERY( cquery ), cache );
- }
- return error;
- Bad_Descriptor:
- FT_ERROR(( "ftp_cmap_family_init: invalid charmap descriptor\n" ));
- return FTC_Err_Invalid_Argument;
- }
- FT_CALLBACK_DEF( FT_Bool )
- ftc_cmap_family_compare( FTC_CMapFamily cfam,
- FTC_CMapQuery cquery )
- {
- FT_Int result = 0;
- /* first, compare face id and type */
- if ( cfam->desc.face_id != cquery->desc->face_id ||
- cfam->desc.type != cquery->desc->type )
- goto Exit;
- switch ( cfam->desc.type )
- {
- case FTC_CMAP_BY_INDEX:
- result = ( cfam->desc.u.index == cquery->desc->u.index );
- break;
- case FTC_CMAP_BY_ENCODING:
- result = ( cfam->desc.u.encoding == cquery->desc->u.encoding );
- break;
- case FTC_CMAP_BY_ID:
- result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform &&
- cfam->desc.u.id.encoding == cquery->desc->u.id.encoding );
- break;
- default:
- ;
- }
- if ( result )
- {
- /* when found, update the 'family' and 'hash' field of the query */
- FTC_QUERY( cquery )->family = FTC_FAMILY( cfam );
- FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
- }
- Exit:
- return FT_BOOL( result );
- }
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** GLYPH IMAGE CACHE *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- FT_CALLBACK_TABLE_DEF
- const FTC_Cache_ClassRec ftc_cmap_cache_class =
- {
- sizeof ( FTC_CacheRec ),
- (FTC_Cache_InitFunc) ftc_cache_init,
- (FTC_Cache_ClearFunc)ftc_cache_clear,
- (FTC_Cache_DoneFunc) ftc_cache_done,
- sizeof ( FTC_CMapFamilyRec ),
- (FTC_Family_InitFunc) ftc_cmap_family_init,
- (FTC_Family_CompareFunc)ftc_cmap_family_compare,
- (FTC_Family_DoneFunc) ftc_family_done,
- sizeof ( FTC_CMapNodeRec ),
- (FTC_Node_InitFunc) ftc_cmap_node_init,
- (FTC_Node_WeightFunc) ftc_cmap_node_weight,
- (FTC_Node_CompareFunc)ftc_cmap_node_compare,
- (FTC_Node_DoneFunc) ftc_node_done
- };
- /* documentation is in ftccmap.h */
- FT_EXPORT_DEF( FT_Error )
- FTC_CMapCache_New( FTC_Manager manager,
- FTC_CMapCache *acache )
- {
- return FTC_Manager_Register_Cache(
- manager,
- (FTC_Cache_Class)&ftc_cmap_cache_class,
- FTC_CACHE_P( acache ) );
- }
- #ifdef FTC_CACHE_USE_INLINE
- #define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
- ftc_cmap_family_compare( (FTC_CMapFamily)(f), (FTC_CMapQuery)(q) )
- #define GEN_CACHE_NODE_COMPARE( n, q, c ) \
- ftc_cmap_node_compare( (FTC_CMapNode)(n), (FTC_CMapQuery)(q) )
- #define GEN_CACHE_LOOKUP ftc_cmap_cache_lookup
- #include "ftccache.i"
- #else /* !FTC_CACHE_USE_INLINE */
- #define ftc_cmap_cache_lookup ftc_cache_lookup
- #endif /* !FTC_CACHE_USE_INLINE */
- /* documentation is in ftccmap.h */
- FT_EXPORT_DEF( FT_UInt )
- FTC_CMapCache_Lookup( FTC_CMapCache cache,
- FTC_CMapDesc desc,
- FT_UInt32 char_code )
- {
- FTC_CMapQueryRec cquery;
- FTC_CMapNode node;
- FT_Error error;
- FT_UInt gindex = 0;
- if ( !cache || !desc )
- {
- FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
- return 0;
- }
- cquery.desc = desc;
- cquery.char_code = char_code;
- error = ftc_cmap_cache_lookup( FTC_CACHE( cache ),
- FTC_QUERY( &cquery ),
- (FTC_Node*)&node );
- if ( !error )
- {
- FT_UInt offset = (FT_UInt)( char_code - node->first );
- FT_ASSERT( offset < FTC_CMAP_INDICES_MAX );
- gindex = node->indices[offset];
- if ( gindex == FTC_CMAP_UNKNOWN )
- {
- FT_Face face;
- /* we need to use FT_Get_Char_Index */
- gindex = 0;
- error = FTC_Manager_Lookup_Face( FTC_CACHE(cache)->manager,
- desc->face_id,
- &face );
- if ( !error )
- {
- FT_CharMap old, cmap = NULL;
- FT_UInt cmap_index;
- /* save old charmap, select new one */
- old = face->charmap;
- cmap_index = FTC_CMAP_FAMILY( FTC_QUERY( &cquery )->family )->index;
- cmap = face->charmaps[cmap_index];
- FT_Set_Charmap( face, cmap );
- /* perform lookup */
- gindex = FT_Get_Char_Index( face, char_code );
- node->indices[offset] = (FT_UInt16)gindex;
- /* restore old charmap */
- FT_Set_Charmap( face, old );
- }
- }
- }
- return gindex;
- }
- /* END */
|