ref: b466a7650ce97d3843bcbb4b145bda323a201022
dir: /src/cache/ftcmanag.c/
#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; }