completing the FreeType Cache subsystem files

This commit is contained in:
David Turner 2000-08-23 21:11:13 +00:00
parent 8728f294bc
commit 3b2c50eb3b
10 changed files with 1141 additions and 115 deletions

View File

@ -1,5 +1,9 @@
LATEST CHANGES
- added the cache sub-system. See <freetype/ftcache.h> as well as the
sources in "src/cache". Note that it compiles but is still untested
for now ..
- updated "docs/docmaker.py", a draft API reference is available at
http://www.freetype.org/ft2api.html

451
include/freetype/ftcache.h Normal file
View File

@ -0,0 +1,451 @@
/***************************************************************************/
/* */
/* ftcache.h */
/* */
/* FreeType Cache subsystem */
/* */
/* Copyright 1996-2000 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef FTCACHE_H
#define FTCACHE_H
#include <freetype/ftglyph.h>
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** BASIC TYPE DEFINITIONS *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************
*
* <Type>
* FTC_FaceID
*
* <Description>
* a generic pointer type that is used to identity face objects.
* the content of such objects is application-dependent
*
**************************************************************************/
typedef FT_Pointer FTC_FaceID;
/**************************************************************************
*
* <FuncType>
* FTC_Face_Requester
*
* <Description>
* a callback function provided by client applications. It is used
* to translate a given FTC_FaceID into a new valid FT_Face object
*
* <Input>
* face_id :: the face id to resolve
* library :: handle to a FreeType library object
* data :: application-provided request data
*
* <Output>
* aface :: a new FT_Face handle
*
* <Return>
* Error code. 0 means success
*
**************************************************************************/
typedef FT_Error (*FTC_Face_Requester)( FTC_FaceID face_id,
FT_Library library,
FT_Pointer request_data,
FT_Face* aface );
/**************************************************************************
*
* <Struct>
* FTC_SizeRec
*
* <Description>
* A simple structure used to describe a given "font size" to the
* cache manager
*
* <Fields>
* face_id :: id of face to use
* pix_width :: character width in integer pixels
* pix_height :: character height in integer pixels
*
**************************************************************************/
typedef struct FTC_SizeRec_
{
FTC_FaceID face_id;
FT_UShort pix_width;
FT_UShort pix_height;
} FTC_SizeRec;
/**************************************************************************
*
* <Type>
* FTC_SizeID
*
* <Description>
* A simple handle to a FTC_SizeRec structure
*
**************************************************************************/
typedef FTC_SizeRec* FTC_SizeID;
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** CACHE MANAGER OBJECT *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************
*
* <Type>
* FTC_Manager
*
* <Description>
* This object is used to cache one or more FT_Face object, along with
* corresponding FT_Size objects.
*
**************************************************************************/
typedef struct FTC_ManagerRec_* FTC_Manager;
/**************************************************************************
*
* <Function>
* FTC_Manager_New
*
* <Description>
* Create a new cache manager.
*
* <Input>
* library :: the parent FreeType library handle to use
*
* requester :: an application-provided callback used to translate
* face IDs into real FT_Face objects
*
* req_data :: a generic pointer that is passed to the requester
* each time it is called (see FTC_Face_Requester)
*
* <Output>
* amanager :: handle to new manager object. 0 in case of failure
*
* <Return>
* Error code. 0 means success
*
**************************************************************************/
FT_EXPORT_DEF( FT_Error ) FTC_Manager_New( FT_Library library,
FTC_Face_Requester requester,
FT_Pointer req_data,
FTC_Manager* amanager );
/**************************************************************************
*
* <Function>
* FTC_Manager_Reset
*
* <Description>
* Empty a given cache manager. This simply gets rid of all the
* currently cached FT_Face & FT_Size objects within the manager
*
* <Input>
* manager :: handle to manager
*
**************************************************************************/
FT_EXPORT_DEF( void ) FTC_Manager_Reset( FTC_Manager manager );
/**************************************************************************
*
* <Function>
* FTC_Manager_Done
*
* <Description>
* destroys a given manager after emptying it..
*
* <Input>
* manager :: handle to target cache manager object
*
**************************************************************************/
FT_EXPORT_DEF( void ) FTC_Manager_Done( FTC_Manager manager );
/**************************************************************************
*
* <Function>
* FTC_Manager_Lookup_Face
*
* <Description>
* retrieves the FT_Face that corresponds to a given face ID through
* a cache manager.
*
* <Input>
* manager :: handle to cache manager
* face_id :: ID of face object
*
* <Output>
* aface :: handle to face object
*
* <Return>
* Error code. 0 means success
*
* <Note>
* The returned FT_Face object is always owned by the manager, you
* should never try to discard it yourself..
*
* The FT_Face object doesn't necessarily have a current size object
* (i.e. face->size can be 0). If you need a specific "font size",
* use FTC_Manager_Lookup_Size instead..
*
* Never change the face's transform (i.e. NEVER CALL FT_Set_Transform)
* on a returned face. If you need to transform glyphs, do it yourself
* after glyph loading..
*
**************************************************************************/
FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Face( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face* aface );
/**************************************************************************
*
* <Function>
* FTC_Manager_Lookup_Size
*
* <Description>
* retrieves the FT_Face & FT_Size that correspond to a given
* FTC_SizeID
*
* <Input>
* manager :: handle to cache manager.
* size_id :: ID of the "font size" to use
*
* <InOut>
* aface :: ptr to handle to face object. Set to 0 if you don't need it
* asize :: ptr to handle to size object. Set to 0 if you don't need it
*
* <Return>
* Error code. 0 means success
*
* <Note>
* The returned FT_Face object is always owned by the manager, you
* should never try to discard it yourself..
*
* Never change the face's transform (i.e. NEVER CALL FT_Set_Transform)
* on a returned face. If you need to transform glyphs, do it yourself
* after glyph loading..
*
* The returned FT_Size object is always owned by the manager, you
* should never try to discard it, NEVER CHANGE ITS SETTINGS THROUGH
* FT_Set_Pixel_Sizes OR FT_Set_Char_Size !!
*
* The returned size object is the face's current size, which means
* that you can call FT_Load_Glyph with the face if you need to..
*
**************************************************************************/
FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Size( FTC_Manager manager,
FTC_SizeID size_id,
FT_Face* aface,
FT_Size* asize );
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** IMAGE CACHE OBJECT *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************************************************************
*
* <Enum>
* FTC_Image_Type
*
* <Description>
* An enumeration used to list the types of glyph images found in a
* glyph image cache.
*
* <Fields>
* ftc_image_mono :: monochrome bitmap glyphs
* ftc_image_grays :: anti-aliased bitmap glyphs
* ftc_image_outline :: scaled (and hinted) outline glyphs
* ftc_master_outline :: unscaled original outline glyphs
*
* <Note>
* other types may be defined in the future
*
**************************************************************************/
typedef enum FTC_Image_Type_
{
ftc_image_mono = 0, /* monochrome bitmap */
ftc_image_grays, /* anti-aliased bitmap */
ftc_image_outline, /* scaled outline */
ftc_image_master_outline /* original outline */
} FTC_Image_Type;
/**************************************************************************
*
* <Struct>
* FTC_Image_Desc
*
* <Description>
* A simple structure used to describe a given glyph image category
*
* <Fields>
* size :: a FTC_SizeRec used to describe the glyph's face & size
* image_type :: the glyph image's type
*
**************************************************************************/
typedef struct FTC_Image_Desc_
{
FTC_SizeRec size;
FT_UInt image_type;
} FTC_Image_Desc;
/**************************************************************************
*
* <Type>
* FTC_Image_Cache
*
* <Description>
* A handle to an glyph image cache object.. They are designed to
* hold many distinct glyph images, while not exceeding a certain
* memory threshold..
*
**************************************************************************/
typedef struct FTC_Image_CacheRec_* FTC_Image_Cache;
/**************************************************************************
*
* <Function>
* FTC_Image_Cache_New
*
* <Description>
* Create a new glyph image cache.
*
* <Input>
* manager :: parent manager for the image cache
*
* max_bytes :: the maximum amount of memory that will be used to
* store glyph images
*
* <Output>
* acache :: handle to new glyph image cache object
*
* <Return>
* Error code. 0 means success
*
**************************************************************************/
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager,
FT_ULong max_bytes,
FTC_Image_Cache* acache );
/**************************************************************************
*
* <Function>
* FTC_Image_Cache_Done
*
* <Description>
* Destroys a given glyph image cache (and all glyphs within it).
*
* <Input>
* manager :: parent manager for the image cache
*
**************************************************************************/
FT_EXPORT_DEF( void ) FTC_Image_Cache_Done( FTC_Image_Cache cache );
/**************************************************************************
*
* <Function>
* FTC_Image_Cache_Lookup
*
* <Description>
* Retrieve a given glyph image from a glyph image cache.
*
* <Input>
* cache :: handle to source glyph image cache
* desc :: pointer to a glyph image descriptor
* gindex :: index of glyph to retrieve
*
* <Output>
* aglyph :: the corresponding FT_Glyph object. 0 in case of failure
*
* <Return>
* Error code. 0 means success
*
* <Note>
* the returned glyph is owned and manager by the glyph image cache,
* never try to transform or discard it manually. You can however
* create a copy with FT_Glyph_Copy and modify the new one at will.
*
* Because the glyph image cache limits the total amount of memory
* taken by the glyphs it holds, the returned glyph might disappear
* on a later invocation of this function !! It's a cache after all ;-)
*
**************************************************************************/
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_Lookup(
FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph* aglyph );
#endif /* FTCACHE_H */

36
src/cache/ftcache.c vendored Normal file
View File

@ -0,0 +1,36 @@
/***************************************************************************/
/* */
/* ftcache.c */
/* */
/* The FreeType Caching sub-system */
/* */
/* Copyright 1996-2000 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#ifdef FT_FLAT_COMPILE
#include "ftlru.c"
#include "ftcmanag.c"
#include "ftcimage.c"
#else
#include <cache/ftlru.c>
#include <cache/ftcmanag.c>
#include <cache/ftcimage.c>
#endif
/* END */

545
src/cache/ftcimage.c vendored
View File

@ -17,6 +17,59 @@
#include <cache/ftcimage.h>
#include <freetype/fterrors.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftlist.h>
/***********************************************************************/
/***********************************************************************/
/***** *****/
/***** IMAGE NODE MANAGEMENT *****/
/***** *****/
/***** For now, we simply ALLOC/FREE the FTC_ImageNode. However, *****/
/***** it certainly is a good idea to use a chunk manager in the *****/
/***** future in order to reduce memory waste/fragmentation *****/
/***** *****/
/***********************************************************************/
/***********************************************************************/
static
FT_Error FTC_ImageNode_New( FTC_Image_Cache cache,
FTC_ImageNode *anode )
{
FT_Error error;
FT_Memory memory = cache->memory;
FTC_ImageNode node;
*anode = 0;
if (!ALLOC( node, sizeof(*node) ))
*anode = node;
return error;
}
static
void FTC_ImageNode_Done( FTC_Image_Cache cache,
FTC_ImageNode node )
{
/* for now, we simply discard the node. We may later add a chunk */
/* manager to the image cache.. */
FT_Memory memory = cache->memory;
FREE( node );
}
/***********************************************************************/
/***********************************************************************/
/***** *****/
/***** GLYPH IMAGE QUEUES *****/
/***** *****/
/***********************************************************************/
/***********************************************************************/
static
void ftc_done_glyph_image( FTC_Image_Queue queue,
@ -43,7 +96,7 @@
if ( pitch < 0 )
pitch = -pitch;
return (FT_ULong)(pitch * glyph->bitmap->rows + sizeof ( *glyph ) );
return (FT_ULong)(pitch * glyph->bitmap.rows + sizeof ( *glyph ) );
}
@ -51,7 +104,6 @@
FT_ULong ftc_size_outline_image( FTC_Image_Queue queue,
FTC_ImageNode node )
{
FT_Long pitch;
FT_OutlineGlyph glyph;
FT_Outline* outline;
@ -68,14 +120,6 @@
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** MONOCHROME BITMAP CALLBACKS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static
FT_Error ftc_init_mono_image( FTC_Image_Queue queue,
FTC_ImageNode node )
@ -84,20 +128,19 @@
FT_Size size;
FT_Error error;
error = FTC_Manager_Lookup_Size( queue->manager,
&queue->size_rec,
&queue->descriptor.size,
&face, &size );
if ( !error )
{
FT_UInt glyph_index = FTC_IMAGENODE_GINDEX( node );
FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
error = FT_Load_Glyph( face, glyph_index,
FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
if ( !error )
{
if ( face->glyph->format != ft_image_format_bitmap ||
if ( face->glyph->format != ft_glyph_format_bitmap ||
face->glyph->bitmap.pixel_mode != ft_pixel_mode_mono )
{
/* there is no monochrome glyph for this font! */
@ -129,21 +172,21 @@
error = FTC_Manager_Lookup_Size( queue->manager,
&queue->size_rec,
&queue->descriptor.size,
&face, &size );
if ( !error )
{
FT_UInt glyph_index = FTC_IMAGENODE_GINDEX( node );
FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
error = FT_Load_Glyph( face, glyph_index,
FT_LOAD_RENDER );
if ( !error )
{
if ( face->glyph->format != ft_image_format_bitmap ||
if ( face->glyph->format != ft_glyph_format_bitmap ||
face->glyph->bitmap.pixel_mode != ft_pixel_mode_grays )
{
/* there is no monochrome glyph for this font! */
/* there is no anti-aliased glyph for this font! */
error = FT_Err_Invalid_Glyph_Index;
}
else
@ -162,4 +205,470 @@
}
static
FT_Error ftc_init_outline_image( FTC_Image_Queue queue,
FTC_ImageNode node )
{
FT_Face face;
FT_Size size;
FT_Error error;
error = FTC_Manager_Lookup_Size( queue->manager,
&queue->descriptor.size,
&face, &size );
if ( !error )
{
FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
error = FT_Load_Glyph( face, glyph_index,
FT_LOAD_NO_BITMAP );
if ( !error )
{
if ( face->glyph->format != ft_glyph_format_outline )
{
/* there is no outline glyph for this font! */
error = FT_Err_Invalid_Glyph_Index;
}
else
{
/* ok, copy it */
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
FTC_IMAGENODE_SET_GLYPH( node, glyph );
}
}
}
return error;
}
static
FT_Error ftc_init_master_outline_image( FTC_Image_Queue queue,
FTC_ImageNode node )
{
FT_Face face;
FT_Size size;
FT_Error error;
error = FTC_Manager_Lookup_Size( queue->manager,
&queue->descriptor.size,
&face, &size );
if ( !error )
{
FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
error = FT_Load_Glyph( face, glyph_index,
FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
if ( !error )
{
if ( face->glyph->format != ft_glyph_format_outline )
{
/* there is no outline glyph for this font! */
error = FT_Err_Invalid_Glyph_Index;
}
else
{
/* ok, copy it */
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
FTC_IMAGENODE_SET_GLYPH( node, glyph );
}
}
}
return error;
}
static
const FTC_Image_Class ftc_mono_image_class =
{
ftc_init_mono_image,
ftc_done_glyph_image,
ftc_size_bitmap_image
};
static
const FTC_Image_Class ftc_gray_image_class =
{
ftc_init_gray_image,
ftc_done_glyph_image,
ftc_size_bitmap_image
};
static
const FTC_Image_Class ftc_outline_image_class =
{
ftc_init_outline_image,
ftc_done_glyph_image,
ftc_size_outline_image
};
static
const FTC_Image_Class ftc_master_outline_image_class =
{
ftc_init_master_outline_image,
ftc_done_glyph_image,
ftc_size_outline_image
};
static
FT_Error FTC_Image_Queue_New( FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FTC_Image_Queue *aqueue )
{
FT_Error error;
FT_Memory memory = cache->memory;
FTC_Manager manager = cache->manager;
FTC_Image_Queue queue = 0;
const FTC_Image_Class* clazz;
*aqueue = 0;
if ( ALLOC( queue, sizeof(*queue) ) )
goto Exit;
queue->cache = cache;
queue->manager = manager;
queue->memory = memory;
queue->descriptor = *desc;
queue->hash_size = 32;
if ( ALLOC_ARRAY( queue->buckets, queue->hash_size, FT_ListRec ) )
goto Exit;
switch (desc->image_type)
{
case ftc_image_mono:
clazz = &ftc_mono_image_class;
break;
case ftc_image_grays:
clazz = &ftc_gray_image_class;
break;
case ftc_image_outline:
clazz = &ftc_outline_image_class;
break;
case ftc_image_master_outline:
clazz = &ftc_master_outline_image_class;
break;
default:
/* invalid image type !! */
error = FT_Err_Invalid_Argument;
goto Exit;
}
queue->clazz = (FTC_Image_Class*)clazz;
*aqueue = queue;
Exit:
if (error)
FREE( queue );
return error;
}
static
void FTC_Image_Queue_Done( FTC_Image_Queue queue )
{
FTC_Image_Cache cache = queue->cache;
FT_List glyphs_lru = &cache->glyphs_lru;
FT_List bucket = queue->buckets;
FT_List bucket_limit = bucket + queue->hash_size;
FT_Memory memory = cache->memory;
/* for each bucket, free the list of image nodes */
for ( ; bucket < bucket_limit; bucket++ )
{
FT_ListNode node = bucket->head;
FT_ListNode next = 0;
FT_ListNode lrunode;
FTC_ImageNode inode;
for ( ; node; node = next )
{
next = node->next;
inode = (FTC_ImageNode)node;
lrunode = FTC_IMAGENODE_TO_LISTNODE(inode);
queue->clazz->done_image( queue, inode );
FT_List_Remove( glyphs_lru, lrunode );
FTC_ImageNode_Done( cache, inode );
}
bucket->head = bucket->tail = 0;
}
FREE( queue->buckets );
FREE( queue );
}
static
FT_Error FTC_Image_Queue_Lookup_Node( FTC_Image_Queue queue,
FT_UInt glyph_index,
FTC_ImageNode *anode )
{
FTC_Image_Cache cache = queue->cache;
FT_UInt hash_index = glyph_index % queue->hash_size;
FT_List bucket = queue->buckets + hash_index;
FT_ListNode node, next;
FT_Error error;
FTC_ImageNode inode;
*anode = 0;
for ( node = bucket->head; node; node = next )
{
inode = (FTC_ImageNode)node;
if ( FTC_IMAGENODE_GET_GINDEX(inode) == glyph_index )
{
/* we found it !! - move glyph to start of the list */
FT_List_Up( bucket, node );
*anode = inode;
return 0;
}
}
/* we didn't found the glyph image, we will now create a new one */
error = FTC_ImageNode_New( queue->cache, &inode );
if (error)
goto Exit;
error = queue->clazz->init_image( queue, inode );
if (error)
{
FTC_ImageNode_Done( queue->cache, inode );
goto Exit;
}
/* set the glyph and queue indices in the image node */
FTC_IMAGENODE_SET_INDICES( inode, glyph_index, queue->index );
/* insert the node at the start of our bucket list */
FT_List_Insert( bucket, (FT_ListNode)inode );
/* insert the node at the start the global LRU glyph list */
FT_List_Insert( &cache->glyphs_lru, FTC_IMAGENODE_TO_LISTNODE(inode) );
cache->num_bytes += queue->clazz->size_image(queue,inode);
*anode = inode;
Exit:
return error;
}
/***********************************************************************/
/***********************************************************************/
/***** *****/
/***** IMAGE CACHE CALLBACKS *****/
/***** *****/
/***********************************************************************/
/***********************************************************************/
#define FTC_QUEUE_LRU_GET_CACHE(lru) ((FTC_Image_Cache)(lru)->user_data)
#define FTC_QUEUE_LRU_GET_MANAGER(lru) FTC_QUEUE_LRU_GET_CACHE(lru)->manager
#define FTC_LRUNODE_QUEUE(node) ((FTC_Image_Queue)(node)->root.data)
static
FT_Error ftc_image_cache_init_queue( FT_Lru lru,
FT_LruNode node )
{
FTC_Image_Cache cache = FTC_QUEUE_LRU_GET_CACHE(lru);
FTC_Image_Desc* desc = (FTC_Image_Desc*)node->key;
FT_Error error;
FTC_Image_Queue queue;
error = FTC_Image_Queue_New( cache, desc, &queue );
if (!error)
{
/* good, now set the queue index within the queue object */
queue->index = node - lru->nodes;
node->root.data = queue;
}
return error;
}
static
void ftc_image_cache_done_queue( FT_Lru lru,
FT_LruNode node )
{
FTC_Image_Queue queue = FTC_LRUNODE_QUEUE(node);
FT_UNUSED(lru);
FTC_Image_Queue_Done(queue);
}
static
FT_Bool ftc_image_cache_compare_queue( FT_LruNode node,
FT_LruKey key )
{
FTC_Image_Queue queue = FTC_LRUNODE_QUEUE(node);
FTC_Image_Desc* desc2 = (FTC_Image_Desc*)key;
FTC_Image_Desc* desc1 = &queue->descriptor;
return ( desc1->size.face_id == desc2->size.face_id &&
desc1->size.pix_width == desc2->size.pix_width &&
desc1->size.pix_height == desc2->size.pix_height &&
desc1->image_type == desc2->image_type );
}
static
const FT_Lru_Class ftc_image_queue_lru_class =
{
sizeof( FT_LruRec ),
ftc_image_cache_init_queue,
ftc_image_cache_done_queue,
0, /* no flush */
ftc_image_cache_compare_queue
};
/* compress image cache if it needs it.. i.e. discards all old glyph images */
/* until "cache.num_bytes" is under "cache.max_bytes". Note that this function */
/* will avoid to remove "new_node".. */
static
void FTC_Image_Cache_Compress( FTC_Image_Cache cache,
FTC_ImageNode new_node )
{
while (cache->num_bytes > cache->max_bytes)
{
FT_ListNode cur = cache->glyphs_lru.tail;
FTC_Image_Queue queue;
FT_UInt glyph_index;
FT_UInt hash_index;
FT_UInt queue_index;
FT_ULong size;
FTC_ImageNode inode;
/* exit our loop if there isn't any glyph image left, or if */
/* we reached the newly created node (which is always at the */
/* start of the list..) */
inode = FTC_LISTNODE_TO_IMAGENODE(cur);
if ( !cur || inode == new_node )
break;
glyph_index = FTC_IMAGENODE_GET_GINDEX(inode);
queue_index = FTC_IMAGENODE_GET_QINDEX(inode);
queue = (FTC_Image_Queue)cache->queues_lru->nodes[queue_index].root.data;
hash_index = glyph_index % queue->hash_size;
size = queue->clazz->size_image( queue, inode );
FT_List_Remove( &cache->glyphs_lru, cur );
FT_List_Remove( queue->buckets + hash_index, (FT_ListNode)inode );
queue->clazz->done_image( queue, inode );
FTC_ImageNode_Done( cache, inode );
cache->num_bytes -= size;
}
}
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager,
FT_ULong max_bytes,
FTC_Image_Cache* acache )
{
FT_Error error;
FT_Memory memory;
FTC_Image_Cache cache;
*acache = 0;
memory = manager->library->memory;
if ( ALLOC( cache, sizeof(*cache) ) )
goto Exit;
cache->manager = manager;
cache->max_bytes = max_bytes;
error = FT_Lru_New( &ftc_image_queue_lru_class,
FTC_MAX_IMAGE_QUEUES,
cache,
memory,
1, /* pre_alloc == TRUE */
&cache->queues_lru );
if (error)
goto Exit;
*acache = cache;
Exit:
if ( error )
FREE( cache );
return error;
}
FT_EXPORT_DEF( void ) FTC_Image_Cache_Done( FTC_Image_Cache cache )
{
FT_Memory memory = cache->memory;
/* discard image queues */
FT_Lru_Done( cache->queues_lru );
/* discard cache */
FREE( cache );
}
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_Lookup(
FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph* aglyph )
{
FT_Error error;
FTC_Image_Queue queue;
FTC_ImageNode inode;
*aglyph = 0;
error = FT_Lru_Lookup( cache->queues_lru,
(FT_LruKey)desc,
(FT_Pointer*)&queue );
if (error)
goto Exit;
error = FTC_Image_Queue_Lookup_Node( queue, gindex, &inode );
if (error)
goto Exit;
FTC_Image_Cache_Compress( cache, inode );
*aglyph = FTC_IMAGENODE_GET_GLYPH(inode);
Exit:
return error;
}
/* END */

67
src/cache/ftcimage.h vendored
View File

@ -21,40 +21,18 @@
#include <cache/ftcmanag.h>
#include <freetype/ftglyph.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FTC_MAX_IMAGE_QUEUES 16
typedef struct FTC_Image_QueueRec_* FTC_Image_Queue;
typedef struct FTC_Image_CacheRec_* FTC_Image_Cache;
typedef struct FTC_ImageNodeRec_* FTC_ImageNode;
/* types of glyph images */
typedef enum FTC_Image_Type_
{
ftc_image_mono = 0, /* monochrome bitmap */
ftc_image_grays, /* anti-aliased bitmap */
ftc_image_outline, /* scaled outline */
ftc_image_master_outline, /* original outline */
} FTC_Image_Type;
/* a descriptor used to describe all glyphs in a given queue */
typedef struct FTC_Image_Desc_
{
FTC_FaceID face_id;
FT_UInt pix_width;
FT_UInt pix_height;
FT_UInt image_type;
} FTC_Image_Desc;
/* macros used to pack a glyph index and a queue index in a single ptr */
#define FTC_PTR_TO_GINDEX( p ) ( (FT_UInt)( (FT_ULong)(p) >> 16 ) )
#define FTC_PTR_TO_QINDEX( p ) ( (FT_UInt)( (FT_ULong)(p) & 0xFFFF ) )
@ -76,13 +54,26 @@
/* macros to read/set the glyph & queue index in a FTC_ImageNode */
#define FTC_IMAGENODE_GET_GINDEX( n ) FTC_PTR_TO_GINDEX( (n)->root2.data )
#define FTC_IMAGENODE_GET_QINDEX( n ) FTC_PTR_TO_QINDEX( (n)->root2.data )
#define FTC_IMAGENODE_SET_INDICES( g, q ) \
#define FTC_IMAGENODE_GET_GLYPH(n) ((FT_Glyph)(n)->root1.data)
#define FTC_IMAGENODE_SET_GLYPH(n,g) do { (n)->root1.data = g; } while (0)
#define FTC_IMAGENODE_SET_INDICES( n, g, q ) \
do \
{ \
(n)->root2.data = FTC_INDICES_TO_PTR( g, q ); \
} while ( 0 )
/* this macro is used to extract a handle to the global LRU list node */
/* corresponding to a given image node.. */
#define FTC_IMAGENODE_TO_LISTNODE(n) \
((FT_ListNode)&(n)->root2)
/* this macro is used to extract a handle to a given image node from */
/* the corresponding LRU glyph list node. That's a bit hackish.. */
#define FTC_LISTNODE_TO_IMAGENODE(p) \
((FTC_ImageNode)((char*)(p) - offsetof(FTC_ImageNodeRec,root2)))
typedef struct FTC_Image_CacheRec_
{
FTC_Manager manager;
@ -91,22 +82,23 @@
FT_ULong max_bytes; /* maximum size of cache in bytes */
FT_ULong num_bytes; /* current size of cache in bytes */
FT_Lru queues_lru; /* static queues lru list */
FT_Lru queues_lru; /* static queues lru list */
FT_ListRec glyphs_lru; /* global lru list of glyph images */
} FTC_Image_Cache;
} FTC_Image_CacheRec;
/* a table of functions used to generate/manager glyph images */
typedef struct FTC_Image_Class_
{
FT_Error (*init_image)( FTC_Image_Queue queue,
FTC_Image_Node node );
FTC_ImageNode node );
void (*done_image)( FTC_Image_Queue queue,
FTC_Image_Node node );
FTC_ImageNode node );
FT_ULong (*size_image)( FTC_Image_Queue queue,
FTC_Image_Node node );
FTC_ImageNode node );
} FTC_Image_Class;
@ -120,22 +112,11 @@
FTC_Image_Desc descriptor;
FT_UInt hash_size;
FT_List buckets;
FT_UInt index; /* index in parent cache */
} FTC_Image_SubCacheRec;
} FTC_Image_QueueRec;
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager,
FT_ULong max_bytes,
FTC_Image_Cache* acache );
FT_EXPORT_DEF( void ) FTC_Image_Cache_Done( FTC_Image_Cache cache );
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_Lookup(
FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph* aglyph );
#ifdef __cplusplus
}

31
src/cache/ftcmanag.c vendored
View File

@ -20,7 +20,7 @@
#include <freetype/internal/ftobjs.h>
#define FTC_LRU_GET_MANAGER( lru ) ((FTC_Manager_Lru)lru)->manager
#define FTC_LRU_GET_MANAGER( lru ) (FTC_Manager)lru->user_data
/**************************************************************************/
@ -40,6 +40,7 @@
error = manager->request_face( (FTC_FaceID)node->key,
manager->library,
manager->request_data,
(FT_Face*)&node->root.data );
if ( !error )
@ -179,7 +180,7 @@
static
const FT_Lru_Class ftc_face_lru_class =
{
sizeof ( FTC_Manager_LruRec ),
sizeof ( FT_LruRec ),
ftc_manager_init_face,
ftc_manager_done_face,
0,
@ -190,7 +191,7 @@
static
const FT_Lru_Class ftc_size_lru_class =
{
sizeof ( FTC_Manager_LruRec ),
sizeof ( FT_LruRec ),
ftc_manager_init_size,
ftc_manager_done_size,
ftc_manager_flush_size,
@ -213,6 +214,7 @@
error = FT_Lru_New( &ftc_face_lru_class,
FTC_MAX_FACES,
manager,
memory,
1, /* pre_alloc = TRUE */
(FT_Lru*)&manager->faces_lru );
@ -221,15 +223,13 @@
error = FT_Lru_New( &ftc_size_lru_class,
FTC_MAX_SIZES,
manager,
memory,
1, /* pre_alloc = TRUE */
(FT_Lru*)&manager->sizes_lru );
if ( error )
goto Exit;
((FTC_Manager_Lru)manager->faces_lru)->manager = manager;
((FTC_Manager_Lru)manager->sizes_lru)->manager = manager;
manager->library = library;
manager->request_face = requester;
manager->request_data = req_data;
@ -275,6 +275,7 @@
}
FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Size( FTC_Manager manager,
FTC_SizeID size_id,
FT_Face* aface,
@ -285,24 +286,34 @@
FT_Face face;
*aface = 0;
*asize = 0;
if (aface)
*aface = 0;
if (asize)
*asize = 0;
error = FTC_Manager_Lookup_Face( manager, size_id->face_id, &face );
if ( !error )
{
FT_Size size;
req.face = face;
req.width = size_id->pix_width;
req.height = size_id->pix_height;
error = FT_Lru_Lookup( manager->sizes_lru,
(FT_LruKey)&req,
(FT_Pointer*)asize );
(FT_Pointer*)&size );
if ( !error )
{
/* select the size as the current one for this face */
face->size = *asize;
*aface = face;
if (asize)
*asize = size;
if (aface)
*aface = face;
}
}

45
src/cache/ftcmanag.h vendored
View File

@ -19,6 +19,7 @@
#ifndef FTCMANAG_H
#define FTCMANAG_H
#include <freetype/ftcache.h>
#include <cache/ftlru.h>
@ -31,32 +32,6 @@
#define FTC_MAX_SIZES 8
typedef FT_Pointer FTC_FaceID;
typedef struct FTC_SizeRec_
{
FTC_FaceID face_id;
FT_UShort pix_width;
FT_UShort pix_height;
} FTC_SizeRec, *FTC_SizeID;
typedef FT_Error (*FTC_Face_Requester)( FTC_FaceID face_id,
FT_Pointer data,
FT_Face* aface );
typedef struct FTC_ManagerRec_* FTC_Manager;
typedef struct FTC_Manager_LruRec_
{
FT_LruRec root;
FTC_Manager manager;
} FTC_Manager_LruRec, *FTC_Manager_Lru;
typedef struct FTC_ManagerRec_
{
FT_Library library;
@ -69,24 +44,6 @@
} FTC_ManagerRec;
FT_EXPORT_DEF( FT_Error ) FTC_Manager_New( FT_Library library,
FTC_Face_Requester requester,
FT_Pointer req_data,
FTC_Manager* amanager );
FT_EXPORT_DEF( void ) FTC_Manager_Done( FTC_Manager manager );
FT_EXPORT_DEF( void ) FTC_Manager_Reset( FTC_Manager manager );
FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Face( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face* aface );
FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Size( FTC_Manager manager,
FTC_SizeID size_id,
FT_Face* aface,
FT_Size* asize );
#ifdef __cplusplus
}

2
src/cache/ftlru.c vendored
View File

@ -38,6 +38,7 @@
FT_EXPORT_FUNC( FT_Error ) FT_Lru_New( const FT_Lru_Class* clazz,
FT_UInt max_elements,
FT_Pointer user_data,
FT_Memory memory,
FT_Bool pre_alloc,
FT_Lru* alru )
@ -66,6 +67,7 @@
lru->clazz = (FT_Lru_Class*)clazz;
lru->max_elements = max_elements;
lru->memory = memory;
lru->user_data = user_data;
*alru = lru;
}

5
src/cache/ftlru.h vendored
View File

@ -40,6 +40,8 @@
typedef struct FT_LruRec_* FT_Lru;
typedef struct FT_Lru_Class_
{
FT_UInt lru_size; /* object size in bytes */
@ -60,6 +62,7 @@
} FT_Lru_Class;
typedef FT_Bool (*FT_Lru_Selector)( FT_Lru lru,
FT_LruNode node,
FT_Pointer data );
@ -72,6 +75,7 @@
FT_UInt num_elements;
FT_ListRec elements;
FT_Memory memory;
FT_Pointer user_data;
/* the following fields are only meaningful for static lru containers */
FT_ListRec free_nodes;
@ -82,6 +86,7 @@
FT_EXPORT_DEF( FT_Error ) FT_Lru_New( const FT_Lru_Class* clazz,
FT_UInt max_elements,
FT_Pointer user_data,
FT_Memory memory,
FT_Bool pre_alloc,
FT_Lru* alru );

70
src/cache/rules.mk vendored Normal file
View File

@ -0,0 +1,70 @@
#
# FreeType 2 Cache configuration rules
#
# Copyright 1996-2000 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
# and distributed under the terms of the FreeType project license,
# LICENSE.TXT. By continuing to use, modify, or distribute this file you
# indicate that you have read the license and understand and accept it
# fully.
# Cache driver directory
#
Cache_DIR := $(SRC_)cache
Cache_DIR_ := $(Cache_DIR)$(SEP)
# compilation flags for the driver
#
Cache_COMPILE := $(FT_COMPILE)
# Cache driver sources (i.e., C files)
#
Cache_DRV_SRC := $(Cache_DIR_)ftlru.c \
$(Cache_DIR_)ftcmanag.c \
$(Cache_DIR_)ftcimage.c
# Cache driver headers
#
Cache_DRV_H := $(Cache_DRV_SRC:%c=%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_)%.$O)
Cache_DRV_OBJ_S := $(OBJ_)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$@ $(Cache_DRV_SRC_S)
# Cache driver - multiple objects
#
$(OBJ_)%.$O: $(Cache_DIR_)%.c $(FREETYPE_H) $(Cache_DRV_H)
$(Cache_COMPILE) $T$@ $<
# update main driver object lists
#
DRV_OBJS_S += $(Cache_DRV_OBJ_S)
DRV_OBJS_M += $(Cache_DRV_OBJ_M)
# EOF