The FreeType Caching Subsystem - first lines of code
beware, this code is not tested, and probably doesn't compile
correctly.. more information will follow..
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
new file mode 100644
index 0000000..98453e1
--- /dev/null
+++ b/src/cache/ftcmanag.c
@@ -0,0 +1,280 @@
+#include <cache/ftcmanag.h>
+#include <freetype/internal/ftobjs.h>
+
+#define FTC_LRU_GET_MANAGER(lru) ((FTC_Manager_Lru)lru)->manager
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** FACE & SIZE LRU CALLBACKS *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+ static
+ FT_Error ftc_manager_init_face( FT_Lru lru,
+ FT_LruNode node )
+ {
+ FTC_Manager manager = FTC_LRU_GET_MANAGER(lru);
+ FT_Error error;
+
+ error = manager->request_face( (FTC_FaceID)node->key,
+ manager->request_data,
+ (FT_Face*)&node->root.data );
+ if (!error)
+ {
+ /* destroy initial size object, it will be re-created later */
+ FT_Face face = (FT_Face)node->root.data;
+ FT_Done_Size( face->size );
+ }
+ return error;
+ }
+
+
+ /* helper function for ftc_manager_done_face */
+ static
+ FT_Bool ftc_manager_size_selector( FT_Lru lru,
+ FT_LruNode node,
+ FT_Pointer data )
+ {
+ FT_UNUSED(lru);
+ return ((FT_Size)node->root.data)->face == (FT_Face)data;
+ }
+
+ static
+ void ftc_manager_done_face( FT_Lru lru,
+ FT_LruNode node )
+ {
+ FTC_Manager manager = FTC_LRU_GET_MANAGER(lru);
+ FT_Face face = (FT_Face)node->root.data;
+
+ /* we must begin by removing all sizes for the target face */
+ /* from the manager's list.. */
+ FT_Lru_Remove_Selection( manager->sizes_lru,
+ ftc_manager_size_selector,
+ face );
+
+ /* all right, we can discard the face now */
+ FT_Done_Face( face );
+ node->root.data = 0;
+ }
+
+
+ typedef struct FTC_SizeRequest_
+ {
+ FT_Face face;
+ FT_UShort width;
+ FT_UShort height;
+
+ } FTC_SizeRequest;
+
+
+ static
+ FT_Error ftc_manager_init_size( FT_Lru lru,
+ FT_LruNode node )
+ {
+ FTC_SizeRequest* size_req = (FTC_SizeRequest*)node->key;
+ FT_Size size;
+ FT_Error error;
+
+ FT_UNUSED(lru);
+
+ node->root.data = 0;
+ error = FT_New_Size( size_req->face, &size );
+ if (!error)
+ {
+ error = FT_Set_Pixel_Sizes( size_req->face,
+ size_req->width,
+ size_req->height );
+ if (error)
+ FT_Done_Size(size);
+ else
+ node->root.data = size;
+ }
+ return error;
+ }
+
+
+ static
+ void ftc_manager_done_size( FT_Lru lru,
+ FT_LruNode node )
+ {
+ FT_UNUSED(lru);
+ FT_Done_Size( (FT_Size)node->root.data );
+ }
+
+
+
+ static
+ FT_Error ftc_manager_flush_size( FT_Lru lru,
+ FT_LruNode node,
+ FT_LruKey key )
+ {
+ FTC_SizeRequest* req = (FTC_SizeRequest*)key;
+ FT_Size size = (FT_Size)node->root.data;
+ FT_Error error;
+
+ if ( size->face == req->face )
+ {
+ size->face->size = size; /* set current size */
+ error = FT_Set_Pixel_Sizes( req->face, req->width, req->height );
+ if (error)
+ FT_Done_Size( size );
+ }
+ else
+ {
+ FT_Done_Size(size);
+ node->key = key;
+ error = ftc_manager_init_size( lru, node );
+ }
+ return error;
+ }
+
+
+ static
+ FT_Bool ftc_manager_compare_size( FT_LruNode node,
+ FT_LruKey key )
+ {
+ FTC_SizeRequest* req = (FTC_SizeRequest*)key;
+ FT_Size size = (FT_Size)node->root.data;
+
+ FT_UNUSED(node);
+ return ( size->face == req->face &&
+ size->metrics.x_ppem == req->width &&
+ size->metrics.y_ppem == req->height );
+ }
+
+
+
+
+ static
+ const FT_Lru_Class ftc_face_lru_class =
+ {
+ sizeof( FTC_Manager_LruRec ),
+ ftc_manager_init_face,
+ ftc_manager_done_face,
+ 0,
+ 0
+ };
+
+
+ static
+ const FT_Lru_Class ftc_size_lru_class =
+ {
+ sizeof( FTC_Manager_LruRec ),
+ ftc_manager_init_size,
+ ftc_manager_done_size,
+ ftc_manager_flush_size,
+ ftc_manager_compare_size
+ };
+
+
+
+ FT_EXPORT_FUNC(FT_Error) FTC_Manager_New ( FT_Library library,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager )
+ {
+ FT_Error error;
+ FT_Memory memory = library->memory;
+ FTC_Manager manager = 0;
+
+
+ if ( ALLOC( manager, sizeof(*manager) ) )
+ goto Exit;
+
+ error = FT_Lru_New( &ftc_face_lru_class,
+ FTC_MAX_FACES,
+ memory,
+ 1, /* pre_alloc = TRUE */
+ (FT_Lru*)&manager->faces_lru );
+ if (error)
+ goto Exit;
+
+ error = FT_Lru_New( &ftc_size_lru_class,
+ FTC_MAX_SIZES,
+ 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;
+ *amanager = manager;
+
+ Exit:
+ if (error && manager)
+ {
+ FT_Lru_Done( manager->sizes_lru );
+ FT_Lru_Done( manager->faces_lru );
+ FREE( manager );
+ }
+
+ return error;
+ }
+
+ FT_EXPORT_DEF(void) FTC_Manager_Done ( FTC_Manager manager )
+ {
+ FT_Memory memory = manager->library->memory;
+
+ FT_Lru_Done( manager->sizes_lru );
+ FT_Lru_Done( manager->faces_lru );
+ FREE( manager );
+ }
+
+
+ FT_EXPORT_DEF(void) FTC_Manager_Reset( FTC_Manager manager )
+ {
+ FT_Lru_Reset( manager->sizes_lru );
+ FT_Lru_Reset( manager->faces_lru );
+ }
+
+
+ FT_EXPORT_DEF(FT_Error) FTC_Manager_Lookup_Face( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ return FT_Lru_Lookup( manager->faces_lru,
+ (FT_LruKey)face_id,
+ (FT_Pointer*)aface );
+ }
+
+
+
+ FT_EXPORT_DEF(FT_Error) FTC_Manager_Lookup_Size( FTC_Manager manager,
+ FTC_SizeID size_id,
+ FT_Face *aface,
+ FT_Size *asize )
+ {
+ FTC_SizeRequest req;
+ FT_Error error;
+ FT_Face face;
+
+ *aface = 0;
+ *asize = 0;
+ error = FTC_Manager_Lookup_Face( manager, size_id->face_id, &face );
+ if (!error)
+ {
+ 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 );
+ if (!error)
+ {
+ /* select the size as the current one for this face */
+ face->size = *asize;
+ *aface = face;
+ }
+ }
+ return error;
+ }
+
+