- started implementin a "small-bitmaps" cache derived from it - (soon a "metrics" cache will be written too)VER-2-0-4-PATCH
parent
843997b2ca
commit
6b4a4610eb
9 changed files with 1236 additions and 227 deletions
@ -0,0 +1,208 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcchunk.h */ |
||||
/* */ |
||||
/* FreeType chunk cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Important: The functions defined in this file are only used to */ |
||||
/* implement an abstract chunk cache class. You need to */ |
||||
/* provide additional logic to implement a complete cache. */ |
||||
/* For example, see `ftcmetrx.h' and `ftcmetrx.c' which */ |
||||
/* implement a glyph metrics cache based on this code. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/********* *********/ |
||||
/********* WARNING, THIS IS ALPHA CODE, THIS API *********/ |
||||
/********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/ |
||||
/********* FREETYPE DEVELOPMENT TEAM *********/ |
||||
/********* *********/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#ifndef FTCCHUNK_H |
||||
#define FTCCHUNK_H |
||||
|
||||
#include <freetype/cache/ftcmanag.h> |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* maximum number of chunk sets in a given chunk cache */ |
||||
#define FTC_MAX_CHUNK_SETS 16 |
||||
|
||||
|
||||
typedef struct FTC_ChunkRec_* FTC_Chunk; |
||||
typedef struct FTC_ChunkSetRec_* FTC_ChunkSet; |
||||
typedef struct FTC_Chunk_CacheRec_* FTC_Chunk_Cache; |
||||
|
||||
typedef struct FTC_ChunkRec_ |
||||
{ |
||||
FTC_CacheNodeRec root; |
||||
FTC_ChunkSet cset; |
||||
FT_UShort cset_index; |
||||
FT_UShort num_elements; |
||||
FT_Byte* elements; |
||||
|
||||
} FTC_ChunkRec; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* chunk set methods */ |
||||
/* */ |
||||
|
||||
typedef FT_Error (*FTC_ChunkSet_InitFunc) ( FTC_ChunkSet cset, |
||||
FT_Pointer type ); |
||||
|
||||
|
||||
typedef void (*FTC_ChunkSet_DoneFunc) ( FTC_ChunkSet cset ); |
||||
|
||||
typedef FT_Bool (*FTC_ChunkSet_CompareFunc)( FTC_ChunkSet cset, |
||||
FT_Pointer type ); |
||||
|
||||
|
||||
|
||||
typedef FT_Error (*FTC_ChunkSet_NewNodeFunc)( FTC_ChunkSet cset, |
||||
FT_UInt index, |
||||
FTC_ChunkNode* anode ); |
||||
|
||||
typedef void (*FTC_ChunkSet_DestroyNodeFunc)( FTC_ChunkNode node ); |
||||
|
||||
typedef FT_ULong (*FTC_ChunkSet_SizeNodeFunc) ( FTC_ChunkNode node ); |
||||
|
||||
|
||||
typedef struct FTC_ChunkSet_Class_ |
||||
{ |
||||
FT_UInt cset_size; |
||||
|
||||
FTC_ChunkSet_InitFunc init; |
||||
FTC_ChunkSet_DoneFunc done; |
||||
FTC_ChunkSet_CompareFunc compare; |
||||
|
||||
FTC_ChunkSet_NewNodeFunc new_node; |
||||
FTC_ChunkSet_SizeNodeFunc size_node; |
||||
FTC_ChunkSet_DestroyNodeFunc destroy_node; |
||||
|
||||
} FTC_ChunkSet_Class; |
||||
|
||||
|
||||
typedef struct FTC_ChunkSetRec_ |
||||
{ |
||||
FTC_Chunk_Cache cache; |
||||
FTC_Manager manager; |
||||
FT_Memory memory; |
||||
FTC_ChunkSet_Class* clazz; |
||||
FT_UInt cset_index; /* index in parent cache */ |
||||
|
||||
FT_UInt element_max; /* maximum number of elements */ |
||||
FT_UInt element_size; /* element size in bytes */ |
||||
FT_UInt element_count; /* number of elements per chunk */ |
||||
FT_UInt num_chunks; |
||||
FTC_ChunkNode* chunks; |
||||
|
||||
} FTC_ChunkSetRec; |
||||
|
||||
|
||||
/* the abstract chunk cache class */ |
||||
typedef struct FTC_Chunk_Cache_Class_ |
||||
{ |
||||
FTC_Cache_Class root; |
||||
FTC_ChunkSet_Class* cset_class; |
||||
|
||||
} FTC_Chunk_Cache_Class; |
||||
|
||||
|
||||
/* the abstract chunk cache object */ |
||||
typedef struct FTC_Chunk_CacheRec_ |
||||
{ |
||||
FTC_CacheRec root; |
||||
FT_Lru csets_lru; /* static chunk set lru list */ |
||||
FTC_ChunkSet last_cset; /* small cache :-) */ |
||||
|
||||
} FTC_Chunk_CacheRec; |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* These functions are exported so that they can be called from */ |
||||
/* user-provided cache classes; otherwise, they are really parts of the */ |
||||
/* cache sub-system internals. */ |
||||
/* */ |
||||
|
||||
FT_EXPORT_FUNC( NV_Error ) |
||||
FTC_ChunkNode_Init( FTC_ChunkNode node, |
||||
FTC_ChunkSet cset, |
||||
FT_UInt index, |
||||
FT_Bool alloc ); |
||||
|
||||
#define FTC_ChunkNode_Ref( n ) \ |
||||
FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++ |
||||
|
||||
#define FTC_ChunkNode_Unref( n ) \ |
||||
FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count-- |
||||
|
||||
|
||||
FT_EXPORT_DEF( void ) |
||||
FTC_ChunkNode_Destroy( FTC_ChunkNode node ); |
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_Chunk_Cache_Init( FTC_Chunk_Cache cache ); |
||||
|
||||
|
||||
FT_EXPORT_DEF( void ) |
||||
FTC_Chunk_Cache_Done( FTC_Chunk_Cache cache ); |
||||
|
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_ChunkSet_New( FTC_Chunk_Cache cache, |
||||
FT_Pointer type, |
||||
FT_UInt num_elements, |
||||
FT_UInt element_size, |
||||
FT_UInt chunk_size, |
||||
FTC_ChunkSet *aset ) |
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_ChunkSet_Lookup_Node( FTC_ChunkSet cset, |
||||
FT_UInt glyph_index, |
||||
FTC_ChunkNode *anode, |
||||
FT_UInt *aindex ); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* FTCCHUNK_H */ |
||||
|
||||
/* END */ |
@ -0,0 +1,373 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcchunk.c */ |
||||
/* */ |
||||
/* FreeType chunk cache cache (body). */ |
||||
/* */ |
||||
/* Copyright 2000 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 <freetype/cache/ftcglyph.h> |
||||
#include <freetype/fterrors.h> |
||||
#include <freetype/internal/ftobjs.h> |
||||
#include <freetype/internal/ftlist.h> |
||||
#include <freetype/fterrors.h> |
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** GLYPH NODES *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
|
||||
/* create a new chunk node, setting its cache index and ref count */ |
||||
FT_EXPORT_FUNC( NV_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 ); |
||||
NV_Error error = 0; |
||||
|
||||
|
||||
data->cache_index = (FT_UShort) cache->root.cache_index; |
||||
data->ref_count = (FT_Short) 0; |
||||
node->cset_index = (FT_UShort) index; |
||||
|
||||
node->num_elements = (index+1 < cset->chunk_count) |
||||
? cset->chunk_size |
||||
: cset->element_max - cset->chunk_count*index; |
||||
if (alloc) |
||||
{ |
||||
/* allocate elements array */ |
||||
memory = cache->root.memory; |
||||
error = MEM_ALLOC( cache->elements, cset->element_size * |
||||
cset->element_count ); |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_FUNC( 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_FUNC( FT_ULong ) FTC_ChunkNode_Size( FTC_ChunkNode node ) |
||||
{ |
||||
FTC_ChunkSet cset = node->cset; |
||||
|
||||
|
||||
return cset->clazz->size_node( node, cset ); |
||||
} |
||||
|
||||
|
||||
FT_CPLUSPLUS( 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_FUNC( FT_Error ) |
||||
FTC_ChunkSet_New( FTC_Chunk_Cache cache, |
||||
FT_Pointer type, |
||||
FT_UInt num_elements, |
||||
FT_UInt element_size, |
||||
FT_UInt chunk_size, |
||||
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( set, clazz->cset_byte_size ) ) |
||||
goto Exit; |
||||
|
||||
cset->cache = cache; |
||||
cset->manager = manager; |
||||
cset->memory = memory; |
||||
cset->element_max = num_elements; |
||||
cset->element_size = element_size; |
||||
cset->element_count = chunk_size; |
||||
cset->clazz = clazz; |
||||
|
||||
/* compute maximum number of nodes */ |
||||
cset->num_chunks = (num_elements + (chunk_size-1))/chunk_size; |
||||
|
||||
/* 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_FUNC( 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->chunk; |
||||
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; |
||||
|
||||
lrunode = FTC_CHUNKNODE_TO_LRUNODE( node ); |
||||
|
||||
manager->num_bytes -= clazz->size_node( node ); |
||||
|
||||
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_FUNC( FT_Error ) |
||||
FTC_ChunkSet_Lookup_Node( FTC_ChunkSet cset, |
||||
FT_UInt glyph_index, |
||||
FTC_ChunkNode *anode, |
||||
FTC_UInt *index ) |
||||
{ |
||||
FTC_Glyph_Cache cache = cset->cache; |
||||
FTC_Manager manager = cache->root.manager; |
||||
FT_Error error = 0; |
||||
|
||||
FTC_GlyphSet_Class* clazz = cset->clazz; |
||||
|
||||
|
||||
*anode = 0; |
||||
if (glyph_index >= cset->elements_max) |
||||
error = FT_Err_Invalid_Argument; |
||||
else |
||||
{ |
||||
FT_UInt chunk_size = cset->chunk_size; |
||||
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, glyph_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, gset ); |
||||
|
||||
if (manager->num_bytes > manager->max_bytes) |
||||
{ |
||||
FTC_ChunkNode_Ref ( node ); |
||||
FTC_Manager_Compress( manager ); |
||||
FTC_ChunkNode_Unref ( node ); |
||||
} |
||||
} |
||||
|
||||
*anode = node; |
||||
*aindex = 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 ) |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
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 = node - lru->nodes; |
||||
node->root.data = set; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
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 ); |
||||
} |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
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_CPLUSPLUS( 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_FUNC( FT_Error ) FTC_Chunk_Cache_Init( FTC_Chunk_Cache cache ) |
||||
{ |
||||
FT_Memory memory = cache->root.memory; |
||||
FT_Error error; |
||||
|
||||
|
||||
/* set up root node_class to be used by manager */ |
||||
cache->root.node_clazz = |
||||
(FTC_CacheNode_Class*)&ftc_chunk_cache_node_class; |
||||
|
||||
/* The following is extremely important for ftc_destroy_glyph_image() */ |
||||
/* to work properly, as the second parameter that is sent to it */ |
||||
/* through the cache manager is `user_data' and must be set to */ |
||||
/* `cache' here. */ |
||||
/* */ |
||||
cache->root.cache_user = cache; |
||||
|
||||
error = FT_Lru_New( &ftc_chunk_set_lru_class, |
||||
FTC_MAX_GLYPH_CSETS, |
||||
cache, |
||||
memory, |
||||
1, /* pre_alloc == TRUE */ |
||||
&cache->csets_lru ); |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_FUNC( void ) FTC_Chunk_Cache_Done( FTC_Chunk_Cache cache ) |
||||
{ |
||||
/* discard glyph sets */ |
||||
FT_Lru_Done( cache->csets_lru ); |
||||
} |
||||
|
||||
|
@ -0,0 +1,346 @@ |
||||
#include <cache/ftcsbits.h> |
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** GLYPH IMAGE NODES *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
void ftc_sbit_chunk_node_destroy( FTC_ChunkNode node ) |
||||
{ |
||||
FTC_ChunkSet cset = node->cset; |
||||
FT_Memory memory = cset->memory; |
||||
FT_UInt count = node->num_elements; |
||||
FTC_SBit sbit = (FTC_SBit)node->elements; |
||||
|
||||
for ( ; count > 0; sbit++, count-- ) |
||||
FREE( sbit->buffer ); |
||||
|
||||
FREE( node ); |
||||
} |
||||
|
||||
|
||||
static |
||||
FT_Error ftc_bitmap_copy( FT_Memory memory, |
||||
FT_Bitmap* source, |
||||
FTC_SBit target ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Int pitch = source->pitch; |
||||
FT_ULong size; |
||||
|
||||
if ( pitch < 0 ) |
||||
pitch = -pitch; |
||||
|
||||
size = (FT_ULong)( pitch * source->rows ); |
||||
|
||||
if ( !ALLOC( target->buffer, size ) ) |
||||
MEM_Copy( target->buffer, source->buffer, size ); |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
FT_Error ftc_sbit_chunk_node_new( FTC_ChunkSet cset, |
||||
FT_UInt index, |
||||
FTC_SBitChunk *anode ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Memory memory = cset->memory; |
||||
FTC_SBitSet sbitset = (FTC_SBitSet)cset; |
||||
FTC_SBitChunk node = 0; |
||||
FT_Face face; |
||||
FT_Size size; |
||||
|
||||
|
||||
/* allocate node */ |
||||
if ( ALLOC( node, sizeof ( *node ) ) ) |
||||
goto Exit; |
||||
|
||||
/* init its inner fields */ |
||||
error = FTC_ChunkNode_Init( FTC_CHUNKNODE(node), cset, index, 1 ); |
||||
if (error) |
||||
goto Exit; |
||||
|
||||
/* we will now load all glyph images */ |
||||
error = FTC_Manager_Lookup_Size( cset->manager, |
||||
&sbitset->description.font, |
||||
&face, &size ); |
||||
if ( !error ) |
||||
{ |
||||
FT_UInt glyph_index = index * cset->chunk_size; |
||||
FT_UInt load_flags = FT_LOAD_DEFAULT; |
||||
FT_UInt image_type = sbitset->description.image_type; |
||||
FT_UInt count = node->num_elements; |
||||
FTC_SBit sbit = (FTC_SBit)node->elements; |
||||
|
||||
|
||||
if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap ) |
||||
{ |
||||
if ( image_type & ftc_image_flag_monochrome ) |
||||
load_flags |= FT_LOAD_MONOCHROME; |
||||
|
||||
/* disable embedded bitmaps loading if necessary */ |
||||
if ( image_type & ftc_image_flag_no_sbits ) |
||||
load_flags |= FT_LOAD_NO_BITMAP; |
||||
} |
||||
else if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_outline ) |
||||
{ |
||||
/* disable embedded bitmaps loading */ |
||||
load_flags |= FT_LOAD_NO_BITMAP; |
||||
|
||||
if ( image_type & ftc_image_flag_unscaled ) |
||||
{ |
||||
FT_ERROR(( "FTC_SBit_Cache: cannot load vector outlines in a" |
||||
" sbit cache, please check your arguments !!\n" )); |
||||
error = FT_Err_Bad_Argument; |
||||
goto Exit; |
||||
} |
||||
} |
||||
|
||||
/* always render glyphs to bitmaps */ |
||||
load_flags |= FT_LOAD_RENDER; |
||||
|
||||
if ( image_type & ftc_image_flag_unhinted ) |
||||
load_flags |= FT_LOAD_NO_HINTING; |
||||
|
||||
if ( image_type & ftc_image_flag_autohinted ) |
||||
load_flags |= FT_LOAD_FORCE_AUTOHINT; |
||||
|
||||
|
||||
/* load a chunk of small bitmaps in a row */ |
||||
for ( ; count > 0; count--, glyph_index++ ) |
||||
{ |
||||
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
||||
if (!error) |
||||
{ |
||||
FT_Int temp; |
||||
FT_GlyphSlot slot = face->glyph; |
||||
FT_Bitmap* bitmap = &slot->bitmap; |
||||
FT_Int advance; |
||||
|
||||
/* check that our values fit in 8-bit containers !! */ |
||||
#define CHECK_SCHAR(d) ( temp = (FT_SChar)d, temp == d ) |
||||
#define CHECK_BYTE(d) ( temp = (FT_Byte) d, temp == d ) |
||||
|
||||
advance = (slot->metrics.horiAdvance+32) >> 6; |
||||
|
||||
if ( CHECK_BYTE ( bitmap->rows ) && |
||||
CHECK_BYTE ( bitmap->width ) && |
||||
CHECK_SCHAR( bitmap->pitch ) && |
||||
CHECK_SCHAR( slot->bitmap_left ) && |
||||
CHECK_SCHAR( slot->bitmap_top ) && |
||||
CHECK_SCHAR( advance ) ) |
||||
{ |
||||
sbit->width = (FT_Byte) bitmap->width; |
||||
sbit->height = (FT_Byte) bitmap->height; |
||||
sbit->pitch = (FT_SChar)bitmap->pitch; |
||||
sbit->left = (FT_SChar)slot->bitmap_left; |
||||
sbit->top = (FT_SChar)slot->bitmap_top; |
||||
sbit->advance = (FT_SChar)advance; |
||||
|
||||
/* grab the bitmap when possible */ |
||||
if ( slot->flags & ft_glyph_own_bitmap ) |
||||
{ |
||||
slot->flags &= ~ft_glyph_own_bitmap; |
||||
sbit->buffer = bitmap->buffer; |
||||
} |
||||
else |
||||
{ |
||||
/* copy the bitmap into a new buffer - ignore error */ |
||||
ftc_bitmap_copy( memory, bitmap, sbit ); |
||||
} |
||||
} |
||||
} |
||||
else |
||||
sbit->buffer = 0; |
||||
} |
||||
|
||||
/* ignore the errors that might have occured there */ |
||||
/* we recognize unloaded glyphs with "sbit.buffer == 0" */ |
||||
error = 0; |
||||
} |
||||
|
||||
Exit: |
||||
if ( error && node ) |
||||
{ |
||||
FREE( node->elements ); |
||||
FREE( node ); |
||||
} |
||||
|
||||
*anode = node; |
||||
return error; |
||||
} |
||||
|
||||
|
||||
/* this function is important because it is both part of */ |
||||
/* a FTC_ChunkSet_Class and a FTC_CacheNode_Class */ |
||||
/* */ |
||||
LOCAL_FUNC_X |
||||
FT_ULong ftc_sbit_chunk_node_size( FTC_SBitChunk node ) |
||||
{ |
||||
FT_ULong size = 0; |
||||
FT_Glyph glyph = node->ft_glyph; |
||||
|
||||
|
||||
switch ( glyph->format ) |
||||
{ |
||||
case ft_glyph_format_bitmap: |
||||
{ |
||||
FT_BitmapGlyph bitg; |
||||
|
||||
|
||||
bitg = (FT_BitmapGlyph)glyph; |
||||
size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) + |
||||
sizeof ( *bitg ); |
||||
} |
||||
break; |
||||
|
||||
case ft_glyph_format_outline: |
||||
{ |
||||
FT_OutlineGlyph outg; |
||||
|
||||
|
||||
outg = (FT_OutlineGlyph)glyph; |
||||
size = outg->outline.n_points * |
||||
( sizeof( FT_Vector ) + sizeof ( FT_Byte ) ) + |
||||
outg->outline.n_contours * sizeof ( FT_Short ) + |
||||
sizeof ( *outg ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
; |
||||
} |
||||
|
||||
size += sizeof ( *node ); |
||||
return size; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** GLYPH IMAGE QUEUES *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
FT_Error ftc_image_set_init( FTC_ImageSet iset, |
||||
FTC_Image_Desc* type ) |
||||
{ |
||||
iset->description = *type; |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
LOCAL_FUNC_X |
||||
FT_Bool ftc_image_set_compare( FTC_ImageSet iset, |
||||
FTC_Image_Desc* type ) |
||||
{ |
||||
return !memcmp( &iset->description, type, sizeof ( *type ) ); |
||||
} |
||||
|
||||
|
||||
FT_CPLUSPLUS( const FTC_ChunkSet_Class ) ftc_sbit_chunk_set_class = |
||||
{ |
||||
sizeof( FTC_ImageSetRec ), |
||||
|
||||
(FTC_ChunkSet_InitFunc) ftc_image_set_init, |
||||
(FTC_ChunkSet_DoneFunc) 0, |
||||
(FTC_ChunkSet_CompareFunc) ftc_image_set_compare, |
||||
|
||||
(FTC_ChunkSet_NewNodeFunc) ftc_sbit_chunk_node_new, |
||||
(FTC_ChunkSet_SizeNodeFunc) ftc_sbit_chunk_node_size, |
||||
(FTC_ChunkSet_DestroyNodeFunc)ftc_sbit_chunk_node_destroy |
||||
}; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** GLYPH IMAGE CACHE *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
FT_CPLUSPLUS( const FTC_Glyph_Cache_Class ) ftc_sbit_chunk_cache_class = |
||||
{ |
||||
{ |
||||
sizeof( FTC_Image_CacheRec ), |
||||
(FTC_Cache_InitFunc) FTC_Glyph_Cache_Init, |
||||
(FTC_Cache_DoneFunc) FTC_Glyph_Cache_Done |
||||
}, |
||||
(FTC_ChunkSet_Class*) &ftc_sbit_chunk_set_class |
||||
}; |
||||
|
||||
|
||||
FT_EXPORT_FUNC( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager, |
||||
FTC_Image_Cache* acache ) |
||||
{ |
||||
return FTC_Manager_Register_Cache( |
||||
manager, |
||||
(FTC_Cache_Class*)&ftc_sbit_chunk_cache_class, |
||||
(FTC_Cache*)acache ); |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_Image_Cache_Lookup( FTC_Image_Cache cache, |
||||
FTC_Image_Desc* desc, |
||||
FT_UInt gindex, |
||||
FT_Glyph* aglyph ) |
||||
{ |
||||
FT_Error error; |
||||
FTC_ChunkSet gset; |
||||
FTC_GlyphNode node; |
||||
FTC_Manager manager; |
||||
|
||||
FTC_ImageSet img_set; |
||||
|
||||
|
||||
/* check for valid `desc' delayed to FT_Lru_Lookup() */ |
||||
|
||||
if ( !cache || !aglyph ) |
||||
return FT_Err_Invalid_Argument; |
||||
|
||||
*aglyph = 0; |
||||
gset = cache->root.last_gset; |
||||
img_set = (FTC_ImageSet)gset; |
||||
if ( !gset || memcmp( &img_set->description, desc, sizeof ( *desc ) ) ) |
||||
{ |
||||
error = FT_Lru_Lookup( cache->root.gsets_lru, |
||||
(FT_LruKey)desc, |
||||
(FT_Pointer*)&gset ); |
||||
cache->root.last_gset = gset; |
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
|
||||
error = FTC_ChunkSet_Lookup_Node( gset, gindex, &node ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* now compress the manager's cache pool if needed */ |
||||
manager = cache->root.root.manager; |
||||
if ( manager->num_bytes > manager->max_bytes ) |
||||
{ |
||||
FTC_GlyphNode_Ref ( node ); |
||||
FTC_Manager_Compress( manager ); |
||||
FTC_GlyphNode_Unref ( node ); |
||||
} |
||||
|
||||
*aglyph = ((FTC_SBitChunk)node)->ft_glyph; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
@ -0,0 +1,97 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcsbits.h */ |
||||
/* */ |
||||
/* a small-bitmaps cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#ifndef FTCSBITS_H |
||||
#define FTCSBITS_H |
||||
|
||||
#include <freetype/cache/ftcchunk.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* handle to small bitmap */ |
||||
typedef struct FTC_SBitRec_* FTC_SBit; |
||||
|
||||
|
||||
/* handle to small bitmap cache */ |
||||
typedef struct FTC_SBit_CacheRec_* FTC_SBit_Cache; |
||||
|
||||
|
||||
/* format of small bitmaps */
|
||||
typedef enum FTC_SBit_Format_ |
||||
{ |
||||
ftc_sbit_format_mono = 0, |
||||
ftc_sbit_format_aa256 = 1, |
||||
|
||||
} FTC_SBit_Format; |
||||
|
||||
|
||||
/* a compact structure used to hold a single small bitmap */
|
||||
typedef struct FTC_SBitRec_ |
||||
{ |
||||
FT_Byte width; |
||||
FT_Byte height; |
||||
FT_SChar left; |
||||
FT_SChar top; |
||||
|
||||
FT_Byte format; |
||||
FT_SChar pitch; |
||||
FT_SChar xadvance; |
||||
FT_SChar yadvance; |
||||
|
||||
FT_Byte* buffer; |
||||
|
||||
} FTC_SBitRec; |
||||
|
||||
|
||||
typedef struct FTC_SBitSetRec_ |
||||
{ |
||||
FTC_ChunkSetRec root; |
||||
FTC_Image_Desc desc; |
||||
|
||||
} FTC_SBitSet; |
||||
|
||||
|
||||
typedef struct FTC_SBit_CacheRec_ |
||||
{ |
||||
FTC_Chunk_CacheRec root; |
||||
|
||||
} FTC_SBit_CacheRec; |
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_SBit_Cache_New( FTC_Manager manager, |
||||
FTC_SBit_Cache *acache ); |
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache, |
||||
FTC_Image_Desc* desc, |
||||
FTC_SBit *sbit ); |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
|
||||
#endif /* FTCSBITS_H */ |
||||
|
||||
/* END */ |
||||
|
Loading…
Reference in new issue