/programs/develop/libraries/freetype/src/cache/Jamfile |
---|
0,0 → 1,43 |
# FreeType 2 src/cache Jamfile |
# |
# Copyright 2001, 2003, 2004 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. |
SubDir FT2_TOP $(FT2_SRC_DIR) cache ; |
# The file <freetype/ftcache.h> contains some macro definitions that are |
# later used in #include statements related to the cache sub-system. It |
# needs to be parsed through a HDRMACRO rule for macro definitions. |
# |
HDRMACRO [ FT2_SubDir include ftcache.h ] ; |
{ |
local _sources ; |
if $(FT2_MULTI) |
{ |
_sources = ftcmru |
ftcmanag |
ftccache |
ftcglyph |
ftcsbits |
ftcimage |
ftcbasic |
ftccmap |
; |
} |
else |
{ |
_sources = ftcache ; |
} |
Library $(FT2_LIB) : $(_sources).c ; |
} |
# end of src/cache Jamfile |
/programs/develop/libraries/freetype/src/cache/ftcache.c |
---|
0,0 → 1,31 |
/***************************************************************************/ |
/* */ |
/* ftcache.c */ |
/* */ |
/* The FreeType Caching sub-system (body only). */ |
/* */ |
/* Copyright 2000-2001, 2003 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. */ |
/* */ |
/***************************************************************************/ |
#define FT_MAKE_OPTION_SINGLE_OBJECT |
#include <ft2build.h> |
#include "ftcmru.c" |
#include "ftcmanag.c" |
#include "ftccache.c" |
#include "ftccmap.c" |
#include "ftcglyph.c" |
#include "ftcimage.c" |
#include "ftcsbits.c" |
#include "ftcbasic.c" |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcbasic.c |
---|
0,0 → 1,602 |
/***************************************************************************/ |
/* */ |
/* ftcbasic.c */ |
/* */ |
/* The FreeType basic cache interface (body). */ |
/* */ |
/* Copyright 2003-2007, 2009-2011, 2013 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_INTERNAL_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include FT_CACHE_H |
#include "ftcglyph.h" |
#include "ftcimage.h" |
#include "ftcsbits.h" |
#include "ftccback.h" |
#include "ftcerror.h" |
#define FT_COMPONENT trace_cache |
/* |
* Basic Families |
* |
*/ |
typedef struct FTC_BasicAttrRec_ |
{ |
FTC_ScalerRec scaler; |
FT_UInt load_flags; |
} FTC_BasicAttrRec, *FTC_BasicAttrs; |
#define FTC_BASIC_ATTR_COMPARE( a, b ) \ |
FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \ |
(a)->load_flags == (b)->load_flags ) |
#define FTC_BASIC_ATTR_HASH( a ) \ |
( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags ) |
typedef struct FTC_BasicQueryRec_ |
{ |
FTC_GQueryRec gquery; |
FTC_BasicAttrRec attrs; |
} FTC_BasicQueryRec, *FTC_BasicQuery; |
typedef struct FTC_BasicFamilyRec_ |
{ |
FTC_FamilyRec family; |
FTC_BasicAttrRec attrs; |
} FTC_BasicFamilyRec, *FTC_BasicFamily; |
FT_CALLBACK_DEF( FT_Bool ) |
ftc_basic_family_compare( FTC_MruNode ftcfamily, |
FT_Pointer ftcquery ) |
{ |
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ); |
} |
FT_CALLBACK_DEF( FT_Error ) |
ftc_basic_family_init( FTC_MruNode ftcfamily, |
FT_Pointer ftcquery, |
FT_Pointer ftccache ) |
{ |
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; |
FTC_Cache cache = (FTC_Cache)ftccache; |
FTC_Family_Init( FTC_FAMILY( family ), cache ); |
family->attrs = query->attrs; |
return 0; |
} |
FT_CALLBACK_DEF( FT_UInt ) |
ftc_basic_family_get_count( FTC_Family ftcfamily, |
FTC_Manager manager ) |
{ |
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
FT_Error error; |
FT_Face face; |
FT_UInt result = 0; |
error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id, |
&face ); |
if ( error || !face ) |
return result; |
if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs ) |
{ |
FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " )); |
FT_TRACE1(( "in this face, truncated\n", face->num_glyphs )); |
} |
if ( !error ) |
result = (FT_UInt)face->num_glyphs; |
return result; |
} |
FT_CALLBACK_DEF( FT_Error ) |
ftc_basic_family_load_bitmap( FTC_Family ftcfamily, |
FT_UInt gindex, |
FTC_Manager manager, |
FT_Face *aface ) |
{ |
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
FT_Error error; |
FT_Size size; |
error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size ); |
if ( !error ) |
{ |
FT_Face face = size->face; |
error = FT_Load_Glyph( face, gindex, |
family->attrs.load_flags | FT_LOAD_RENDER ); |
if ( !error ) |
*aface = face; |
} |
return error; |
} |
FT_CALLBACK_DEF( FT_Error ) |
ftc_basic_family_load_glyph( FTC_Family ftcfamily, |
FT_UInt gindex, |
FTC_Cache cache, |
FT_Glyph *aglyph ) |
{ |
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; |
FT_Error error; |
FTC_Scaler scaler = &family->attrs.scaler; |
FT_Face face; |
FT_Size size; |
/* we will now load the glyph image */ |
error = FTC_Manager_LookupSize( cache->manager, |
scaler, |
&size ); |
if ( !error ) |
{ |
face = size->face; |
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags ); |
if ( !error ) |
{ |
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || |
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) |
{ |
/* ok, copy it */ |
FT_Glyph glyph; |
error = FT_Get_Glyph( face->glyph, &glyph ); |
if ( !error ) |
{ |
*aglyph = glyph; |
goto Exit; |
} |
} |
else |
error = FT_THROW( Invalid_Argument ); |
} |
} |
Exit: |
return error; |
} |
FT_CALLBACK_DEF( FT_Bool ) |
ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode, |
FT_Pointer ftcface_id, |
FTC_Cache cache, |
FT_Bool* list_changed ) |
{ |
FTC_GNode gnode = (FTC_GNode)ftcgnode; |
FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
FTC_BasicFamily family = (FTC_BasicFamily)gnode->family; |
FT_Bool result; |
if ( list_changed ) |
*list_changed = FALSE; |
result = FT_BOOL( family->attrs.scaler.face_id == face_id ); |
if ( result ) |
{ |
/* we must call this function to avoid this node from appearing |
* in later lookups with the same face_id! |
*/ |
FTC_GNode_UnselectFamily( gnode, cache ); |
} |
return result; |
} |
/* |
* |
* basic image cache |
* |
*/ |
FT_CALLBACK_TABLE_DEF |
const FTC_IFamilyClassRec ftc_basic_image_family_class = |
{ |
{ |
sizeof ( FTC_BasicFamilyRec ), |
ftc_basic_family_compare, |
ftc_basic_family_init, |
0, /* FTC_MruNode_ResetFunc */ |
0 /* FTC_MruNode_DoneFunc */ |
}, |
ftc_basic_family_load_glyph |
}; |
FT_CALLBACK_TABLE_DEF |
const FTC_GCacheClassRec ftc_basic_image_cache_class = |
{ |
{ |
ftc_inode_new, |
ftc_inode_weight, |
ftc_gnode_compare, |
ftc_basic_gnode_compare_faceid, |
ftc_inode_free, |
sizeof ( FTC_GCacheRec ), |
ftc_gcache_init, |
ftc_gcache_done |
}, |
(FTC_MruListClass)&ftc_basic_image_family_class |
}; |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_ImageCache_New( FTC_Manager manager, |
FTC_ImageCache *acache ) |
{ |
return FTC_GCache_New( manager, &ftc_basic_image_cache_class, |
(FTC_GCache*)acache ); |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_ImageCache_Lookup( FTC_ImageCache cache, |
FTC_ImageType type, |
FT_UInt gindex, |
FT_Glyph *aglyph, |
FTC_Node *anode ) |
{ |
FTC_BasicQueryRec query; |
FTC_Node node = 0; /* make compiler happy */ |
FT_Error error; |
FT_PtrDist hash; |
/* some argument checks are delayed to FTC_Cache_Lookup */ |
if ( !aglyph ) |
{ |
error = FT_THROW( Invalid_Argument ); |
goto Exit; |
} |
*aglyph = NULL; |
if ( anode ) |
*anode = NULL; |
{ |
if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
{ |
FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) )); |
} |
query.attrs.scaler.face_id = type->face_id; |
query.attrs.scaler.width = type->width; |
query.attrs.scaler.height = type->height; |
query.attrs.load_flags = (FT_UInt)type->flags; |
} |
query.attrs.scaler.pixel = 1; |
query.attrs.scaler.x_res = 0; /* make compilers happy */ |
query.attrs.scaler.y_res = 0; |
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
#if 1 /* inlining is about 50% faster! */ |
FTC_GCACHE_LOOKUP_CMP( cache, |
ftc_basic_family_compare, |
FTC_GNode_Compare, |
hash, gindex, |
&query, |
node, |
error ); |
#else |
error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
hash, gindex, |
FTC_GQUERY( &query ), |
&node ); |
#endif |
if ( !error ) |
{ |
*aglyph = FTC_INODE( node )->glyph; |
if ( anode ) |
{ |
*anode = node; |
node->ref_count++; |
} |
} |
Exit: |
return error; |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_ImageCache_LookupScaler( FTC_ImageCache cache, |
FTC_Scaler scaler, |
FT_ULong load_flags, |
FT_UInt gindex, |
FT_Glyph *aglyph, |
FTC_Node *anode ) |
{ |
FTC_BasicQueryRec query; |
FTC_Node node = 0; /* make compiler happy */ |
FT_Error error; |
FT_PtrDist hash; |
/* some argument checks are delayed to FTC_Cache_Lookup */ |
if ( !aglyph || !scaler ) |
{ |
error = FT_THROW( Invalid_Argument ); |
goto Exit; |
} |
*aglyph = NULL; |
if ( anode ) |
*anode = NULL; |
/* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
if ( load_flags > FT_UINT_MAX ) |
{ |
FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); |
} |
query.attrs.scaler = scaler[0]; |
query.attrs.load_flags = (FT_UInt)load_flags; |
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; |
FTC_GCACHE_LOOKUP_CMP( cache, |
ftc_basic_family_compare, |
FTC_GNode_Compare, |
hash, gindex, |
&query, |
node, |
error ); |
if ( !error ) |
{ |
*aglyph = FTC_INODE( node )->glyph; |
if ( anode ) |
{ |
*anode = node; |
node->ref_count++; |
} |
} |
Exit: |
return error; |
} |
/* |
* |
* basic small bitmap cache |
* |
*/ |
FT_CALLBACK_TABLE_DEF |
const FTC_SFamilyClassRec ftc_basic_sbit_family_class = |
{ |
{ |
sizeof ( FTC_BasicFamilyRec ), |
ftc_basic_family_compare, |
ftc_basic_family_init, |
0, /* FTC_MruNode_ResetFunc */ |
0 /* FTC_MruNode_DoneFunc */ |
}, |
ftc_basic_family_get_count, |
ftc_basic_family_load_bitmap |
}; |
FT_CALLBACK_TABLE_DEF |
const FTC_GCacheClassRec ftc_basic_sbit_cache_class = |
{ |
{ |
ftc_snode_new, |
ftc_snode_weight, |
ftc_snode_compare, |
ftc_basic_gnode_compare_faceid, |
ftc_snode_free, |
sizeof ( FTC_GCacheRec ), |
ftc_gcache_init, |
ftc_gcache_done |
}, |
(FTC_MruListClass)&ftc_basic_sbit_family_class |
}; |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_SBitCache_New( FTC_Manager manager, |
FTC_SBitCache *acache ) |
{ |
return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class, |
(FTC_GCache*)acache ); |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_SBitCache_Lookup( FTC_SBitCache cache, |
FTC_ImageType type, |
FT_UInt gindex, |
FTC_SBit *ansbit, |
FTC_Node *anode ) |
{ |
FT_Error error; |
FTC_BasicQueryRec query; |
FTC_Node node = 0; /* make compiler happy */ |
FT_PtrDist hash; |
if ( anode ) |
*anode = NULL; |
/* other argument checks delayed to FTC_Cache_Lookup */ |
if ( !ansbit ) |
return FT_THROW( Invalid_Argument ); |
*ansbit = NULL; |
{ |
if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) |
{ |
FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); |
FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) )); |
} |
query.attrs.scaler.face_id = type->face_id; |
query.attrs.scaler.width = type->width; |
query.attrs.scaler.height = type->height; |
query.attrs.load_flags = (FT_UInt)type->flags; |
} |
query.attrs.scaler.pixel = 1; |
query.attrs.scaler.x_res = 0; /* make compilers happy */ |
query.attrs.scaler.y_res = 0; |
/* beware, the hash must be the same for all glyph ranges! */ |
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
gindex / FTC_SBIT_ITEMS_PER_NODE; |
#if 1 /* inlining is about 50% faster! */ |
FTC_GCACHE_LOOKUP_CMP( cache, |
ftc_basic_family_compare, |
FTC_SNode_Compare, |
hash, gindex, |
&query, |
node, |
error ); |
#else |
error = FTC_GCache_Lookup( FTC_GCACHE( cache ), |
hash, |
gindex, |
FTC_GQUERY( &query ), |
&node ); |
#endif |
if ( error ) |
goto Exit; |
*ansbit = FTC_SNODE( node )->sbits + |
( gindex - FTC_GNODE( node )->gindex ); |
if ( anode ) |
{ |
*anode = node; |
node->ref_count++; |
} |
Exit: |
return error; |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_SBitCache_LookupScaler( FTC_SBitCache cache, |
FTC_Scaler scaler, |
FT_ULong load_flags, |
FT_UInt gindex, |
FTC_SBit *ansbit, |
FTC_Node *anode ) |
{ |
FT_Error error; |
FTC_BasicQueryRec query; |
FTC_Node node = 0; /* make compiler happy */ |
FT_PtrDist hash; |
if ( anode ) |
*anode = NULL; |
/* other argument checks delayed to FTC_Cache_Lookup */ |
if ( !ansbit || !scaler ) |
return FT_THROW( Invalid_Argument ); |
*ansbit = NULL; |
/* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ |
if ( load_flags > FT_UINT_MAX ) |
{ |
FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); |
FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); |
} |
query.attrs.scaler = scaler[0]; |
query.attrs.load_flags = (FT_UInt)load_flags; |
/* beware, the hash must be the same for all glyph ranges! */ |
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + |
gindex / FTC_SBIT_ITEMS_PER_NODE; |
FTC_GCACHE_LOOKUP_CMP( cache, |
ftc_basic_family_compare, |
FTC_SNode_Compare, |
hash, gindex, |
&query, |
node, |
error ); |
if ( error ) |
goto Exit; |
*ansbit = FTC_SNODE( node )->sbits + |
( gindex - FTC_GNODE( node )->gindex ); |
if ( anode ) |
{ |
*anode = node; |
node->ref_count++; |
} |
Exit: |
return error; |
} |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftccache.c |
---|
0,0 → 1,621 |
/***************************************************************************/ |
/* */ |
/* ftccache.c */ |
/* */ |
/* The FreeType internal cache interface (body). */ |
/* */ |
/* Copyright 2000-2007, 2009-2011, 2013 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 "ftcmanag.h" |
#include FT_INTERNAL_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include "ftccback.h" |
#include "ftcerror.h" |
#undef FT_COMPONENT |
#define FT_COMPONENT trace_cache |
#define FTC_HASH_MAX_LOAD 2 |
#define FTC_HASH_MIN_LOAD 1 |
#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD ) |
/* this one _must_ be a power of 2! */ |
#define FTC_HASH_INITIAL_SIZE 8 |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** CACHE NODE DEFINITIONS *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
/* add a new node to the head of the manager's circular MRU list */ |
static void |
ftc_node_mru_link( FTC_Node node, |
FTC_Manager manager ) |
{ |
void *nl = &manager->nodes_list; |
FTC_MruNode_Prepend( (FTC_MruNode*)nl, |
(FTC_MruNode)node ); |
manager->num_nodes++; |
} |
/* remove a node from the manager's MRU list */ |
static void |
ftc_node_mru_unlink( FTC_Node node, |
FTC_Manager manager ) |
{ |
void *nl = &manager->nodes_list; |
FTC_MruNode_Remove( (FTC_MruNode*)nl, |
(FTC_MruNode)node ); |
manager->num_nodes--; |
} |
#ifndef FTC_INLINE |
/* move a node to the head of the manager's MRU list */ |
static void |
ftc_node_mru_up( FTC_Node node, |
FTC_Manager manager ) |
{ |
FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list, |
(FTC_MruNode)node ); |
} |
/* get a top bucket for specified hash from cache, |
* body for FTC_NODE__TOP_FOR_HASH( cache, hash ) |
*/ |
FT_LOCAL_DEF( FTC_Node* ) |
ftc_get_top_node_for_hash( FTC_Cache cache, |
FT_PtrDist hash ) |
{ |
FTC_Node* pnode; |
FT_UInt idx; |
idx = (FT_UInt)( hash & cache->mask ); |
if ( idx < cache->p ) |
idx = (FT_UInt)( hash & ( 2 * cache->mask + 1 ) ); |
pnode = cache->buckets + idx; |
return pnode; |
} |
#endif /* !FTC_INLINE */ |
/* Note that this function cannot fail. If we cannot re-size the |
* buckets array appropriately, we simply degrade the hash table's |
* performance! |
*/ |
static void |
ftc_cache_resize( FTC_Cache cache ) |
{ |
for (;;) |
{ |
FTC_Node node, *pnode; |
FT_UFast p = cache->p; |
FT_UFast mask = cache->mask; |
FT_UFast count = mask + p + 1; /* number of buckets */ |
/* do we need to shrink the buckets array? */ |
if ( cache->slack < 0 ) |
{ |
FTC_Node new_list = NULL; |
/* try to expand the buckets array _before_ splitting |
* the bucket lists |
*/ |
if ( p >= mask ) |
{ |
FT_Memory memory = cache->memory; |
FT_Error error; |
/* if we can't expand the array, leave immediately */ |
if ( FT_RENEW_ARRAY( cache->buckets, |
( mask + 1 ) * 2, ( mask + 1 ) * 4 ) ) |
break; |
} |
/* split a single bucket */ |
pnode = cache->buckets + p; |
for (;;) |
{ |
node = *pnode; |
if ( node == NULL ) |
break; |
if ( node->hash & ( mask + 1 ) ) |
{ |
*pnode = node->link; |
node->link = new_list; |
new_list = node; |
} |
else |
pnode = &node->link; |
} |
cache->buckets[p + mask + 1] = new_list; |
cache->slack += FTC_HASH_MAX_LOAD; |
if ( p >= mask ) |
{ |
cache->mask = 2 * mask + 1; |
cache->p = 0; |
} |
else |
cache->p = p + 1; |
} |
/* do we need to expand the buckets array? */ |
else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) |
{ |
FT_UFast old_index = p + mask; |
FTC_Node* pold; |
if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) |
break; |
if ( p == 0 ) |
{ |
FT_Memory memory = cache->memory; |
FT_Error error; |
/* if we can't shrink the array, leave immediately */ |
if ( FT_RENEW_ARRAY( cache->buckets, |
( mask + 1 ) * 2, mask + 1 ) ) |
break; |
cache->mask >>= 1; |
p = cache->mask; |
} |
else |
p--; |
pnode = cache->buckets + p; |
while ( *pnode ) |
pnode = &(*pnode)->link; |
pold = cache->buckets + old_index; |
*pnode = *pold; |
*pold = NULL; |
cache->slack -= FTC_HASH_MAX_LOAD; |
cache->p = p; |
} |
/* otherwise, the hash table is balanced */ |
else |
break; |
} |
} |
/* remove a node from its cache's hash table */ |
static void |
ftc_node_hash_unlink( FTC_Node node0, |
FTC_Cache cache ) |
{ |
FTC_Node *pnode = FTC_NODE__TOP_FOR_HASH( cache, node0->hash ); |
for (;;) |
{ |
FTC_Node node = *pnode; |
if ( node == NULL ) |
{ |
FT_TRACE0(( "ftc_node_hash_unlink: unknown node\n" )); |
return; |
} |
if ( node == node0 ) |
break; |
pnode = &(*pnode)->link; |
} |
*pnode = node0->link; |
node0->link = NULL; |
cache->slack++; |
ftc_cache_resize( cache ); |
} |
/* add a node to the `top' of its cache's hash table */ |
static void |
ftc_node_hash_link( FTC_Node node, |
FTC_Cache cache ) |
{ |
FTC_Node *pnode = FTC_NODE__TOP_FOR_HASH( cache, node->hash ); |
node->link = *pnode; |
*pnode = node; |
cache->slack--; |
ftc_cache_resize( cache ); |
} |
/* remove a node from the cache manager */ |
FT_LOCAL_DEF( void ) |
ftc_node_destroy( FTC_Node node, |
FTC_Manager manager ) |
{ |
FTC_Cache cache; |
#ifdef FT_DEBUG_ERROR |
/* find node's cache */ |
if ( node->cache_index >= manager->num_caches ) |
{ |
FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" )); |
return; |
} |
#endif |
cache = manager->caches[node->cache_index]; |
#ifdef FT_DEBUG_ERROR |
if ( cache == NULL ) |
{ |
FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" )); |
return; |
} |
#endif |
manager->cur_weight -= cache->clazz.node_weight( node, cache ); |
/* remove node from mru list */ |
ftc_node_mru_unlink( node, manager ); |
/* remove node from cache's hash table */ |
ftc_node_hash_unlink( node, cache ); |
/* now finalize it */ |
cache->clazz.node_free( node, cache ); |
#if 0 |
/* check, just in case of general corruption :-) */ |
if ( manager->num_nodes == 0 ) |
FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%d)\n", |
manager->num_nodes )); |
#endif |
} |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** ABSTRACT CACHE CLASS *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
FT_LOCAL_DEF( FT_Error ) |
FTC_Cache_Init( FTC_Cache cache ) |
{ |
return ftc_cache_init( cache ); |
} |
FT_LOCAL_DEF( FT_Error ) |
ftc_cache_init( FTC_Cache cache ) |
{ |
FT_Memory memory = cache->memory; |
FT_Error error; |
cache->p = 0; |
cache->mask = FTC_HASH_INITIAL_SIZE - 1; |
cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD; |
(void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ); |
return error; |
} |
static void |
FTC_Cache_Clear( FTC_Cache cache ) |
{ |
if ( cache && cache->buckets ) |
{ |
FTC_Manager manager = cache->manager; |
FT_UFast i; |
FT_UFast count; |
count = cache->p + cache->mask + 1; |
for ( i = 0; i < count; i++ ) |
{ |
FTC_Node *pnode = cache->buckets + i, next, node = *pnode; |
while ( node ) |
{ |
next = node->link; |
node->link = NULL; |
/* remove node from mru list */ |
ftc_node_mru_unlink( node, manager ); |
/* now finalize it */ |
manager->cur_weight -= cache->clazz.node_weight( node, cache ); |
cache->clazz.node_free( node, cache ); |
node = next; |
} |
cache->buckets[i] = NULL; |
} |
ftc_cache_resize( cache ); |
} |
} |
FT_LOCAL_DEF( void ) |
ftc_cache_done( FTC_Cache cache ) |
{ |
if ( cache->memory ) |
{ |
FT_Memory memory = cache->memory; |
FTC_Cache_Clear( cache ); |
FT_FREE( cache->buckets ); |
cache->mask = 0; |
cache->p = 0; |
cache->slack = 0; |
cache->memory = NULL; |
} |
} |
FT_LOCAL_DEF( void ) |
FTC_Cache_Done( FTC_Cache cache ) |
{ |
ftc_cache_done( cache ); |
} |
static void |
ftc_cache_add( FTC_Cache cache, |
FT_PtrDist hash, |
FTC_Node node ) |
{ |
node->hash = hash; |
node->cache_index = (FT_UInt16)cache->index; |
node->ref_count = 0; |
ftc_node_hash_link( node, cache ); |
ftc_node_mru_link( node, cache->manager ); |
{ |
FTC_Manager manager = cache->manager; |
manager->cur_weight += cache->clazz.node_weight( node, cache ); |
if ( manager->cur_weight >= manager->max_weight ) |
{ |
node->ref_count++; |
FTC_Manager_Compress( manager ); |
node->ref_count--; |
} |
} |
} |
FT_LOCAL_DEF( FT_Error ) |
FTC_Cache_NewNode( FTC_Cache cache, |
FT_PtrDist hash, |
FT_Pointer query, |
FTC_Node *anode ) |
{ |
FT_Error error; |
FTC_Node node; |
/* |
* We use the FTC_CACHE_TRYLOOP macros to support out-of-memory |
* errors (OOM) correctly, i.e., by flushing the cache progressively |
* in order to make more room. |
*/ |
FTC_CACHE_TRYLOOP( cache ) |
{ |
error = cache->clazz.node_new( &node, query, cache ); |
} |
FTC_CACHE_TRYLOOP_END( NULL ); |
if ( error ) |
node = NULL; |
else |
{ |
/* don't assume that the cache has the same number of buckets, since |
* our allocation request might have triggered global cache flushing |
*/ |
ftc_cache_add( cache, hash, node ); |
} |
*anode = node; |
return error; |
} |
#ifndef FTC_INLINE |
FT_LOCAL_DEF( FT_Error ) |
FTC_Cache_Lookup( FTC_Cache cache, |
FT_PtrDist hash, |
FT_Pointer query, |
FTC_Node *anode ) |
{ |
FTC_Node* bucket; |
FTC_Node* pnode; |
FTC_Node node; |
FT_Error error = FT_Err_Ok; |
FT_Bool list_changed = FALSE; |
FTC_Node_CompareFunc compare = cache->clazz.node_compare; |
if ( cache == NULL || anode == NULL ) |
return FT_THROW( Invalid_Argument ); |
/* Go to the `top' node of the list sharing same masked hash */ |
bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash ); |
/* Lookup a node with exactly same hash and queried properties. */ |
/* NOTE: _nodcomp() may change the linked list to reduce memory. */ |
for (;;) |
{ |
node = *pnode; |
if ( node == NULL ) |
goto NewNode; |
if ( node->hash == hash && |
compare( node, query, cache, &list_changed ) ) |
break; |
pnode = &node->link; |
} |
if ( list_changed ) |
{ |
/* Update bucket by modified linked list */ |
bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash ); |
/* Update pnode by modified linked list */ |
while ( *pnode != node ) |
{ |
if ( *pnode == NULL ) |
{ |
FT_ERROR(( "FTC_Cache_Lookup: oops!!! node missing\n" )); |
goto NewNode; |
} |
else |
pnode = &((*pnode)->link); |
} |
} |
/* Reorder the list to move the found node to the `top' */ |
if ( node != *bucket ) |
{ |
*pnode = node->link; |
node->link = *bucket; |
*bucket = node; |
} |
/* move to head of MRU list */ |
{ |
FTC_Manager manager = cache->manager; |
if ( node != manager->nodes_list ) |
ftc_node_mru_up( node, manager ); |
} |
*anode = node; |
return error; |
NewNode: |
return FTC_Cache_NewNode( cache, hash, query, anode ); |
} |
#endif /* !FTC_INLINE */ |
FT_LOCAL_DEF( void ) |
FTC_Cache_RemoveFaceID( FTC_Cache cache, |
FTC_FaceID face_id ) |
{ |
FT_UFast i, count; |
FTC_Manager manager = cache->manager; |
FTC_Node frees = NULL; |
count = cache->p + cache->mask + 1; |
for ( i = 0; i < count; i++ ) |
{ |
FTC_Node* bucket = cache->buckets + i; |
FTC_Node* pnode = bucket; |
for ( ;; ) |
{ |
FTC_Node node = *pnode; |
FT_Bool list_changed = FALSE; |
if ( node == NULL ) |
break; |
if ( cache->clazz.node_remove_faceid( node, face_id, |
cache, &list_changed ) ) |
{ |
*pnode = node->link; |
node->link = frees; |
frees = node; |
} |
else |
pnode = &node->link; |
} |
} |
/* remove all nodes in the free list */ |
while ( frees ) |
{ |
FTC_Node node; |
node = frees; |
frees = node->link; |
manager->cur_weight -= cache->clazz.node_weight( node, cache ); |
ftc_node_mru_unlink( node, manager ); |
cache->clazz.node_free( node, cache ); |
cache->slack++; |
} |
ftc_cache_resize( cache ); |
} |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftccache.h |
---|
0,0 → 1,352 |
/***************************************************************************/ |
/* */ |
/* ftccache.h */ |
/* */ |
/* FreeType internal cache interface (specification). */ |
/* */ |
/* Copyright 2000-2007, 2009-2011, 2013 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 __FTCCACHE_H__ |
#define __FTCCACHE_H__ |
#include "ftcmru.h" |
FT_BEGIN_HEADER |
#define _FTC_FACE_ID_HASH( i ) \ |
((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 ))) |
/* handle to cache object */ |
typedef struct FTC_CacheRec_* FTC_Cache; |
/* handle to cache class */ |
typedef const struct FTC_CacheClassRec_* FTC_CacheClass; |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** CACHE NODE DEFINITIONS *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/* */ |
/* Each cache controls one or more cache nodes. Each node is part of */ |
/* the global_lru list of the manager. Its `data' field however is used */ |
/* as a reference count for now. */ |
/* */ |
/* A node can be anything, depending on the type of information held by */ |
/* the cache. It can be an individual glyph image, a set of bitmaps */ |
/* glyphs for a given size, some metrics, etc. */ |
/* */ |
/*************************************************************************/ |
/* structure size should be 20 bytes on 32-bits machines */ |
typedef struct FTC_NodeRec_ |
{ |
FTC_MruNodeRec mru; /* circular mru list pointer */ |
FTC_Node link; /* used for hashing */ |
FT_PtrDist hash; /* used for hashing too */ |
FT_UShort cache_index; /* index of cache the node belongs to */ |
FT_Short ref_count; /* reference count for this node */ |
} FTC_NodeRec; |
#define FTC_NODE( x ) ( (FTC_Node)(x) ) |
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) ) |
#define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next ) |
#define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev ) |
#ifdef FTC_INLINE |
#define FTC_NODE__TOP_FOR_HASH( cache, hash ) \ |
( ( cache )->buckets + \ |
( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \ |
? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \ |
: ( ( hash ) & ( cache )->mask ) ) ) |
#else |
FT_LOCAL( FTC_Node* ) |
ftc_get_top_node_for_hash( FTC_Cache cache, |
FT_PtrDist hash ); |
#define FTC_NODE__TOP_FOR_HASH( cache, hash ) \ |
ftc_get_top_node_for_hash( ( cache ), ( hash ) ) |
#endif |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** CACHE DEFINITIONS *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
/* initialize a new cache node */ |
typedef FT_Error |
(*FTC_Node_NewFunc)( FTC_Node *pnode, |
FT_Pointer query, |
FTC_Cache cache ); |
typedef FT_Offset |
(*FTC_Node_WeightFunc)( FTC_Node node, |
FTC_Cache cache ); |
/* compare a node to a given key pair */ |
typedef FT_Bool |
(*FTC_Node_CompareFunc)( FTC_Node node, |
FT_Pointer key, |
FTC_Cache cache, |
FT_Bool* list_changed ); |
typedef void |
(*FTC_Node_FreeFunc)( FTC_Node node, |
FTC_Cache cache ); |
typedef FT_Error |
(*FTC_Cache_InitFunc)( FTC_Cache cache ); |
typedef void |
(*FTC_Cache_DoneFunc)( FTC_Cache cache ); |
typedef struct FTC_CacheClassRec_ |
{ |
FTC_Node_NewFunc node_new; |
FTC_Node_WeightFunc node_weight; |
FTC_Node_CompareFunc node_compare; |
FTC_Node_CompareFunc node_remove_faceid; |
FTC_Node_FreeFunc node_free; |
FT_Offset cache_size; |
FTC_Cache_InitFunc cache_init; |
FTC_Cache_DoneFunc cache_done; |
} FTC_CacheClassRec; |
/* each cache really implements a dynamic hash table to manage its nodes */ |
typedef struct FTC_CacheRec_ |
{ |
FT_UFast p; |
FT_UFast mask; |
FT_Long slack; |
FTC_Node* buckets; |
FTC_CacheClassRec clazz; /* local copy, for speed */ |
FTC_Manager manager; |
FT_Memory memory; |
FT_UInt index; /* in manager's table */ |
FTC_CacheClass org_class; /* original class pointer */ |
} FTC_CacheRec; |
#define FTC_CACHE( x ) ( (FTC_Cache)(x) ) |
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) ) |
/* default cache initialize */ |
FT_LOCAL( FT_Error ) |
FTC_Cache_Init( FTC_Cache cache ); |
/* default cache finalizer */ |
FT_LOCAL( void ) |
FTC_Cache_Done( FTC_Cache cache ); |
/* Call this function to look up the cache. If no corresponding |
* node is found, a new one is automatically created. This function |
* is capable of flushing the cache adequately to make room for the |
* new cache object. |
*/ |
#ifndef FTC_INLINE |
FT_LOCAL( FT_Error ) |
FTC_Cache_Lookup( FTC_Cache cache, |
FT_PtrDist hash, |
FT_Pointer query, |
FTC_Node *anode ); |
#endif |
FT_LOCAL( FT_Error ) |
FTC_Cache_NewNode( FTC_Cache cache, |
FT_PtrDist hash, |
FT_Pointer query, |
FTC_Node *anode ); |
/* Remove all nodes that relate to a given face_id. This is useful |
* when un-installing fonts. Note that if a cache node relates to |
* the face_id but is locked (i.e., has `ref_count > 0'), the node |
* will _not_ be destroyed, but its internal face_id reference will |
* be modified. |
* |
* The final result will be that the node will never come back |
* in further lookup requests, and will be flushed on demand from |
* the cache normally when its reference count reaches 0. |
*/ |
FT_LOCAL( void ) |
FTC_Cache_RemoveFaceID( FTC_Cache cache, |
FTC_FaceID face_id ); |
#ifdef FTC_INLINE |
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
FT_BEGIN_STMNT \ |
FTC_Node *_bucket, *_pnode, _node; \ |
FTC_Cache _cache = FTC_CACHE(cache); \ |
FT_PtrDist _hash = (FT_PtrDist)(hash); \ |
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \ |
FT_Bool _list_changed = FALSE; \ |
\ |
\ |
error = FT_Err_Ok; \ |
node = NULL; \ |
\ |
/* Go to the `top' node of the list sharing same masked hash */ \ |
_bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \ |
\ |
/* Look up a node with identical hash and queried properties. */ \ |
/* NOTE: _nodcomp() may change the linked list to reduce memory. */ \ |
for (;;) \ |
{ \ |
_node = *_pnode; \ |
if ( _node == NULL ) \ |
goto _NewNode; \ |
\ |
if ( _node->hash == _hash && \ |
_nodcomp( _node, query, _cache, &_list_changed ) ) \ |
break; \ |
\ |
_pnode = &_node->link; \ |
} \ |
\ |
if ( _list_changed ) \ |
{ \ |
/* Update _bucket by possibly modified linked list */ \ |
_bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \ |
\ |
/* Update _pnode by possibly modified linked list */ \ |
while ( *_pnode != _node ) \ |
{ \ |
if ( *_pnode == NULL ) \ |
{ \ |
FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" )); \ |
goto _NewNode; \ |
} \ |
else \ |
_pnode = &((*_pnode)->link); \ |
} \ |
} \ |
\ |
/* Reorder the list to move the found node to the `top' */ \ |
if ( _node != *_bucket ) \ |
{ \ |
*_pnode = _node->link; \ |
_node->link = *_bucket; \ |
*_bucket = _node; \ |
} \ |
\ |
/* Update MRU list */ \ |
{ \ |
FTC_Manager _manager = _cache->manager; \ |
void* _nl = &_manager->nodes_list; \ |
\ |
\ |
if ( _node != _manager->nodes_list ) \ |
FTC_MruNode_Up( (FTC_MruNode*)_nl, \ |
(FTC_MruNode)_node ); \ |
} \ |
goto _Ok; \ |
\ |
_NewNode: \ |
error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \ |
\ |
_Ok: \ |
node = _node; \ |
FT_END_STMNT |
#else /* !FTC_INLINE */ |
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
FT_BEGIN_STMNT \ |
error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \ |
(FTC_Node*)&(node) ); \ |
FT_END_STMNT |
#endif /* !FTC_INLINE */ |
/* |
* This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry |
* loop to flush the cache repeatedly in case of memory overflows. |
* |
* It is used when creating a new cache node, or within a lookup |
* that needs to allocate data (e.g. the sbit cache lookup). |
* |
* Example: |
* |
* { |
* FTC_CACHE_TRYLOOP( cache ) |
* error = load_data( ... ); |
* FTC_CACHE_TRYLOOP_END() |
* } |
* |
*/ |
#define FTC_CACHE_TRYLOOP( cache ) \ |
{ \ |
FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \ |
FT_UInt _try_count = 4; \ |
\ |
\ |
for (;;) \ |
{ \ |
FT_UInt _try_done; |
#define FTC_CACHE_TRYLOOP_END( list_changed ) \ |
if ( !error || FT_ERR_NEQ( error, Out_Of_Memory ) ) \ |
break; \ |
\ |
_try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \ |
if ( _try_done > 0 && ( list_changed ) ) \ |
*(FT_Bool*)( list_changed ) = TRUE; \ |
\ |
if ( _try_done == 0 ) \ |
break; \ |
\ |
if ( _try_done == _try_count ) \ |
{ \ |
_try_count *= 2; \ |
if ( _try_count < _try_done || \ |
_try_count > _try_manager->num_nodes ) \ |
_try_count = _try_manager->num_nodes; \ |
} \ |
} \ |
} |
/* */ |
FT_END_HEADER |
#endif /* __FTCCACHE_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftccback.h |
---|
0,0 → 1,91 |
/***************************************************************************/ |
/* */ |
/* ftccback.h */ |
/* */ |
/* Callback functions of the caching sub-system (specification only). */ |
/* */ |
/* Copyright 2004-2006, 2011, 2013 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 __FTCCBACK_H__ |
#define __FTCCBACK_H__ |
#include <ft2build.h> |
#include FT_CACHE_H |
#include "ftcmru.h" |
#include "ftcimage.h" |
#include "ftcmanag.h" |
#include "ftcglyph.h" |
#include "ftcsbits.h" |
FT_LOCAL( void ) |
ftc_inode_free( FTC_Node inode, |
FTC_Cache cache ); |
FT_LOCAL( FT_Error ) |
ftc_inode_new( FTC_Node *pinode, |
FT_Pointer gquery, |
FTC_Cache cache ); |
FT_LOCAL( FT_Offset ) |
ftc_inode_weight( FTC_Node inode, |
FTC_Cache cache ); |
FT_LOCAL( void ) |
ftc_snode_free( FTC_Node snode, |
FTC_Cache cache ); |
FT_LOCAL( FT_Error ) |
ftc_snode_new( FTC_Node *psnode, |
FT_Pointer gquery, |
FTC_Cache cache ); |
FT_LOCAL( FT_Offset ) |
ftc_snode_weight( FTC_Node snode, |
FTC_Cache cache ); |
FT_LOCAL( FT_Bool ) |
ftc_snode_compare( FTC_Node snode, |
FT_Pointer gquery, |
FTC_Cache cache, |
FT_Bool* list_changed ); |
FT_LOCAL( FT_Bool ) |
ftc_gnode_compare( FTC_Node gnode, |
FT_Pointer gquery, |
FTC_Cache cache, |
FT_Bool* list_changed ); |
FT_LOCAL( FT_Error ) |
ftc_gcache_init( FTC_Cache cache ); |
FT_LOCAL( void ) |
ftc_gcache_done( FTC_Cache cache ); |
FT_LOCAL( FT_Error ) |
ftc_cache_init( FTC_Cache cache ); |
FT_LOCAL( void ) |
ftc_cache_done( FTC_Cache cache ); |
FT_LOCAL( void ) |
ftc_node_destroy( FTC_Node node, |
FTC_Manager manager ); |
#endif /* __FTCCBACK_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftccmap.c |
---|
0,0 → 1,337 |
/***************************************************************************/ |
/* */ |
/* ftccmap.c */ |
/* */ |
/* FreeType CharMap cache (body) */ |
/* */ |
/* Copyright 2000-2013 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_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include "ftccback.h" |
#include "ftcerror.h" |
#undef FT_COMPONENT |
#define FT_COMPONENT trace_cache |
/*************************************************************************/ |
/* */ |
/* 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)~0 |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** 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, |
FT_Bool* list_changed ) |
{ |
FTC_CMapNode node = (FTC_CMapNode)ftcnode; |
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery; |
FT_UNUSED( cache ); |
if ( list_changed ) |
*list_changed = FALSE; |
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, |
FT_Bool* list_changed ) |
{ |
FTC_CMapNode node = (FTC_CMapNode)ftcnode; |
FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
FT_UNUSED( cache ); |
if ( list_changed ) |
*list_changed = FALSE; |
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 ) ); |
} |
/* 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_PtrDist 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; |
} |
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 */ |
/programs/develop/libraries/freetype/src/cache/ftcerror.h |
---|
0,0 → 1,41 |
/***************************************************************************/ |
/* */ |
/* ftcerror.h */ |
/* */ |
/* Caching sub-system error codes (specification only). */ |
/* */ |
/* Copyright 2001, 2012 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. */ |
/* */ |
/***************************************************************************/ |
/*************************************************************************/ |
/* */ |
/* This file is used to define the caching sub-system error enumeration */ |
/* constants. */ |
/* */ |
/*************************************************************************/ |
#ifndef __FTCERROR_H__ |
#define __FTCERROR_H__ |
#include FT_MODULE_ERRORS_H |
#undef __FTERRORS_H__ |
#undef FT_ERR_PREFIX |
#define FT_ERR_PREFIX FTC_Err_ |
#define FT_ERR_BASE FT_Mod_Err_Cache |
#include FT_ERRORS_H |
#endif /* __FTCERROR_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcglyph.c |
---|
0,0 → 1,219 |
/***************************************************************************/ |
/* */ |
/* ftcglyph.c */ |
/* */ |
/* FreeType Glyph Image (FT_Glyph) cache (body). */ |
/* */ |
/* Copyright 2000-2001, 2003, 2004, 2006, 2009, 2011 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_INTERNAL_OBJECTS_H |
#include FT_CACHE_H |
#include "ftcglyph.h" |
#include FT_ERRORS_H |
#include "ftccback.h" |
#include "ftcerror.h" |
/* create a new chunk node, setting its cache index and ref count */ |
FT_LOCAL_DEF( void ) |
FTC_GNode_Init( FTC_GNode gnode, |
FT_UInt gindex, |
FTC_Family family ) |
{ |
gnode->family = family; |
gnode->gindex = gindex; |
family->num_nodes++; |
} |
FT_LOCAL_DEF( void ) |
FTC_GNode_UnselectFamily( FTC_GNode gnode, |
FTC_Cache cache ) |
{ |
FTC_Family family = gnode->family; |
gnode->family = NULL; |
if ( family && --family->num_nodes == 0 ) |
FTC_FAMILY_FREE( family, cache ); |
} |
FT_LOCAL_DEF( void ) |
FTC_GNode_Done( FTC_GNode gnode, |
FTC_Cache cache ) |
{ |
/* finalize the node */ |
gnode->gindex = 0; |
FTC_GNode_UnselectFamily( gnode, cache ); |
} |
FT_LOCAL_DEF( FT_Bool ) |
ftc_gnode_compare( FTC_Node ftcgnode, |
FT_Pointer ftcgquery, |
FTC_Cache cache, |
FT_Bool* list_changed ) |
{ |
FTC_GNode gnode = (FTC_GNode)ftcgnode; |
FTC_GQuery gquery = (FTC_GQuery)ftcgquery; |
FT_UNUSED( cache ); |
if ( list_changed ) |
*list_changed = FALSE; |
return FT_BOOL( gnode->family == gquery->family && |
gnode->gindex == gquery->gindex ); |
} |
#ifdef FTC_INLINE |
FT_LOCAL_DEF( FT_Bool ) |
FTC_GNode_Compare( FTC_GNode gnode, |
FTC_GQuery gquery, |
FTC_Cache cache, |
FT_Bool* list_changed ) |
{ |
return ftc_gnode_compare( FTC_NODE( gnode ), gquery, |
cache, list_changed ); |
} |
#endif |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** CHUNK SETS *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
FT_LOCAL_DEF( void ) |
FTC_Family_Init( FTC_Family family, |
FTC_Cache cache ) |
{ |
FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS( cache ); |
family->clazz = clazz->family_class; |
family->num_nodes = 0; |
family->cache = cache; |
} |
FT_LOCAL_DEF( FT_Error ) |
ftc_gcache_init( FTC_Cache ftccache ) |
{ |
FTC_GCache cache = (FTC_GCache)ftccache; |
FT_Error error; |
error = FTC_Cache_Init( FTC_CACHE( cache ) ); |
if ( !error ) |
{ |
FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class; |
FTC_MruList_Init( &cache->families, |
clazz->family_class, |
0, /* no maximum here! */ |
cache, |
FTC_CACHE( cache )->memory ); |
} |
return error; |
} |
#if 0 |
FT_LOCAL_DEF( FT_Error ) |
FTC_GCache_Init( FTC_GCache cache ) |
{ |
return ftc_gcache_init( FTC_CACHE( cache ) ); |
} |
#endif /* 0 */ |
FT_LOCAL_DEF( void ) |
ftc_gcache_done( FTC_Cache ftccache ) |
{ |
FTC_GCache cache = (FTC_GCache)ftccache; |
FTC_Cache_Done( (FTC_Cache)cache ); |
FTC_MruList_Done( &cache->families ); |
} |
#if 0 |
FT_LOCAL_DEF( void ) |
FTC_GCache_Done( FTC_GCache cache ) |
{ |
ftc_gcache_done( FTC_CACHE( cache ) ); |
} |
#endif /* 0 */ |
FT_LOCAL_DEF( FT_Error ) |
FTC_GCache_New( FTC_Manager manager, |
FTC_GCacheClass clazz, |
FTC_GCache *acache ) |
{ |
return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz, |
(FTC_Cache*)acache ); |
} |
#ifndef FTC_INLINE |
FT_LOCAL_DEF( FT_Error ) |
FTC_GCache_Lookup( FTC_GCache cache, |
FT_PtrDist hash, |
FT_UInt gindex, |
FTC_GQuery query, |
FTC_Node *anode ) |
{ |
FT_Error error; |
query->gindex = gindex; |
FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error ); |
if ( !error ) |
{ |
FTC_Family family = query->family; |
/* prevent the family from being destroyed too early when an */ |
/* out-of-memory condition occurs during glyph node initialization. */ |
family->num_nodes++; |
error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode ); |
if ( --family->num_nodes == 0 ) |
FTC_FAMILY_FREE( family, cache ); |
} |
return error; |
} |
#endif /* !FTC_INLINE */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcglyph.h |
---|
0,0 → 1,329 |
/***************************************************************************/ |
/* */ |
/* ftcglyph.h */ |
/* */ |
/* FreeType abstract glyph cache (specification). */ |
/* */ |
/* Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 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. */ |
/* */ |
/***************************************************************************/ |
/* |
* |
* FTC_GCache is an _abstract_ cache object optimized to store glyph |
* data. It works as follows: |
* |
* - It manages FTC_GNode objects. Each one of them can hold one or more |
* glyph `items'. Item types are not specified in the FTC_GCache but |
* in classes that extend it. |
* |
* - Glyph attributes, like face ID, character size, render mode, etc., |
* can be grouped into abstract `glyph families'. This avoids storing |
* the attributes within the FTC_GCache, since it is likely that many |
* FTC_GNodes will belong to the same family in typical uses. |
* |
* - Each FTC_GNode is thus an FTC_Node with two additional fields: |
* |
* * gindex: A glyph index, or the first index in a glyph range. |
* * family: A pointer to a glyph `family'. |
* |
* - Family types are not fully specific in the FTC_Family type, but |
* by classes that extend it. |
* |
* Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache. |
* They share an FTC_Family sub-class called FTC_BasicFamily which is |
* used to store the following data: face ID, pixel/point sizes, load |
* flags. For more details see the file `src/cache/ftcbasic.c'. |
* |
* Client applications can extend FTC_GNode with their own FTC_GNode |
* and FTC_Family sub-classes to implement more complex caches (e.g., |
* handling automatic synthesis, like obliquing & emboldening, colored |
* glyphs, etc.). |
* |
* See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and |
* `ftcsbits.h', which both extend FTC_GCache with additional |
* optimizations. |
* |
* A typical FTC_GCache implementation must provide at least the |
* following: |
* |
* - FTC_GNode sub-class, e.g. MyNode, with relevant methods: |
* my_node_new (must call FTC_GNode_Init) |
* my_node_free (must call FTC_GNode_Done) |
* my_node_compare (must call FTC_GNode_Compare) |
* my_node_remove_faceid (must call ftc_gnode_unselect in case |
* of match) |
* |
* - FTC_Family sub-class, e.g. MyFamily, with relevant methods: |
* my_family_compare |
* my_family_init |
* my_family_reset (optional) |
* my_family_done |
* |
* - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query |
* data. |
* |
* - Constant structures for a FTC_GNodeClass. |
* |
* - MyCacheNew() can be implemented easily as a call to the convenience |
* function FTC_GCache_New. |
* |
* - MyCacheLookup with a call to FTC_GCache_Lookup. This function will |
* automatically: |
* |
* - Search for the corresponding family in the cache, or create |
* a new one if necessary. Put it in FTC_GQUERY(myquery).family |
* |
* - Call FTC_Cache_Lookup. |
* |
* If it returns NULL, you should create a new node, then call |
* ftc_cache_add as usual. |
*/ |
/*************************************************************************/ |
/* */ |
/* Important: The functions defined in this file are only used to */ |
/* implement an abstract glyph cache class. You need to */ |
/* provide additional logic to implement a complete cache. */ |
/* */ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/********* *********/ |
/********* WARNING, THIS IS BETA CODE. *********/ |
/********* *********/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
#ifndef __FTCGLYPH_H__ |
#define __FTCGLYPH_H__ |
#include <ft2build.h> |
#include "ftcmanag.h" |
FT_BEGIN_HEADER |
/* |
* We can group glyphs into `families'. Each family correspond to a |
* given face ID, character size, transform, etc. |
* |
* Families are implemented as MRU list nodes. They are |
* reference-counted. |
*/ |
typedef struct FTC_FamilyRec_ |
{ |
FTC_MruNodeRec mrunode; |
FT_UInt num_nodes; /* current number of nodes in this family */ |
FTC_Cache cache; |
FTC_MruListClass clazz; |
} FTC_FamilyRec, *FTC_Family; |
#define FTC_FAMILY(x) ( (FTC_Family)(x) ) |
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) |
typedef struct FTC_GNodeRec_ |
{ |
FTC_NodeRec node; |
FTC_Family family; |
FT_UInt gindex; |
} FTC_GNodeRec, *FTC_GNode; |
#define FTC_GNODE( x ) ( (FTC_GNode)(x) ) |
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) ) |
typedef struct FTC_GQueryRec_ |
{ |
FT_UInt gindex; |
FTC_Family family; |
} FTC_GQueryRec, *FTC_GQuery; |
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) ) |
/*************************************************************************/ |
/* */ |
/* These functions are exported so that they can be called from */ |
/* user-provided cache classes; otherwise, they are really part of the */ |
/* cache sub-system internals. */ |
/* */ |
/* must be called by derived FTC_Node_InitFunc routines */ |
FT_LOCAL( void ) |
FTC_GNode_Init( FTC_GNode node, |
FT_UInt gindex, /* glyph index for node */ |
FTC_Family family ); |
#ifdef FTC_INLINE |
/* returns TRUE iff the query's glyph index correspond to the node; */ |
/* this assumes that the `family' and `hash' fields of the query are */ |
/* already correctly set */ |
FT_LOCAL( FT_Bool ) |
FTC_GNode_Compare( FTC_GNode gnode, |
FTC_GQuery gquery, |
FTC_Cache cache, |
FT_Bool* list_changed ); |
#endif |
/* call this function to clear a node's family -- this is necessary */ |
/* to implement the `node_remove_faceid' cache method correctly */ |
FT_LOCAL( void ) |
FTC_GNode_UnselectFamily( FTC_GNode gnode, |
FTC_Cache cache ); |
/* must be called by derived FTC_Node_DoneFunc routines */ |
FT_LOCAL( void ) |
FTC_GNode_Done( FTC_GNode node, |
FTC_Cache cache ); |
FT_LOCAL( void ) |
FTC_Family_Init( FTC_Family family, |
FTC_Cache cache ); |
typedef struct FTC_GCacheRec_ |
{ |
FTC_CacheRec cache; |
FTC_MruListRec families; |
} FTC_GCacheRec, *FTC_GCache; |
#define FTC_GCACHE( x ) ((FTC_GCache)(x)) |
#if 0 |
/* can be used as @FTC_Cache_InitFunc */ |
FT_LOCAL( FT_Error ) |
FTC_GCache_Init( FTC_GCache cache ); |
#endif |
#if 0 |
/* can be used as @FTC_Cache_DoneFunc */ |
FT_LOCAL( void ) |
FTC_GCache_Done( FTC_GCache cache ); |
#endif |
/* the glyph cache class adds fields for the family implementation */ |
typedef struct FTC_GCacheClassRec_ |
{ |
FTC_CacheClassRec clazz; |
FTC_MruListClass family_class; |
} FTC_GCacheClassRec; |
typedef const FTC_GCacheClassRec* FTC_GCacheClass; |
#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) |
#define FTC_CACHE__GCACHE_CLASS( x ) \ |
FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) |
#define FTC_CACHE__FAMILY_CLASS( x ) \ |
( (FTC_MruListClass)FTC_CACHE__GCACHE_CLASS( x )->family_class ) |
/* convenience function; use it instead of FTC_Manager_Register_Cache */ |
FT_LOCAL( FT_Error ) |
FTC_GCache_New( FTC_Manager manager, |
FTC_GCacheClass clazz, |
FTC_GCache *acache ); |
#ifndef FTC_INLINE |
FT_LOCAL( FT_Error ) |
FTC_GCache_Lookup( FTC_GCache cache, |
FT_PtrDist hash, |
FT_UInt gindex, |
FTC_GQuery query, |
FTC_Node *anode ); |
#endif |
/* */ |
#define FTC_FAMILY_FREE( family, cache ) \ |
FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \ |
(FTC_MruNode)(family) ) |
#ifdef FTC_INLINE |
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
gindex, query, node, error ) \ |
FT_BEGIN_STMNT \ |
FTC_GCache _gcache = FTC_GCACHE( cache ); \ |
FTC_GQuery _gquery = (FTC_GQuery)( query ); \ |
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \ |
FTC_MruNode _mrunode; \ |
\ |
\ |
_gquery->gindex = (gindex); \ |
\ |
FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \ |
_mrunode, error ); \ |
_gquery->family = FTC_FAMILY( _mrunode ); \ |
if ( !error ) \ |
{ \ |
FTC_Family _gqfamily = _gquery->family; \ |
\ |
\ |
_gqfamily->num_nodes++; \ |
\ |
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \ |
\ |
if ( --_gqfamily->num_nodes == 0 ) \ |
FTC_FAMILY_FREE( _gqfamily, _gcache ); \ |
} \ |
FT_END_STMNT |
/* */ |
#else /* !FTC_INLINE */ |
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
gindex, query, node, error ) \ |
FT_BEGIN_STMNT \ |
\ |
error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \ |
FTC_GQUERY( query ), &node ); \ |
\ |
FT_END_STMNT |
#endif /* !FTC_INLINE */ |
FT_END_HEADER |
#endif /* __FTCGLYPH_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcimage.c |
---|
0,0 → 1,163 |
/***************************************************************************/ |
/* */ |
/* ftcimage.c */ |
/* */ |
/* FreeType Image cache (body). */ |
/* */ |
/* Copyright 2000-2001, 2003, 2004, 2006, 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_CACHE_H |
#include "ftcimage.h" |
#include FT_INTERNAL_MEMORY_H |
#include "ftccback.h" |
#include "ftcerror.h" |
/* finalize a given glyph image node */ |
FT_LOCAL_DEF( void ) |
ftc_inode_free( FTC_Node ftcinode, |
FTC_Cache cache ) |
{ |
FTC_INode inode = (FTC_INode)ftcinode; |
FT_Memory memory = cache->memory; |
if ( inode->glyph ) |
{ |
FT_Done_Glyph( inode->glyph ); |
inode->glyph = NULL; |
} |
FTC_GNode_Done( FTC_GNODE( inode ), cache ); |
FT_FREE( inode ); |
} |
FT_LOCAL_DEF( void ) |
FTC_INode_Free( FTC_INode inode, |
FTC_Cache cache ) |
{ |
ftc_inode_free( FTC_NODE( inode ), cache ); |
} |
/* initialize a new glyph image node */ |
FT_LOCAL_DEF( FT_Error ) |
FTC_INode_New( FTC_INode *pinode, |
FTC_GQuery gquery, |
FTC_Cache cache ) |
{ |
FT_Memory memory = cache->memory; |
FT_Error error; |
FTC_INode inode = NULL; |
if ( !FT_NEW( inode ) ) |
{ |
FTC_GNode gnode = FTC_GNODE( inode ); |
FTC_Family family = gquery->family; |
FT_UInt gindex = gquery->gindex; |
FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache ); |
/* initialize its inner fields */ |
FTC_GNode_Init( gnode, gindex, family ); |
/* we will now load the glyph image */ |
error = clazz->family_load_glyph( family, gindex, cache, |
&inode->glyph ); |
if ( error ) |
{ |
FTC_INode_Free( inode, cache ); |
inode = NULL; |
} |
} |
*pinode = inode; |
return error; |
} |
FT_LOCAL_DEF( FT_Error ) |
ftc_inode_new( FTC_Node *ftcpinode, |
FT_Pointer ftcgquery, |
FTC_Cache cache ) |
{ |
FTC_INode *pinode = (FTC_INode*)ftcpinode; |
FTC_GQuery gquery = (FTC_GQuery)ftcgquery; |
return FTC_INode_New( pinode, gquery, cache ); |
} |
FT_LOCAL_DEF( FT_Offset ) |
ftc_inode_weight( FTC_Node ftcinode, |
FTC_Cache ftccache ) |
{ |
FTC_INode inode = (FTC_INode)ftcinode; |
FT_Offset size = 0; |
FT_Glyph glyph = inode->glyph; |
FT_UNUSED( ftccache ); |
switch ( glyph->format ) |
{ |
case FT_GLYPH_FORMAT_BITMAP: |
{ |
FT_BitmapGlyph bitg; |
bitg = (FT_BitmapGlyph)glyph; |
size = bitg->bitmap.rows * ft_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 ( *inode ); |
return size; |
} |
#if 0 |
FT_LOCAL_DEF( FT_Offset ) |
FTC_INode_Weight( FTC_INode inode ) |
{ |
return ftc_inode_weight( FTC_NODE( inode ), NULL ); |
} |
#endif /* 0 */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcimage.h |
---|
0,0 → 1,107 |
/***************************************************************************/ |
/* */ |
/* ftcimage.h */ |
/* */ |
/* FreeType Generic Image cache (specification) */ |
/* */ |
/* Copyright 2000-2001, 2002, 2003, 2006 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. */ |
/* */ |
/***************************************************************************/ |
/* |
* FTC_ICache is an _abstract_ cache used to store a single FT_Glyph |
* image per cache node. |
* |
* FTC_ICache extends FTC_GCache. For an implementation example, |
* see FTC_ImageCache in `src/cache/ftbasic.c'. |
*/ |
/*************************************************************************/ |
/* */ |
/* Each image cache really manages FT_Glyph objects. */ |
/* */ |
/*************************************************************************/ |
#ifndef __FTCIMAGE_H__ |
#define __FTCIMAGE_H__ |
#include <ft2build.h> |
#include FT_CACHE_H |
#include "ftcglyph.h" |
FT_BEGIN_HEADER |
/* the FT_Glyph image node type - we store only 1 glyph per node */ |
typedef struct FTC_INodeRec_ |
{ |
FTC_GNodeRec gnode; |
FT_Glyph glyph; |
} FTC_INodeRec, *FTC_INode; |
#define FTC_INODE( x ) ( (FTC_INode)( x ) ) |
#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex |
#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family |
typedef FT_Error |
(*FTC_IFamily_LoadGlyphFunc)( FTC_Family family, |
FT_UInt gindex, |
FTC_Cache cache, |
FT_Glyph *aglyph ); |
typedef struct FTC_IFamilyClassRec_ |
{ |
FTC_MruListClassRec clazz; |
FTC_IFamily_LoadGlyphFunc family_load_glyph; |
} FTC_IFamilyClassRec; |
typedef const FTC_IFamilyClassRec* FTC_IFamilyClass; |
#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x)) |
#define FTC_CACHE__IFAMILY_CLASS( x ) \ |
FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class ) |
/* can be used as a @FTC_Node_FreeFunc */ |
FT_LOCAL( void ) |
FTC_INode_Free( FTC_INode inode, |
FTC_Cache cache ); |
/* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family' |
* must be set correctly. This function will call the `family_load_glyph' |
* method to load the FT_Glyph into the cache node. |
*/ |
FT_LOCAL( FT_Error ) |
FTC_INode_New( FTC_INode *pinode, |
FTC_GQuery gquery, |
FTC_Cache cache ); |
#if 0 |
/* can be used as @FTC_Node_WeightFunc */ |
FT_LOCAL( FT_ULong ) |
FTC_INode_Weight( FTC_INode inode ); |
#endif |
/* */ |
FT_END_HEADER |
#endif /* __FTCIMAGE_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcmanag.c |
---|
0,0 → 1,693 |
/***************************************************************************/ |
/* */ |
/* ftcmanag.c */ |
/* */ |
/* FreeType Cache Manager (body). */ |
/* */ |
/* Copyright 2000-2006, 2008-2010, 2013 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 "ftcmanag.h" |
#include FT_INTERNAL_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include FT_SIZES_H |
#include "ftccback.h" |
#include "ftcerror.h" |
#ifdef FT_CONFIG_OPTION_PIC |
#error "cache system does not support PIC yet" |
#endif |
#undef FT_COMPONENT |
#define FT_COMPONENT trace_cache |
#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data ) |
static FT_Error |
ftc_scaler_lookup_size( FTC_Manager manager, |
FTC_Scaler scaler, |
FT_Size *asize ) |
{ |
FT_Face face; |
FT_Size size = NULL; |
FT_Error error; |
error = FTC_Manager_LookupFace( manager, scaler->face_id, &face ); |
if ( error ) |
goto Exit; |
error = FT_New_Size( face, &size ); |
if ( error ) |
goto Exit; |
FT_Activate_Size( size ); |
if ( scaler->pixel ) |
error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height ); |
else |
error = FT_Set_Char_Size( face, scaler->width, scaler->height, |
scaler->x_res, scaler->y_res ); |
if ( error ) |
{ |
FT_Done_Size( size ); |
size = NULL; |
} |
Exit: |
*asize = size; |
return error; |
} |
typedef struct FTC_SizeNodeRec_ |
{ |
FTC_MruNodeRec node; |
FT_Size size; |
FTC_ScalerRec scaler; |
} FTC_SizeNodeRec, *FTC_SizeNode; |
#define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) ) |
FT_CALLBACK_DEF( void ) |
ftc_size_node_done( FTC_MruNode ftcnode, |
FT_Pointer data ) |
{ |
FTC_SizeNode node = (FTC_SizeNode)ftcnode; |
FT_Size size = node->size; |
FT_UNUSED( data ); |
if ( size ) |
FT_Done_Size( size ); |
} |
FT_CALLBACK_DEF( FT_Bool ) |
ftc_size_node_compare( FTC_MruNode ftcnode, |
FT_Pointer ftcscaler ) |
{ |
FTC_SizeNode node = (FTC_SizeNode)ftcnode; |
FTC_Scaler scaler = (FTC_Scaler)ftcscaler; |
FTC_Scaler scaler0 = &node->scaler; |
if ( FTC_SCALER_COMPARE( scaler0, scaler ) ) |
{ |
FT_Activate_Size( node->size ); |
return 1; |
} |
return 0; |
} |
FT_CALLBACK_DEF( FT_Error ) |
ftc_size_node_init( FTC_MruNode ftcnode, |
FT_Pointer ftcscaler, |
FT_Pointer ftcmanager ) |
{ |
FTC_SizeNode node = (FTC_SizeNode)ftcnode; |
FTC_Scaler scaler = (FTC_Scaler)ftcscaler; |
FTC_Manager manager = (FTC_Manager)ftcmanager; |
node->scaler = scaler[0]; |
return ftc_scaler_lookup_size( manager, scaler, &node->size ); |
} |
FT_CALLBACK_DEF( FT_Error ) |
ftc_size_node_reset( FTC_MruNode ftcnode, |
FT_Pointer ftcscaler, |
FT_Pointer ftcmanager ) |
{ |
FTC_SizeNode node = (FTC_SizeNode)ftcnode; |
FTC_Scaler scaler = (FTC_Scaler)ftcscaler; |
FTC_Manager manager = (FTC_Manager)ftcmanager; |
FT_Done_Size( node->size ); |
node->scaler = scaler[0]; |
return ftc_scaler_lookup_size( manager, scaler, &node->size ); |
} |
FT_CALLBACK_TABLE_DEF |
const FTC_MruListClassRec ftc_size_list_class = |
{ |
sizeof ( FTC_SizeNodeRec ), |
ftc_size_node_compare, |
ftc_size_node_init, |
ftc_size_node_reset, |
ftc_size_node_done |
}; |
/* helper function used by ftc_face_node_done */ |
static FT_Bool |
ftc_size_node_compare_faceid( FTC_MruNode ftcnode, |
FT_Pointer ftcface_id ) |
{ |
FTC_SizeNode node = (FTC_SizeNode)ftcnode; |
FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
return FT_BOOL( node->scaler.face_id == face_id ); |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_Manager_LookupSize( FTC_Manager manager, |
FTC_Scaler scaler, |
FT_Size *asize ) |
{ |
FT_Error error; |
FTC_MruNode mrunode; |
if ( asize == NULL ) |
return FT_THROW( Invalid_Argument ); |
*asize = NULL; |
if ( !manager ) |
return FT_THROW( Invalid_Cache_Handle ); |
#ifdef FTC_INLINE |
FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare, |
mrunode, error ); |
#else |
error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode ); |
#endif |
if ( !error ) |
*asize = FTC_SIZE_NODE( mrunode )->size; |
return error; |
} |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** FACE MRU IMPLEMENTATION *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
typedef struct FTC_FaceNodeRec_ |
{ |
FTC_MruNodeRec node; |
FTC_FaceID face_id; |
FT_Face face; |
} FTC_FaceNodeRec, *FTC_FaceNode; |
#define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) ) |
FT_CALLBACK_DEF( FT_Error ) |
ftc_face_node_init( FTC_MruNode ftcnode, |
FT_Pointer ftcface_id, |
FT_Pointer ftcmanager ) |
{ |
FTC_FaceNode node = (FTC_FaceNode)ftcnode; |
FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
FTC_Manager manager = (FTC_Manager)ftcmanager; |
FT_Error error; |
node->face_id = face_id; |
error = manager->request_face( face_id, |
manager->library, |
manager->request_data, |
&node->face ); |
if ( !error ) |
{ |
/* destroy initial size object; it will be re-created later */ |
if ( node->face->size ) |
FT_Done_Size( node->face->size ); |
} |
return error; |
} |
FT_CALLBACK_DEF( void ) |
ftc_face_node_done( FTC_MruNode ftcnode, |
FT_Pointer ftcmanager ) |
{ |
FTC_FaceNode node = (FTC_FaceNode)ftcnode; |
FTC_Manager manager = (FTC_Manager)ftcmanager; |
/* we must begin by removing all scalers for the target face */ |
/* from the manager's list */ |
FTC_MruList_RemoveSelection( &manager->sizes, |
ftc_size_node_compare_faceid, |
node->face_id ); |
/* all right, we can discard the face now */ |
FT_Done_Face( node->face ); |
node->face = NULL; |
node->face_id = NULL; |
} |
FT_CALLBACK_DEF( FT_Bool ) |
ftc_face_node_compare( FTC_MruNode ftcnode, |
FT_Pointer ftcface_id ) |
{ |
FTC_FaceNode node = (FTC_FaceNode)ftcnode; |
FTC_FaceID face_id = (FTC_FaceID)ftcface_id; |
return FT_BOOL( node->face_id == face_id ); |
} |
FT_CALLBACK_TABLE_DEF |
const FTC_MruListClassRec ftc_face_list_class = |
{ |
sizeof ( FTC_FaceNodeRec), |
ftc_face_node_compare, |
ftc_face_node_init, |
0, /* FTC_MruNode_ResetFunc */ |
ftc_face_node_done |
}; |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( FT_Error ) |
FTC_Manager_LookupFace( FTC_Manager manager, |
FTC_FaceID face_id, |
FT_Face *aface ) |
{ |
FT_Error error; |
FTC_MruNode mrunode; |
if ( aface == NULL ) |
return FT_THROW( Invalid_Argument ); |
*aface = NULL; |
if ( !manager ) |
return FT_THROW( Invalid_Cache_Handle ); |
/* we break encapsulation for the sake of speed */ |
#ifdef FTC_INLINE |
FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare, |
mrunode, error ); |
#else |
error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode ); |
#endif |
if ( !error ) |
*aface = FTC_FACE_NODE( mrunode )->face; |
return error; |
} |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** 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 FT_THROW( 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; |
manager->library = library; |
manager->memory = memory; |
manager->max_weight = max_bytes; |
manager->request_face = requester; |
manager->request_data = req_data; |
FTC_MruList_Init( &manager->faces, |
&ftc_face_list_class, |
max_faces, |
manager, |
memory ); |
FTC_MruList_Init( &manager->sizes, |
&ftc_size_list_class, |
max_sizes, |
manager, |
memory ); |
*amanager = manager; |
Exit: |
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->memory; |
/* now discard all caches */ |
for (idx = manager->num_caches; idx-- > 0; ) |
{ |
FTC_Cache cache = manager->caches[idx]; |
if ( cache ) |
{ |
cache->clazz.cache_done( cache ); |
FT_FREE( cache ); |
manager->caches[idx] = NULL; |
} |
} |
manager->num_caches = 0; |
/* discard faces and sizes */ |
FTC_MruList_Done( &manager->sizes ); |
FTC_MruList_Done( &manager->faces ); |
manager->library = NULL; |
manager->memory = NULL; |
FT_FREE( manager ); |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( void ) |
FTC_Manager_Reset( FTC_Manager manager ) |
{ |
if ( manager ) |
{ |
FTC_MruList_Reset( &manager->sizes ); |
FTC_MruList_Reset( &manager->faces ); |
} |
FTC_Manager_FlushN( manager, manager->num_nodes ); |
} |
#ifdef FT_DEBUG_ERROR |
static void |
FTC_Manager_Check( FTC_Manager manager ) |
{ |
FTC_Node node, first; |
first = manager->nodes_list; |
/* check node weights */ |
if ( first ) |
{ |
FT_Offset weight = 0; |
node = first; |
do |
{ |
FTC_Cache cache = manager->caches[node->cache_index]; |
if ( (FT_UInt)node->cache_index >= manager->num_caches ) |
FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n", |
node->cache_index )); |
else |
weight += cache->clazz.node_weight( node, cache ); |
node = FTC_NODE__NEXT( node ); |
} while ( node != first ); |
if ( weight != manager->cur_weight ) |
FT_TRACE0(( "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 = FTC_NODE__NEXT( node ); |
} while ( node != first ); |
if ( count != manager->num_nodes ) |
FT_TRACE0(( "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_LOCAL_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_TRACE0(( "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 = FTC_NODE__PREV( first ); |
do |
{ |
FTC_Node prev; |
prev = ( node == first ) ? NULL : FTC_NODE__PREV( node ); |
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_LOCAL_DEF( FT_Error ) |
FTC_Manager_RegisterCache( FTC_Manager manager, |
FTC_CacheClass clazz, |
FTC_Cache *acache ) |
{ |
FT_Error error = FT_ERR( Invalid_Argument ); |
FTC_Cache cache = NULL; |
if ( manager && clazz && acache ) |
{ |
FT_Memory memory = manager->memory; |
if ( manager->num_caches >= FTC_MAX_CACHES ) |
{ |
error = FT_THROW( Too_Many_Caches ); |
FT_ERROR(( "FTC_Manager_RegisterCache:" |
" too many registered caches\n" )); |
goto Exit; |
} |
if ( !FT_ALLOC( cache, clazz->cache_size ) ) |
{ |
cache->manager = manager; |
cache->memory = memory; |
cache->clazz = clazz[0]; |
cache->org_class = clazz; |
/* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */ |
/* IF IT IS NOT SET CORRECTLY */ |
cache->index = manager->num_caches; |
error = clazz->cache_init( cache ); |
if ( error ) |
{ |
clazz->cache_done( cache ); |
FT_FREE( cache ); |
goto Exit; |
} |
manager->caches[manager->num_caches++] = cache; |
} |
} |
Exit: |
if ( acache ) |
*acache = cache; |
return error; |
} |
FT_LOCAL_DEF( FT_UInt ) |
FTC_Manager_FlushN( FTC_Manager manager, |
FT_UInt count ) |
{ |
FTC_Node first = manager->nodes_list; |
FTC_Node node; |
FT_UInt result; |
/* try to remove `count' nodes from the list */ |
if ( first == NULL ) /* empty list! */ |
return 0; |
/* go to last node - it's a circular list */ |
node = FTC_NODE__PREV(first); |
for ( result = 0; result < count; ) |
{ |
FTC_Node prev = FTC_NODE__PREV( node ); |
/* don't touch locked nodes */ |
if ( node->ref_count <= 0 ) |
{ |
ftc_node_destroy( node, manager ); |
result++; |
} |
if ( node == first ) |
break; |
node = prev; |
} |
return result; |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( void ) |
FTC_Manager_RemoveFaceID( FTC_Manager manager, |
FTC_FaceID face_id ) |
{ |
FT_UInt nn; |
/* this will remove all FTC_SizeNode that correspond to |
* the face_id as well |
*/ |
FTC_MruList_RemoveSelection( &manager->faces, |
ftc_face_node_compare, |
face_id ); |
for ( nn = 0; nn < manager->num_caches; nn++ ) |
FTC_Cache_RemoveFaceID( manager->caches[nn], face_id ); |
} |
/* documentation is in ftcache.h */ |
FT_EXPORT_DEF( void ) |
FTC_Node_Unref( FTC_Node node, |
FTC_Manager manager ) |
{ |
if ( node && (FT_UInt)node->cache_index < manager->num_caches ) |
node->ref_count--; |
} |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcmanag.h |
---|
0,0 → 1,175 |
/***************************************************************************/ |
/* */ |
/* ftcmanag.h */ |
/* */ |
/* FreeType Cache Manager (specification). */ |
/* */ |
/* Copyright 2000-2001, 2003, 2004, 2006, 2010, 2013 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. */ |
/* */ |
/***************************************************************************/ |
/*************************************************************************/ |
/* */ |
/* A cache manager is in charge of the following: */ |
/* */ |
/* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face */ |
/* objects. The mapping itself is performed through a user-provided */ |
/* callback. However, the manager maintains a small cache of FT_Face */ |
/* and FT_Size objects in order to speed up things considerably. */ |
/* */ |
/* - Manage one or more cache objects. Each cache is in charge of */ |
/* holding a varying number of `cache nodes'. Each cache node */ |
/* represents a minimal amount of individually accessible cached */ |
/* data. For example, a cache node can be an FT_Glyph image */ |
/* containing a vector outline, or some glyph metrics, or anything */ |
/* else. */ |
/* */ |
/* Each cache node has a certain size in bytes that is added to the */ |
/* total amount of `cache memory' within the manager. */ |
/* */ |
/* All cache nodes are located in a global LRU list, where the oldest */ |
/* node is at the tail of the list. */ |
/* */ |
/* Each node belongs to a single cache, and includes a reference */ |
/* count to avoid destroying it (due to caching). */ |
/* */ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/********* *********/ |
/********* WARNING, THIS IS BETA CODE. *********/ |
/********* *********/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
/*************************************************************************/ |
#ifndef __FTCMANAG_H__ |
#define __FTCMANAG_H__ |
#include <ft2build.h> |
#include FT_CACHE_H |
#include "ftcmru.h" |
#include "ftccache.h" |
FT_BEGIN_HEADER |
/*************************************************************************/ |
/* */ |
/* <Section> */ |
/* cache_subsystem */ |
/* */ |
/*************************************************************************/ |
#define FTC_MAX_FACES_DEFAULT 2 |
#define FTC_MAX_SIZES_DEFAULT 4 |
#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */ |
/* maximum number of caches registered in a single manager */ |
#define FTC_MAX_CACHES 16 |
typedef struct FTC_ManagerRec_ |
{ |
FT_Library library; |
FT_Memory memory; |
FTC_Node nodes_list; |
FT_Offset max_weight; |
FT_Offset cur_weight; |
FT_UInt num_nodes; |
FTC_Cache caches[FTC_MAX_CACHES]; |
FT_UInt num_caches; |
FTC_MruListRec faces; |
FTC_MruListRec sizes; |
FT_Pointer request_data; |
FTC_Face_Requester request_face; |
} FTC_ManagerRec; |
/*************************************************************************/ |
/* */ |
/* <Function> */ |
/* FTC_Manager_Compress */ |
/* */ |
/* <Description> */ |
/* This function is used to check the state of the cache manager if */ |
/* its `num_bytes' field is greater than its `max_bytes' field. It */ |
/* will flush as many old cache nodes as possible (ignoring cache */ |
/* nodes with a non-zero reference count). */ |
/* */ |
/* <InOut> */ |
/* manager :: A handle to the cache manager. */ |
/* */ |
/* <Note> */ |
/* Client applications should not call this function directly. It is */ |
/* normally invoked by specific cache implementations. */ |
/* */ |
/* The reason this function is exported is to allow client-specific */ |
/* cache classes. */ |
/* */ |
FT_LOCAL( void ) |
FTC_Manager_Compress( FTC_Manager manager ); |
/* try to flush `count' old nodes from the cache; return the number |
* of really flushed nodes |
*/ |
FT_LOCAL( FT_UInt ) |
FTC_Manager_FlushN( FTC_Manager manager, |
FT_UInt count ); |
/* this must be used internally for the moment */ |
FT_LOCAL( FT_Error ) |
FTC_Manager_RegisterCache( FTC_Manager manager, |
FTC_CacheClass clazz, |
FTC_Cache *acache ); |
/* */ |
#define FTC_SCALER_COMPARE( a, b ) \ |
( (a)->face_id == (b)->face_id && \ |
(a)->width == (b)->width && \ |
(a)->height == (b)->height && \ |
((a)->pixel != 0) == ((b)->pixel != 0) && \ |
( (a)->pixel || \ |
( (a)->x_res == (b)->x_res && \ |
(a)->y_res == (b)->y_res ) ) ) |
#define FTC_SCALER_HASH( q ) \ |
( _FTC_FACE_ID_HASH( (q)->face_id ) + \ |
(q)->width + (q)->height*7 + \ |
( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) ) |
/* */ |
FT_END_HEADER |
#endif /* __FTCMANAG_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcmru.c |
---|
0,0 → 1,357 |
/***************************************************************************/ |
/* */ |
/* ftcmru.c */ |
/* */ |
/* FreeType MRU support (body). */ |
/* */ |
/* Copyright 2003, 2004, 2006, 2009 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 "ftcmru.h" |
#include FT_INTERNAL_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include "ftcerror.h" |
FT_LOCAL_DEF( void ) |
FTC_MruNode_Prepend( FTC_MruNode *plist, |
FTC_MruNode node ) |
{ |
FTC_MruNode first = *plist; |
if ( first ) |
{ |
FTC_MruNode last = first->prev; |
#ifdef FT_DEBUG_ERROR |
{ |
FTC_MruNode cnode = first; |
do |
{ |
if ( cnode == node ) |
{ |
fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" ); |
exit( 2 ); |
} |
cnode = cnode->next; |
} while ( cnode != first ); |
} |
#endif |
first->prev = node; |
last->next = node; |
node->next = first; |
node->prev = last; |
} |
else |
{ |
node->next = node; |
node->prev = node; |
} |
*plist = node; |
} |
FT_LOCAL_DEF( void ) |
FTC_MruNode_Up( FTC_MruNode *plist, |
FTC_MruNode node ) |
{ |
FTC_MruNode first = *plist; |
FT_ASSERT( first != NULL ); |
if ( first != node ) |
{ |
FTC_MruNode prev, next, last; |
#ifdef FT_DEBUG_ERROR |
{ |
FTC_MruNode cnode = first; |
do |
{ |
if ( cnode == node ) |
goto Ok; |
cnode = cnode->next; |
} while ( cnode != first ); |
fprintf( stderr, "FTC_MruNode_Up: invalid action\n" ); |
exit( 2 ); |
Ok: |
} |
#endif |
prev = node->prev; |
next = node->next; |
prev->next = next; |
next->prev = prev; |
last = first->prev; |
last->next = node; |
first->prev = node; |
node->next = first; |
node->prev = last; |
*plist = node; |
} |
} |
FT_LOCAL_DEF( void ) |
FTC_MruNode_Remove( FTC_MruNode *plist, |
FTC_MruNode node ) |
{ |
FTC_MruNode first = *plist; |
FTC_MruNode prev, next; |
FT_ASSERT( first != NULL ); |
#ifdef FT_DEBUG_ERROR |
{ |
FTC_MruNode cnode = first; |
do |
{ |
if ( cnode == node ) |
goto Ok; |
cnode = cnode->next; |
} while ( cnode != first ); |
fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" ); |
exit( 2 ); |
Ok: |
} |
#endif |
prev = node->prev; |
next = node->next; |
prev->next = next; |
next->prev = prev; |
if ( node == next ) |
{ |
FT_ASSERT( first == node ); |
FT_ASSERT( prev == node ); |
*plist = NULL; |
} |
else if ( node == first ) |
*plist = next; |
} |
FT_LOCAL_DEF( void ) |
FTC_MruList_Init( FTC_MruList list, |
FTC_MruListClass clazz, |
FT_UInt max_nodes, |
FT_Pointer data, |
FT_Memory memory ) |
{ |
list->num_nodes = 0; |
list->max_nodes = max_nodes; |
list->nodes = NULL; |
list->clazz = *clazz; |
list->data = data; |
list->memory = memory; |
} |
FT_LOCAL_DEF( void ) |
FTC_MruList_Reset( FTC_MruList list ) |
{ |
while ( list->nodes ) |
FTC_MruList_Remove( list, list->nodes ); |
FT_ASSERT( list->num_nodes == 0 ); |
} |
FT_LOCAL_DEF( void ) |
FTC_MruList_Done( FTC_MruList list ) |
{ |
FTC_MruList_Reset( list ); |
} |
#ifndef FTC_INLINE |
FT_LOCAL_DEF( FTC_MruNode ) |
FTC_MruList_Find( FTC_MruList list, |
FT_Pointer key ) |
{ |
FTC_MruNode_CompareFunc compare = list->clazz.node_compare; |
FTC_MruNode first, node; |
first = list->nodes; |
node = NULL; |
if ( first ) |
{ |
node = first; |
do |
{ |
if ( compare( node, key ) ) |
{ |
if ( node != first ) |
FTC_MruNode_Up( &list->nodes, node ); |
return node; |
} |
node = node->next; |
} while ( node != first); |
} |
return NULL; |
} |
#endif |
FT_LOCAL_DEF( FT_Error ) |
FTC_MruList_New( FTC_MruList list, |
FT_Pointer key, |
FTC_MruNode *anode ) |
{ |
FT_Error error; |
FTC_MruNode node = NULL; |
FT_Memory memory = list->memory; |
if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 ) |
{ |
node = list->nodes->prev; |
FT_ASSERT( node ); |
if ( list->clazz.node_reset ) |
{ |
FTC_MruNode_Up( &list->nodes, node ); |
error = list->clazz.node_reset( node, key, list->data ); |
if ( !error ) |
goto Exit; |
} |
FTC_MruNode_Remove( &list->nodes, node ); |
list->num_nodes--; |
if ( list->clazz.node_done ) |
list->clazz.node_done( node, list->data ); |
} |
else if ( FT_ALLOC( node, list->clazz.node_size ) ) |
goto Exit; |
error = list->clazz.node_init( node, key, list->data ); |
if ( error ) |
goto Fail; |
FTC_MruNode_Prepend( &list->nodes, node ); |
list->num_nodes++; |
Exit: |
*anode = node; |
return error; |
Fail: |
if ( list->clazz.node_done ) |
list->clazz.node_done( node, list->data ); |
FT_FREE( node ); |
goto Exit; |
} |
#ifndef FTC_INLINE |
FT_LOCAL_DEF( FT_Error ) |
FTC_MruList_Lookup( FTC_MruList list, |
FT_Pointer key, |
FTC_MruNode *anode ) |
{ |
FTC_MruNode node; |
node = FTC_MruList_Find( list, key ); |
if ( node == NULL ) |
return FTC_MruList_New( list, key, anode ); |
*anode = node; |
return 0; |
} |
#endif /* FTC_INLINE */ |
FT_LOCAL_DEF( void ) |
FTC_MruList_Remove( FTC_MruList list, |
FTC_MruNode node ) |
{ |
FTC_MruNode_Remove( &list->nodes, node ); |
list->num_nodes--; |
{ |
FT_Memory memory = list->memory; |
if ( list->clazz.node_done ) |
list->clazz.node_done( node, list->data ); |
FT_FREE( node ); |
} |
} |
FT_LOCAL_DEF( void ) |
FTC_MruList_RemoveSelection( FTC_MruList list, |
FTC_MruNode_CompareFunc selection, |
FT_Pointer key ) |
{ |
FTC_MruNode first, node, next; |
first = list->nodes; |
while ( first && ( selection == NULL || selection( first, key ) ) ) |
{ |
FTC_MruList_Remove( list, first ); |
first = list->nodes; |
} |
if ( first ) |
{ |
node = first->next; |
while ( node != first ) |
{ |
next = node->next; |
if ( selection( node, key ) ) |
FTC_MruList_Remove( list, node ); |
node = next; |
} |
} |
} |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcmru.h |
---|
0,0 → 1,246 |
/***************************************************************************/ |
/* */ |
/* ftcmru.h */ |
/* */ |
/* Simple MRU list-cache (specification). */ |
/* */ |
/* Copyright 2000-2001, 2003-2006, 2010, 2013 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. */ |
/* */ |
/***************************************************************************/ |
/*************************************************************************/ |
/* */ |
/* An MRU is a list that cannot hold more than a certain number of */ |
/* elements (`max_elements'). All elements in the list are sorted in */ |
/* least-recently-used order, i.e., the `oldest' element is at the tail */ |
/* of the list. */ |
/* */ |
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */ |
/* the list is searched for an element with the corresponding key. If */ |
/* it is found, the element is moved to the head of the list and is */ |
/* returned. */ |
/* */ |
/* If no corresponding element is found, the lookup routine will try to */ |
/* obtain a new element with the relevant key. If the list is already */ |
/* full, the oldest element from the list is discarded and replaced by a */ |
/* new one; a new element is added to the list otherwise. */ |
/* */ |
/* Note that it is possible to pre-allocate the element list nodes. */ |
/* This is handy if `max_elements' is sufficiently small, as it saves */ |
/* allocations/releases during the lookup process. */ |
/* */ |
/*************************************************************************/ |
#ifndef __FTCMRU_H__ |
#define __FTCMRU_H__ |
#include <ft2build.h> |
#include FT_FREETYPE_H |
#ifdef FREETYPE_H |
#error "freetype.h of FreeType 1 has been loaded!" |
#error "Please fix the directory search order for header files" |
#error "so that freetype.h of FreeType 2 is found first." |
#endif |
#define xxFT_DEBUG_ERROR |
#define FTC_INLINE |
FT_BEGIN_HEADER |
typedef struct FTC_MruNodeRec_* FTC_MruNode; |
typedef struct FTC_MruNodeRec_ |
{ |
FTC_MruNode next; |
FTC_MruNode prev; |
} FTC_MruNodeRec; |
FT_LOCAL( void ) |
FTC_MruNode_Prepend( FTC_MruNode *plist, |
FTC_MruNode node ); |
FT_LOCAL( void ) |
FTC_MruNode_Up( FTC_MruNode *plist, |
FTC_MruNode node ); |
FT_LOCAL( void ) |
FTC_MruNode_Remove( FTC_MruNode *plist, |
FTC_MruNode node ); |
typedef struct FTC_MruListRec_* FTC_MruList; |
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass; |
typedef FT_Bool |
(*FTC_MruNode_CompareFunc)( FTC_MruNode node, |
FT_Pointer key ); |
typedef FT_Error |
(*FTC_MruNode_InitFunc)( FTC_MruNode node, |
FT_Pointer key, |
FT_Pointer data ); |
typedef FT_Error |
(*FTC_MruNode_ResetFunc)( FTC_MruNode node, |
FT_Pointer key, |
FT_Pointer data ); |
typedef void |
(*FTC_MruNode_DoneFunc)( FTC_MruNode node, |
FT_Pointer data ); |
typedef struct FTC_MruListClassRec_ |
{ |
FT_Offset node_size; |
FTC_MruNode_CompareFunc node_compare; |
FTC_MruNode_InitFunc node_init; |
FTC_MruNode_ResetFunc node_reset; |
FTC_MruNode_DoneFunc node_done; |
} FTC_MruListClassRec; |
typedef struct FTC_MruListRec_ |
{ |
FT_UInt num_nodes; |
FT_UInt max_nodes; |
FTC_MruNode nodes; |
FT_Pointer data; |
FTC_MruListClassRec clazz; |
FT_Memory memory; |
} FTC_MruListRec; |
FT_LOCAL( void ) |
FTC_MruList_Init( FTC_MruList list, |
FTC_MruListClass clazz, |
FT_UInt max_nodes, |
FT_Pointer data, |
FT_Memory memory ); |
FT_LOCAL( void ) |
FTC_MruList_Reset( FTC_MruList list ); |
FT_LOCAL( void ) |
FTC_MruList_Done( FTC_MruList list ); |
FT_LOCAL( FT_Error ) |
FTC_MruList_New( FTC_MruList list, |
FT_Pointer key, |
FTC_MruNode *anode ); |
FT_LOCAL( void ) |
FTC_MruList_Remove( FTC_MruList list, |
FTC_MruNode node ); |
FT_LOCAL( void ) |
FTC_MruList_RemoveSelection( FTC_MruList list, |
FTC_MruNode_CompareFunc selection, |
FT_Pointer key ); |
#ifdef FTC_INLINE |
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \ |
FT_BEGIN_STMNT \ |
FTC_MruNode* _pfirst = &(list)->nodes; \ |
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \ |
FTC_MruNode _first, _node; \ |
\ |
\ |
error = FT_Err_Ok; \ |
_first = *(_pfirst); \ |
_node = NULL; \ |
\ |
if ( _first ) \ |
{ \ |
_node = _first; \ |
do \ |
{ \ |
if ( _compare( _node, (key) ) ) \ |
{ \ |
if ( _node != _first ) \ |
FTC_MruNode_Up( _pfirst, _node ); \ |
\ |
node = _node; \ |
goto _MruOk; \ |
} \ |
_node = _node->next; \ |
\ |
} while ( _node != _first) ; \ |
} \ |
\ |
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \ |
_MruOk: \ |
; \ |
FT_END_STMNT |
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error ) |
#else /* !FTC_INLINE */ |
FT_LOCAL( FTC_MruNode ) |
FTC_MruList_Find( FTC_MruList list, |
FT_Pointer key ); |
FT_LOCAL( FT_Error ) |
FTC_MruList_Lookup( FTC_MruList list, |
FT_Pointer key, |
FTC_MruNode *pnode ); |
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) ) |
#endif /* !FTC_INLINE */ |
#define FTC_MRULIST_LOOP( list, node ) \ |
FT_BEGIN_STMNT \ |
FTC_MruNode _first = (list)->nodes; \ |
\ |
\ |
if ( _first ) \ |
{ \ |
FTC_MruNode _node = _first; \ |
\ |
\ |
do \ |
{ \ |
*(FTC_MruNode*)&(node) = _node; |
#define FTC_MRULIST_LOOP_END() \ |
_node = _node->next; \ |
\ |
} while ( _node != _first ); \ |
} \ |
FT_END_STMNT |
/* */ |
FT_END_HEADER |
#endif /* __FTCMRU_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcsbits.c |
---|
0,0 → 1,421 |
/***************************************************************************/ |
/* */ |
/* ftcsbits.c */ |
/* */ |
/* FreeType sbits manager (body). */ |
/* */ |
/* Copyright 2000-2006, 2009-2011, 2013 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 "ftcsbits.h" |
#include FT_INTERNAL_OBJECTS_H |
#include FT_INTERNAL_DEBUG_H |
#include FT_ERRORS_H |
#include "ftccback.h" |
#include "ftcerror.h" |
#undef FT_COMPONENT |
#define FT_COMPONENT trace_cache |
/*************************************************************************/ |
/*************************************************************************/ |
/***** *****/ |
/***** SBIT CACHE NODES *****/ |
/***** *****/ |
/*************************************************************************/ |
/*************************************************************************/ |
static FT_Error |
ftc_sbit_copy_bitmap( FTC_SBit sbit, |
FT_Bitmap* bitmap, |
FT_Memory memory ) |
{ |
FT_Error error; |
FT_Int pitch = bitmap->pitch; |
FT_ULong size; |
if ( pitch < 0 ) |
pitch = -pitch; |
size = (FT_ULong)( pitch * bitmap->rows ); |
if ( !FT_ALLOC( sbit->buffer, size ) ) |
FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); |
return error; |
} |
FT_LOCAL_DEF( void ) |
ftc_snode_free( FTC_Node ftcsnode, |
FTC_Cache cache ) |
{ |
FTC_SNode snode = (FTC_SNode)ftcsnode; |
FTC_SBit sbit = snode->sbits; |
FT_UInt count = snode->count; |
FT_Memory memory = cache->memory; |
for ( ; count > 0; sbit++, count-- ) |
FT_FREE( sbit->buffer ); |
FTC_GNode_Done( FTC_GNODE( snode ), cache ); |
FT_FREE( snode ); |
} |
FT_LOCAL_DEF( void ) |
FTC_SNode_Free( FTC_SNode snode, |
FTC_Cache cache ) |
{ |
ftc_snode_free( FTC_NODE( snode ), cache ); |
} |
/* |
* This function tries to load a small bitmap within a given FTC_SNode. |
* Note that it returns a non-zero error code _only_ in the case of |
* out-of-memory condition. For all other errors (e.g., corresponding |
* to a bad font file), this function will mark the sbit as `unavailable' |
* and return a value of 0. |
* |
* You should also read the comment within the @ftc_snode_compare |
* function below to see how out-of-memory is handled during a lookup. |
*/ |
static FT_Error |
ftc_snode_load( FTC_SNode snode, |
FTC_Manager manager, |
FT_UInt gindex, |
FT_ULong *asize ) |
{ |
FT_Error error; |
FTC_GNode gnode = FTC_GNODE( snode ); |
FTC_Family family = gnode->family; |
FT_Memory memory = manager->memory; |
FT_Face face; |
FTC_SBit sbit; |
FTC_SFamilyClass clazz; |
if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count ) |
{ |
FT_ERROR(( "ftc_snode_load: invalid glyph index" )); |
return FT_THROW( Invalid_Argument ); |
} |
sbit = snode->sbits + ( gindex - gnode->gindex ); |
clazz = (FTC_SFamilyClass)family->clazz; |
sbit->buffer = 0; |
error = clazz->family_load_glyph( family, gindex, manager, &face ); |
if ( error ) |
goto BadGlyph; |
{ |
FT_Int temp; |
FT_GlyphSlot slot = face->glyph; |
FT_Bitmap* bitmap = &slot->bitmap; |
FT_Pos xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */ |
if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) |
{ |
FT_TRACE0(( "ftc_snode_load:" |
" glyph loaded didn't return a bitmap\n" )); |
goto BadGlyph; |
} |
/* Check that our values fit into 8-bit containers! */ |
/* If this is not the case, our bitmap is too large */ |
/* and we will leave it as `missing' with sbit.buffer = 0 */ |
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) |
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) |
/* horizontal advance in pixels */ |
xadvance = ( slot->advance.x + 32 ) >> 6; |
yadvance = ( slot->advance.y + 32 ) >> 6; |
if ( !CHECK_BYTE( bitmap->rows ) || |
!CHECK_BYTE( bitmap->width ) || |
!CHECK_CHAR( bitmap->pitch ) || |
!CHECK_CHAR( slot->bitmap_left ) || |
!CHECK_CHAR( slot->bitmap_top ) || |
!CHECK_CHAR( xadvance ) || |
!CHECK_CHAR( yadvance ) ) |
{ |
FT_TRACE2(( "ftc_snode_load:" |
" glyph too large for small bitmap cache\n")); |
goto BadGlyph; |
} |
sbit->width = (FT_Byte)bitmap->width; |
sbit->height = (FT_Byte)bitmap->rows; |
sbit->pitch = (FT_Char)bitmap->pitch; |
sbit->left = (FT_Char)slot->bitmap_left; |
sbit->top = (FT_Char)slot->bitmap_top; |
sbit->xadvance = (FT_Char)xadvance; |
sbit->yadvance = (FT_Char)yadvance; |
sbit->format = (FT_Byte)bitmap->pixel_mode; |
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); |
/* copy the bitmap into a new buffer -- ignore error */ |
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); |
/* now, compute size */ |
if ( asize ) |
*asize = FT_ABS( sbit->pitch ) * sbit->height; |
} /* glyph loading successful */ |
/* ignore the errors that might have occurred -- */ |
/* we mark unloaded glyphs with `sbit.buffer == 0' */ |
/* and `width == 255', `height == 0' */ |
/* */ |
if ( error && FT_ERR_NEQ( error, Out_Of_Memory ) ) |
{ |
BadGlyph: |
sbit->width = 255; |
sbit->height = 0; |
sbit->buffer = NULL; |
error = FT_Err_Ok; |
if ( asize ) |
*asize = 0; |
} |
return error; |
} |
FT_LOCAL_DEF( FT_Error ) |
FTC_SNode_New( FTC_SNode *psnode, |
FTC_GQuery gquery, |
FTC_Cache cache ) |
{ |
FT_Memory memory = cache->memory; |
FT_Error error; |
FTC_SNode snode = NULL; |
FT_UInt gindex = gquery->gindex; |
FTC_Family family = gquery->family; |
FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache ); |
FT_UInt total; |
FT_UInt node_count; |
total = clazz->family_get_count( family, cache->manager ); |
if ( total == 0 || gindex >= total ) |
{ |
error = FT_THROW( Invalid_Argument ); |
goto Exit; |
} |
if ( !FT_NEW( snode ) ) |
{ |
FT_UInt count, start; |
start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE ); |
count = total - start; |
if ( count > FTC_SBIT_ITEMS_PER_NODE ) |
count = FTC_SBIT_ITEMS_PER_NODE; |
FTC_GNode_Init( FTC_GNODE( snode ), start, family ); |
snode->count = count; |
for ( node_count = 0; node_count < count; node_count++ ) |
{ |
snode->sbits[node_count].width = 255; |
} |
error = ftc_snode_load( snode, |
cache->manager, |
gindex, |
NULL ); |
if ( error ) |
{ |
FTC_SNode_Free( snode, cache ); |
snode = NULL; |
} |
} |
Exit: |
*psnode = snode; |
return error; |
} |
FT_LOCAL_DEF( FT_Error ) |
ftc_snode_new( FTC_Node *ftcpsnode, |
FT_Pointer ftcgquery, |
FTC_Cache cache ) |
{ |
FTC_SNode *psnode = (FTC_SNode*)ftcpsnode; |
FTC_GQuery gquery = (FTC_GQuery)ftcgquery; |
return FTC_SNode_New( psnode, gquery, cache ); |
} |
FT_LOCAL_DEF( FT_Offset ) |
ftc_snode_weight( FTC_Node ftcsnode, |
FTC_Cache cache ) |
{ |
FTC_SNode snode = (FTC_SNode)ftcsnode; |
FT_UInt count = snode->count; |
FTC_SBit sbit = snode->sbits; |
FT_Int pitch; |
FT_Offset size; |
FT_UNUSED( cache ); |
FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE ); |
/* the node itself */ |
size = sizeof ( *snode ); |
for ( ; count > 0; count--, sbit++ ) |
{ |
if ( sbit->buffer ) |
{ |
pitch = sbit->pitch; |
if ( pitch < 0 ) |
pitch = -pitch; |
/* add the size of a given glyph image */ |
size += pitch * sbit->height; |
} |
} |
return size; |
} |
#if 0 |
FT_LOCAL_DEF( FT_Offset ) |
FTC_SNode_Weight( FTC_SNode snode ) |
{ |
return ftc_snode_weight( FTC_NODE( snode ), NULL ); |
} |
#endif /* 0 */ |
FT_LOCAL_DEF( FT_Bool ) |
ftc_snode_compare( FTC_Node ftcsnode, |
FT_Pointer ftcgquery, |
FTC_Cache cache, |
FT_Bool* list_changed ) |
{ |
FTC_SNode snode = (FTC_SNode)ftcsnode; |
FTC_GQuery gquery = (FTC_GQuery)ftcgquery; |
FTC_GNode gnode = FTC_GNODE( snode ); |
FT_UInt gindex = gquery->gindex; |
FT_Bool result; |
if (list_changed) |
*list_changed = FALSE; |
result = FT_BOOL( gnode->family == gquery->family && |
(FT_UInt)( gindex - gnode->gindex ) < snode->count ); |
if ( result ) |
{ |
/* check if we need to load the glyph bitmap now */ |
FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex ); |
/* |
* The following code illustrates what to do when you want to |
* perform operations that may fail within a lookup function. |
* |
* Here, we want to load a small bitmap on-demand; we thus |
* need to call the `ftc_snode_load' function which may return |
* a non-zero error code only when we are out of memory (OOM). |
* |
* The correct thing to do is to use @FTC_CACHE_TRYLOOP and |
* @FTC_CACHE_TRYLOOP_END in order to implement a retry loop |
* that is capable of flushing the cache incrementally when |
* an OOM errors occur. |
* |
* However, we need to `lock' the node before this operation to |
* prevent it from being flushed within the loop. |
* |
* When we exit the loop, we unlock the node, then check the `error' |
* variable. If it is non-zero, this means that the cache was |
* completely flushed and that no usable memory was found to load |
* the bitmap. |
* |
* We then prefer to return a value of 0 (i.e., NO MATCH). This |
* ensures that the caller will try to allocate a new node. |
* This operation consequently _fail_ and the lookup function |
* returns the appropriate OOM error code. |
* |
* Note that `buffer == NULL && width == 255' is a hack used to |
* tag `unavailable' bitmaps in the array. We should never try |
* to load these. |
* |
*/ |
if ( sbit->buffer == NULL && sbit->width == 255 ) |
{ |
FT_ULong size; |
FT_Error error; |
ftcsnode->ref_count++; /* lock node to prevent flushing */ |
/* in retry loop */ |
FTC_CACHE_TRYLOOP( cache ) |
{ |
error = ftc_snode_load( snode, cache->manager, gindex, &size ); |
} |
FTC_CACHE_TRYLOOP_END( list_changed ); |
ftcsnode->ref_count--; /* unlock the node */ |
if ( error ) |
result = 0; |
else |
cache->manager->cur_weight += size; |
} |
} |
return result; |
} |
#ifdef FTC_INLINE |
FT_LOCAL_DEF( FT_Bool ) |
FTC_SNode_Compare( FTC_SNode snode, |
FTC_GQuery gquery, |
FTC_Cache cache, |
FT_Bool* list_changed ) |
{ |
return ftc_snode_compare( FTC_NODE( snode ), gquery, |
cache, list_changed ); |
} |
#endif |
/* END */ |
/programs/develop/libraries/freetype/src/cache/ftcsbits.h |
---|
0,0 → 1,103 |
/***************************************************************************/ |
/* */ |
/* ftcsbits.h */ |
/* */ |
/* A small-bitmap cache (specification). */ |
/* */ |
/* Copyright 2000-2001, 2002, 2003, 2006, 2011 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 <ft2build.h> |
#include FT_CACHE_H |
#include "ftcglyph.h" |
FT_BEGIN_HEADER |
#define FTC_SBIT_ITEMS_PER_NODE 16 |
typedef struct FTC_SNodeRec_ |
{ |
FTC_GNodeRec gnode; |
FT_UInt count; |
FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE]; |
} FTC_SNodeRec, *FTC_SNode; |
#define FTC_SNODE( x ) ( (FTC_SNode)( x ) ) |
#define FTC_SNODE_GINDEX( x ) FTC_GNODE( x )->gindex |
#define FTC_SNODE_FAMILY( x ) FTC_GNODE( x )->family |
typedef FT_UInt |
(*FTC_SFamily_GetCountFunc)( FTC_Family family, |
FTC_Manager manager ); |
typedef FT_Error |
(*FTC_SFamily_LoadGlyphFunc)( FTC_Family family, |
FT_UInt gindex, |
FTC_Manager manager, |
FT_Face *aface ); |
typedef struct FTC_SFamilyClassRec_ |
{ |
FTC_MruListClassRec clazz; |
FTC_SFamily_GetCountFunc family_get_count; |
FTC_SFamily_LoadGlyphFunc family_load_glyph; |
} FTC_SFamilyClassRec; |
typedef const FTC_SFamilyClassRec* FTC_SFamilyClass; |
#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x)) |
#define FTC_CACHE__SFAMILY_CLASS( x ) \ |
FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS( x )->family_class ) |
FT_LOCAL( void ) |
FTC_SNode_Free( FTC_SNode snode, |
FTC_Cache cache ); |
FT_LOCAL( FT_Error ) |
FTC_SNode_New( FTC_SNode *psnode, |
FTC_GQuery gquery, |
FTC_Cache cache ); |
#if 0 |
FT_LOCAL( FT_ULong ) |
FTC_SNode_Weight( FTC_SNode inode ); |
#endif |
#ifdef FTC_INLINE |
FT_LOCAL( FT_Bool ) |
FTC_SNode_Compare( FTC_SNode snode, |
FTC_GQuery gquery, |
FTC_Cache cache, |
FT_Bool* list_changed); |
#endif |
/* */ |
FT_END_HEADER |
#endif /* __FTCSBITS_H__ */ |
/* END */ |
/programs/develop/libraries/freetype/src/cache/rules.mk |
---|
0,0 → 1,80 |
# |
# FreeType 2 Cache configuration rules |
# |
# Copyright 2000, 2001, 2003, 2004, 2006, 2008 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. |
# Cache driver directory |
# |
CACHE_DIR := $(SRC_DIR)/cache |
# compilation flags for the driver |
# |
CACHE_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(CACHE_DIR)) |
# Cache driver sources (i.e., C files) |
# |
CACHE_DRV_SRC := $(CACHE_DIR)/ftcbasic.c \ |
$(CACHE_DIR)/ftccache.c \ |
$(CACHE_DIR)/ftccmap.c \ |
$(CACHE_DIR)/ftcglyph.c \ |
$(CACHE_DIR)/ftcimage.c \ |
$(CACHE_DIR)/ftcmanag.c \ |
$(CACHE_DIR)/ftcmru.c \ |
$(CACHE_DIR)/ftcsbits.c |
# Cache driver headers |
# |
CACHE_DRV_H := $(CACHE_DIR)/ftccache.h \ |
$(CACHE_DIR)/ftccback.h \ |
$(CACHE_DIR)/ftcerror.h \ |
$(CACHE_DIR)/ftcglyph.h \ |
$(CACHE_DIR)/ftcimage.h \ |
$(CACHE_DIR)/ftcmanag.h \ |
$(CACHE_DIR)/ftcmru.h \ |
$(CACHE_DIR)/ftcsbits.h |
# Cache driver object(s) |
# |
# CACHE_DRV_OBJ_M is used during `multi' builds. |
# CACHE_DRV_OBJ_S is used during `single' builds. |
# |
CACHE_DRV_OBJ_M := $(CACHE_DRV_SRC:$(CACHE_DIR)/%.c=$(OBJ_DIR)/%.$O) |
CACHE_DRV_OBJ_S := $(OBJ_DIR)/ftcache.$O |
# Cache driver source file for single build |
# |
CACHE_DRV_SRC_S := $(CACHE_DIR)/ftcache.c |
# Cache driver - single object |
# |
$(CACHE_DRV_OBJ_S): $(CACHE_DRV_SRC_S) $(CACHE_DRV_SRC) \ |
$(FREETYPE_H) $(CACHE_DRV_H) |
$(CACHE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(CACHE_DRV_SRC_S)) |
# Cache driver - multiple objects |
# |
$(OBJ_DIR)/%.$O: $(CACHE_DIR)/%.c $(FREETYPE_H) $(CACHE_DRV_H) |
$(CACHE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) |
# update main driver object lists |
# |
DRV_OBJS_S += $(CACHE_DRV_OBJ_S) |
DRV_OBJS_M += $(CACHE_DRV_OBJ_M) |
# EOF |
/programs/develop/libraries/freetype/src/cache/. |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |