📄 ftcmanag.c
字号:
entry->index = idx; } entry->link = FTC_FAMILY_ENTRY_NONE; entry->index = idx; } if ( table->free != FTC_FAMILY_ENTRY_NONE ) { entry = table->entries + table->free; table->free = entry->link; } else if ( table->count < table->size ) { entry = table->entries + table->count++; } else { FT_ERROR(( "ftc_family_table_alloc: internal bug!" )); return FTC_Err_Invalid_Argument; } entry->link = FTC_FAMILY_ENTRY_NONE; table->count++; *aentry = entry; return error; } FT_EXPORT_DEF( void ) ftc_family_table_free( FTC_FamilyTable table, FT_UInt idx ) { /* simply add it to the linked list of free entries */ if ( idx < table->count ) { FTC_FamilyEntry entry = table->entries + idx; if ( entry->link != FTC_FAMILY_ENTRY_NONE ) FT_ERROR(( "ftc_family_table_free: internal bug!\n" )); else { entry->link = table->free; table->free = entry->index; table->count--; } } } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** CACHE MANAGER ROUTINES *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* documentation is in ftcache.h */ FT_EXPORT_DEF( FT_Error ) FTC_Manager_New( FT_Library library, FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes, FTC_Face_Requester requester, FT_Pointer req_data, FTC_Manager *amanager ) { FT_Error error; FT_Memory memory; FTC_Manager manager = 0; if ( !library ) return FTC_Err_Invalid_Library_Handle; memory = library->memory; if ( FT_NEW( manager ) ) goto Exit; if ( max_faces == 0 ) max_faces = FTC_MAX_FACES_DEFAULT; if ( max_sizes == 0 ) max_sizes = FTC_MAX_SIZES_DEFAULT; if ( max_bytes == 0 ) max_bytes = FTC_MAX_BYTES_DEFAULT; error = FT_LruList_New( &ftc_face_list_class, max_faces, manager, memory, &manager->faces_list ); if ( error ) goto Exit; error = FT_LruList_New( &ftc_size_list_class, max_sizes, manager, memory, &manager->sizes_list ); if ( error ) goto Exit; manager->library = library; manager->max_weight = max_bytes; manager->cur_weight = 0; manager->request_face = requester; manager->request_data = req_data; ftc_family_table_init( &manager->families ); *amanager = manager; Exit: if ( error && manager ) { FT_LruList_Destroy( manager->faces_list ); FT_LruList_Destroy( manager->sizes_list ); FT_FREE( manager ); } return error; } /* documentation is in ftcache.h */ FT_EXPORT_DEF( void ) FTC_Manager_Done( FTC_Manager manager ) { FT_Memory memory; FT_UInt idx; if ( !manager || !manager->library ) return; memory = manager->library->memory; /* now discard all caches */ for (idx = 0; idx < FTC_MAX_CACHES; idx++ ) { FTC_Cache cache = manager->caches[idx]; if ( cache ) { cache->clazz->cache_done( cache ); FT_FREE( cache ); manager->caches[idx] = 0; } } /* discard families table */ ftc_family_table_done( &manager->families, memory ); /* discard faces and sizes */ FT_LruList_Destroy( manager->faces_list ); manager->faces_list = 0; FT_LruList_Destroy( manager->sizes_list ); manager->sizes_list = 0; FT_FREE( manager ); } /* documentation is in ftcache.h */ FT_EXPORT_DEF( void ) FTC_Manager_Reset( FTC_Manager manager ) { if ( manager ) { FT_LruList_Reset( manager->sizes_list ); FT_LruList_Reset( manager->faces_list ); } /* XXX: FIXME: flush the caches? */ }#ifdef FT_DEBUG_ERROR FT_EXPORT_DEF( void ) FTC_Manager_Check( FTC_Manager manager ) { FTC_Node node, first; first = manager->nodes_list; /* check node weights */ if ( first ) { FT_ULong weight = 0; node = first; do { FTC_FamilyEntry entry = manager->families.entries + node->fam_index; FTC_Cache cache; if ( (FT_UInt)node->fam_index >= manager->families.count || entry->link != FTC_FAMILY_ENTRY_NONE ) FT_ERROR(( "FTC_Manager_Check: invalid node (family index = %ld\n", node->fam_index )); else { cache = entry->cache; weight += cache->clazz->node_weight( node, cache ); } node = node->mru_next; } while ( node != first ); if ( weight != manager->cur_weight ) FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n", manager->cur_weight, weight )); } /* check circular list */ if ( first ) { FT_UFast count = 0; node = first; do { count++; node = node->mru_next; } while ( node != first ); if ( count != manager->num_nodes ) FT_ERROR(( "FTC_Manager_Check: invalid cache node count %d instead of %d\n", manager->num_nodes, count )); } }#endif /* FT_DEBUG_ERROR */ /* `Compress' the manager's data, i.e., get rid of old cache nodes */ /* that are not referenced anymore in order to limit the total */ /* memory used by the cache. */ /* documentation is in ftcmanag.h */ FT_EXPORT_DEF( void ) FTC_Manager_Compress( FTC_Manager manager ) { FTC_Node node, first; if ( !manager ) return; first = manager->nodes_list;#ifdef FT_DEBUG_ERROR FTC_Manager_Check( manager ); FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n", manager->cur_weight, manager->max_weight, manager->num_nodes ));#endif if ( manager->cur_weight < manager->max_weight || first == NULL ) return; /* go to last node - it's a circular list */ node = first->mru_prev; do { FTC_Node prev = node->mru_prev; prev = ( node == first ) ? NULL : node->mru_prev; if ( node->ref_count <= 0 ) ftc_node_destroy( node, manager ); node = prev; } while ( node && manager->cur_weight > manager->max_weight ); } /* documentation is in ftcmanag.h */ FT_EXPORT_DEF( FT_Error ) FTC_Manager_Register_Cache( FTC_Manager manager, FTC_Cache_Class clazz, FTC_Cache *acache ) { FT_Error error = FTC_Err_Invalid_Argument; FTC_Cache cache = NULL; if ( manager && clazz && acache ) { FT_Memory memory = manager->library->memory; FT_UInt idx = 0; /* check for an empty cache slot in the manager's table */ for ( idx = 0; idx < FTC_MAX_CACHES; idx++ ) { if ( manager->caches[idx] == 0 ) break; } /* return an error if there are too many registered caches */ if ( idx >= FTC_MAX_CACHES ) { error = FTC_Err_Too_Many_Caches; FT_ERROR(( "FTC_Manager_Register_Cache:" )); FT_ERROR(( " too many registered caches\n" )); goto Exit; } if ( !FT_ALLOC( cache, clazz->cache_size ) ) { cache->manager = manager; cache->memory = memory; cache->clazz = clazz; /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */ /* IF IT IS NOT SET CORRECTLY */ cache->cache_index = idx; if ( clazz->cache_init ) { error = clazz->cache_init( cache ); if ( error ) { if ( clazz->cache_done ) clazz->cache_done( cache ); FT_FREE( cache ); goto Exit; } } manager->caches[idx] = cache; } } Exit: *acache = cache; return error; } /* documentation is in ftcmanag.h */ FT_EXPORT_DEF( void ) FTC_Node_Unref( FTC_Node node, FTC_Manager manager ) { if ( node && (FT_UInt)node->fam_index < manager->families.count && manager->families.entries[node->fam_index].cache ) { node->ref_count--; } }/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -