+++ /dev/null
-/***************************************************************************/
-/* */
-/* ftcchunk.c */
-/* */
-/* FreeType chunk cache cache (body). */
-/* */
-/* Copyright 2000-2001 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 FT_CACHE_INTERNAL_CHUNK_H
-#include FT_LIST_H
-#include FT_ERRORS_H
-#include FT_INTERNAL_OBJECTS_H
-
-#include "ftcerror.h"
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** GLYPH NODES *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /* create a new chunk node, setting its cache index and ref count */
- FT_EXPORT_DEF( FT_Error )
- FTC_ChunkNode_Init( FTC_ChunkNode node,
- FTC_ChunkSet cset,
- FT_UInt index,
- FT_Bool alloc )
- {
- FTC_Chunk_Cache cache = cset->cache;
- FTC_CacheNode_Data* data = FTC_CACHENODE_TO_DATA_P( &node->root );
- FT_Error error = 0;
-
-
- data->cache_index = (FT_UShort)cache->root.cache_index;
- data->ref_count = (FT_Short) 0;
- node->cset = cset;
- node->cset_index = (FT_UShort)index;
- node->num_elements = (unsigned short)(
- ( index + 1 < cset->num_chunks )
- ? cset->element_count
- : cset->element_max - cset->element_count*index );
- if ( alloc )
- {
- /* allocate elements array */
- FT_Memory memory;
-
-
- memory = cache->root.memory;
- error = MEM_Alloc( node->elements,
- cset->element_size * cset->element_count );
- }
-
- return error;
- }
-
-
- FT_EXPORT_DEF( void )
- FTC_ChunkNode_Destroy( FTC_ChunkNode node )
- {
- FTC_ChunkSet cset = node->cset;
-
-
- /* remove from parent set table */
- cset->chunks[node->cset_index] = 0;
-
- /* destroy the node */
- cset->clazz->destroy_node( node );
- }
-
-
- FT_EXPORT_DEF( FT_ULong )
- FTC_ChunkNode_Size( FTC_ChunkNode node )
- {
- FTC_ChunkSet cset = node->cset;
-
-
- return cset->clazz->size_node( node );
- }
-
-
- FT_CALLBACK_TABLE_DEF
- const FTC_CacheNode_Class ftc_chunk_cache_node_class =
- {
- (FTC_CacheNode_SizeFunc) FTC_ChunkNode_Size,
- (FTC_CacheNode_DestroyFunc)FTC_ChunkNode_Destroy
- };
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHUNK SETS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- FT_EXPORT_DEF( FT_Error )
- FTC_ChunkSet_New( FTC_Chunk_Cache cache,
- FT_Pointer type,
- FTC_ChunkSet *aset )
- {
- FT_Error error;
- FT_Memory memory = cache->root.memory;
- FTC_Manager manager = cache->root.manager;
- FTC_ChunkSet cset = 0;
-
- FTC_Chunk_Cache_Class* ccache_class;
- FTC_ChunkSet_Class* clazz;
-
-
- ccache_class = (FTC_Chunk_Cache_Class*)cache->root.clazz;
- clazz = ccache_class->cset_class;
-
- *aset = 0;
-
- if ( ALLOC( cset, clazz->cset_byte_size ) )
- goto Exit;
-
- cset->cache = cache;
- cset->manager = manager;
- cset->memory = memory;
- cset->clazz = clazz;
-
- /* now compute element_max, element_count and element_size */
- error = clazz->sizes( cset, type );
- if ( error )
- goto Exit;
-
- /* compute maximum number of nodes */
- cset->num_chunks = ( cset->element_max + cset->element_count - 1 ) /
- cset->element_count;
-
- /* allocate chunk pointers table */
- if ( ALLOC_ARRAY( cset->chunks, cset->num_chunks, FTC_ChunkNode ) )
- goto Exit;
-
- /* initialize set by type if needed */
- if ( clazz->init )
- {
- error = clazz->init( cset, type );
- if ( error )
- goto Exit;
- }
-
- *aset = cset;
-
- Exit:
- if ( error && cset )
- {
- FREE( cset->chunks );
- FREE( cset );
- }
-
- return error;
- }
-
-
- FT_EXPORT_DEF( void )
- FTC_ChunkSet_Destroy( FTC_ChunkSet cset )
- {
- FTC_Chunk_Cache cache = cset->cache;
- FTC_Manager manager = cache->root.manager;
- FT_List glyphs_lru = &manager->global_lru;
- FTC_ChunkNode* bucket = cset->chunks;
- FTC_ChunkNode* bucket_limit = bucket + cset->num_chunks;
- FT_Memory memory = cache->root.memory;
-
- FTC_ChunkSet_Class* clazz = cset->clazz;
-
-
- /* for each bucket, free the list of glyph nodes */
- for ( ; bucket < bucket_limit; bucket++ )
- {
- FTC_ChunkNode node = bucket[0];
- FT_ListNode lrunode;
-
-
- if ( node )
- {
- lrunode = FTC_CHUNKNODE_TO_LRUNODE( node );
-
- manager->num_bytes -= clazz->size_node( node );
- manager->num_nodes--;
-
- FT_List_Remove( glyphs_lru, lrunode );
-
- clazz->destroy_node( node );
-
- bucket[0] = 0;
- }
- }
-
- if ( clazz->done )
- clazz->done( cset );
-
- FREE( cset->chunks );
- FREE( cset );
- }
-
-
- FT_EXPORT_DEF( FT_Error )
- FTC_ChunkSet_Lookup_Node( FTC_ChunkSet cset,
- FT_UInt glyph_index,
- FTC_ChunkNode *anode,
- FT_UInt *anindex )
- {
- FTC_Chunk_Cache cache = cset->cache;
- FTC_Manager manager = cache->root.manager;
- FT_Error error = 0;
-
- FTC_ChunkSet_Class* clazz = cset->clazz;
-
-
- *anode = 0;
-
- if ( glyph_index >= cset->element_max )
- error = FTC_Err_Invalid_Argument;
- else
- {
- FT_UInt chunk_size = cset->element_count;
- FT_UInt chunk_index = glyph_index / chunk_size;
- FTC_ChunkNode* pnode = cset->chunks + chunk_index;
- FTC_ChunkNode node = *pnode;
-
-
- if ( !node )
- {
- /* we didn't found the glyph image; we will now create a new one */
- error = clazz->new_node( cset, chunk_index, &node );
- if ( error )
- goto Exit;
-
- /* store the new chunk in the cset's table */
- *pnode = node;
-
- /* insert the node at the start the global LRU glyph list */
- FT_List_Insert( &manager->global_lru,
- FTC_CHUNKNODE_TO_LRUNODE( node ) );
-
- manager->num_bytes += clazz->size_node( node );
- manager->num_nodes++;
-
- if ( manager->num_bytes > manager->max_bytes )
- {
- FTC_ChunkNode_Ref ( node );
- FTC_Manager_Compress( manager );
- FTC_ChunkNode_Unref ( node );
- }
- }
-
- *anode = node;
- *anindex = glyph_index - chunk_index * chunk_size;
- }
-
- Exit:
- return error;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHUNK SETS LRU CALLBACKS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
-#define FTC_CSET_LRU_GET_CACHE( lru ) \
- ( (FTC_Chunk_Cache)((lru)->user_data) )
-
-#define FTC_CSET_LRU_GET_MANAGER( lru ) \
- FTC_CSET_LRU_GET_CACHE( lru )->manager
-
-#define FTC_LRUNODE_CSET( node ) \
- ( (FTC_ChunkSet)(node)->root.data )
-
-
- FT_CALLBACK_DEF( FT_Error )
- ftc_chunk_set_lru_init( FT_Lru lru,
- FT_LruNode node )
- {
- FTC_Chunk_Cache cache = FTC_CSET_LRU_GET_CACHE( lru );
- FT_Error error;
- FTC_ChunkSet cset;
-
-
- error = FTC_ChunkSet_New( cache,
- (FT_Pointer)node->key,
- &cset );
- if ( !error )
- {
- /* good, now set the set index within the set object */
- cset->cset_index = (FT_UInt)( node - lru->nodes );
- node->root.data = cset;
- }
-
- return error;
- }
-
-
- FT_CALLBACK_DEF( void )
- ftc_chunk_set_lru_done( FT_Lru lru,
- FT_LruNode node )
- {
- FTC_ChunkSet cset = FTC_LRUNODE_CSET( node );
-
- FT_UNUSED( lru );
-
-
- FTC_ChunkSet_Destroy( cset );
- }
-
-
- FT_CALLBACK_DEF( FT_Bool )
- ftc_chunk_set_lru_compare( FT_LruNode node,
- FT_LruKey key )
- {
- FTC_ChunkSet cset = FTC_LRUNODE_CSET( node );
-
-
- return cset->clazz->compare( cset, (FT_Pointer)key );
- }
-
-
- FT_CALLBACK_TABLE_DEF
- const FT_Lru_Class ftc_chunk_set_lru_class =
- {
- sizeof( FT_LruRec ),
- ftc_chunk_set_lru_init,
- ftc_chunk_set_lru_done,
- 0, /* no flush */
- ftc_chunk_set_lru_compare
- };
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** CHUNK CACHE OBJECTS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- FT_EXPORT_DEF( FT_Error )
- FTC_Chunk_Cache_Init( FTC_Chunk_Cache cache )
- {
- FT_Memory memory = cache->root.memory;
- FT_Error error;
-
- FTC_Chunk_Cache_Class* ccache_clazz;
-
-
- /* set up root node_class to be used by manager */
- cache->root.node_clazz =
- (FTC_CacheNode_Class*)&ftc_chunk_cache_node_class;
-
- /* setup `compare' shortcut */
- ccache_clazz = (FTC_Chunk_Cache_Class*)cache->root.clazz;
- cache->compare = ccache_clazz->cset_class->compare;
-
- error = FT_Lru_New( &ftc_chunk_set_lru_class,
- FTC_MAX_CHUNK_SETS,
- cache,
- memory,
- 1, /* pre_alloc == TRUE */
- &cache->csets_lru );
- return error;
- }
-
-
- FT_EXPORT_DEF( void )
- FTC_Chunk_Cache_Done( FTC_Chunk_Cache cache )
- {
- /* discard glyph sets */
- FT_Lru_Done( cache->csets_lru );
- }
-
-
- FT_EXPORT_DEF( FT_Error )
- FTC_Chunk_Cache_Lookup( FTC_Chunk_Cache cache,
- FT_Pointer type,
- FT_UInt gindex,
- FTC_ChunkNode *anode,
- FT_UInt *aindex )
- {
- FT_Error error;
- FTC_ChunkSet cset;
- FTC_ChunkNode node;
- FT_UInt cindex;
- FTC_Manager manager;
-
-
- /* check for valid `desc' delayed to FT_Lru_Lookup() */
-
- if ( !cache || !anode || !aindex )
- return FTC_Err_Invalid_Argument;
-
- *anode = 0;
- *aindex = 0;
- cset = cache->last_cset;
-
- if ( !cset || !cache->compare( cset, type ) )
- {
- error = FT_Lru_Lookup( cache->csets_lru,
- (FT_LruKey)type,
- (FT_Pointer*)&cset );
- cache->last_cset = cset;
- if ( error )
- goto Exit;
- }
-
- error = FTC_ChunkSet_Lookup_Node( cset, gindex, &node, &cindex );
- if ( error )
- goto Exit;
-
- /* now compress the manager's cache pool if needed */
- manager = cache->root.manager;
- if ( manager->num_bytes > manager->max_bytes )
- {
- FTC_ChunkNode_Ref ( node );
- FTC_Manager_Compress( manager );
- FTC_ChunkNode_Unref ( node );
- }
-
- *anode = node;
- *aindex = cindex;
-
- Exit:
- return error;
- }
-
-
-/* END */