1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftcmanag.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* FreeType Cache Manager (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2000-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_CACHE_H 21*37da2899SCharles.Forsyth #include FT_CACHE_MANAGER_H 22*37da2899SCharles.Forsyth #include FT_CACHE_INTERNAL_LRU_H 23*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 24*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 25*37da2899SCharles.Forsyth #include FT_SIZES_H 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth #include "ftcerror.h" 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth #undef FT_COMPONENT 31*37da2899SCharles.Forsyth #define FT_COMPONENT trace_cache 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth #define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data ) 34*37da2899SCharles.Forsyth 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth /*************************************************************************/ 37*37da2899SCharles.Forsyth /*************************************************************************/ 38*37da2899SCharles.Forsyth /***** *****/ 39*37da2899SCharles.Forsyth /***** FACE LRU IMPLEMENTATION *****/ 40*37da2899SCharles.Forsyth /***** *****/ 41*37da2899SCharles.Forsyth /*************************************************************************/ 42*37da2899SCharles.Forsyth /*************************************************************************/ 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth typedef struct FTC_FaceNodeRec_* FTC_FaceNode; 45*37da2899SCharles.Forsyth typedef struct FTC_SizeNodeRec_* FTC_SizeNode; 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth typedef struct FTC_FaceNodeRec_ 49*37da2899SCharles.Forsyth { 50*37da2899SCharles.Forsyth FT_LruNodeRec lru; 51*37da2899SCharles.Forsyth FT_Face face; 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth } FTC_FaceNodeRec; 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth typedef struct FTC_SizeNodeRec_ 57*37da2899SCharles.Forsyth { 58*37da2899SCharles.Forsyth FT_LruNodeRec lru; 59*37da2899SCharles.Forsyth FT_Size size; 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth } FTC_SizeNodeRec; 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) ftc_face_node_init(FTC_FaceNode node,FTC_FaceID face_id,FTC_Manager manager)65*37da2899SCharles.Forsyth ftc_face_node_init( FTC_FaceNode node, 66*37da2899SCharles.Forsyth FTC_FaceID face_id, 67*37da2899SCharles.Forsyth FTC_Manager manager ) 68*37da2899SCharles.Forsyth { 69*37da2899SCharles.Forsyth FT_Error error; 70*37da2899SCharles.Forsyth 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth error = manager->request_face( face_id, 73*37da2899SCharles.Forsyth manager->library, 74*37da2899SCharles.Forsyth manager->request_data, 75*37da2899SCharles.Forsyth &node->face ); 76*37da2899SCharles.Forsyth if ( !error ) 77*37da2899SCharles.Forsyth { 78*37da2899SCharles.Forsyth /* destroy initial size object; it will be re-created later */ 79*37da2899SCharles.Forsyth if ( node->face->size ) 80*37da2899SCharles.Forsyth FT_Done_Size( node->face->size ); 81*37da2899SCharles.Forsyth } 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth return error; 84*37da2899SCharles.Forsyth } 85*37da2899SCharles.Forsyth 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsyth /* helper function for ftc_face_node_done() */ 88*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Bool ) ftc_size_node_select(FTC_SizeNode node,FT_Face face)89*37da2899SCharles.Forsyth ftc_size_node_select( FTC_SizeNode node, 90*37da2899SCharles.Forsyth FT_Face face ) 91*37da2899SCharles.Forsyth { 92*37da2899SCharles.Forsyth return FT_BOOL( node->size->face == face ); 93*37da2899SCharles.Forsyth } 94*37da2899SCharles.Forsyth 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) ftc_face_node_done(FTC_FaceNode node,FTC_Manager manager)97*37da2899SCharles.Forsyth ftc_face_node_done( FTC_FaceNode node, 98*37da2899SCharles.Forsyth FTC_Manager manager ) 99*37da2899SCharles.Forsyth { 100*37da2899SCharles.Forsyth FT_Face face = node->face; 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsyth 103*37da2899SCharles.Forsyth /* we must begin by removing all sizes for the target face */ 104*37da2899SCharles.Forsyth /* from the manager's list */ 105*37da2899SCharles.Forsyth FT_LruList_Remove_Selection( manager->sizes_list, 106*37da2899SCharles.Forsyth (FT_LruNode_SelectFunc)ftc_size_node_select, 107*37da2899SCharles.Forsyth face ); 108*37da2899SCharles.Forsyth 109*37da2899SCharles.Forsyth /* all right, we can discard the face now */ 110*37da2899SCharles.Forsyth FT_Done_Face( face ); 111*37da2899SCharles.Forsyth node->face = NULL; 112*37da2899SCharles.Forsyth } 113*37da2899SCharles.Forsyth 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 116*37da2899SCharles.Forsyth const FT_LruList_ClassRec ftc_face_list_class = 117*37da2899SCharles.Forsyth { 118*37da2899SCharles.Forsyth sizeof ( FT_LruListRec ), 119*37da2899SCharles.Forsyth (FT_LruList_InitFunc)0, 120*37da2899SCharles.Forsyth (FT_LruList_DoneFunc)0, 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth sizeof ( FTC_FaceNodeRec ), 123*37da2899SCharles.Forsyth (FT_LruNode_InitFunc) ftc_face_node_init, 124*37da2899SCharles.Forsyth (FT_LruNode_DoneFunc) ftc_face_node_done, 125*37da2899SCharles.Forsyth (FT_LruNode_FlushFunc) 0, /* no flushing needed */ 126*37da2899SCharles.Forsyth (FT_LruNode_CompareFunc)0, /* direct comparison of FTC_FaceID handles */ 127*37da2899SCharles.Forsyth }; 128*37da2899SCharles.Forsyth 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth /* documentation is in ftcache.h */ 131*37da2899SCharles.Forsyth 132*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Face(FTC_Manager manager,FTC_FaceID face_id,FT_Face * aface)133*37da2899SCharles.Forsyth FTC_Manager_Lookup_Face( FTC_Manager manager, 134*37da2899SCharles.Forsyth FTC_FaceID face_id, 135*37da2899SCharles.Forsyth FT_Face *aface ) 136*37da2899SCharles.Forsyth { 137*37da2899SCharles.Forsyth FT_Error error; 138*37da2899SCharles.Forsyth FTC_FaceNode node; 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth 141*37da2899SCharles.Forsyth if ( aface == NULL ) 142*37da2899SCharles.Forsyth return FTC_Err_Bad_Argument; 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth *aface = NULL; 145*37da2899SCharles.Forsyth 146*37da2899SCharles.Forsyth if ( !manager ) 147*37da2899SCharles.Forsyth return FTC_Err_Invalid_Cache_Handle; 148*37da2899SCharles.Forsyth 149*37da2899SCharles.Forsyth error = FT_LruList_Lookup( manager->faces_list, 150*37da2899SCharles.Forsyth (FT_LruKey)face_id, 151*37da2899SCharles.Forsyth (FT_LruNode*)&node ); 152*37da2899SCharles.Forsyth if ( !error ) 153*37da2899SCharles.Forsyth *aface = node->face; 154*37da2899SCharles.Forsyth 155*37da2899SCharles.Forsyth return error; 156*37da2899SCharles.Forsyth } 157*37da2899SCharles.Forsyth 158*37da2899SCharles.Forsyth 159*37da2899SCharles.Forsyth /*************************************************************************/ 160*37da2899SCharles.Forsyth /*************************************************************************/ 161*37da2899SCharles.Forsyth /***** *****/ 162*37da2899SCharles.Forsyth /***** SIZES LRU IMPLEMENTATION *****/ 163*37da2899SCharles.Forsyth /***** *****/ 164*37da2899SCharles.Forsyth /*************************************************************************/ 165*37da2899SCharles.Forsyth /*************************************************************************/ 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsyth 168*37da2899SCharles.Forsyth typedef struct FTC_SizeQueryRec_ 169*37da2899SCharles.Forsyth { 170*37da2899SCharles.Forsyth FT_Face face; 171*37da2899SCharles.Forsyth FT_UInt width; 172*37da2899SCharles.Forsyth FT_UInt height; 173*37da2899SCharles.Forsyth 174*37da2899SCharles.Forsyth } FTC_SizeQueryRec, *FTC_SizeQuery; 175*37da2899SCharles.Forsyth 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) ftc_size_node_init(FTC_SizeNode node,FTC_SizeQuery query)178*37da2899SCharles.Forsyth ftc_size_node_init( FTC_SizeNode node, 179*37da2899SCharles.Forsyth FTC_SizeQuery query ) 180*37da2899SCharles.Forsyth { 181*37da2899SCharles.Forsyth FT_Face face = query->face; 182*37da2899SCharles.Forsyth FT_Size size; 183*37da2899SCharles.Forsyth FT_Error error; 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth 186*37da2899SCharles.Forsyth node->size = NULL; 187*37da2899SCharles.Forsyth error = FT_New_Size( face, &size ); 188*37da2899SCharles.Forsyth if ( !error ) 189*37da2899SCharles.Forsyth { 190*37da2899SCharles.Forsyth FT_Activate_Size( size ); 191*37da2899SCharles.Forsyth error = FT_Set_Pixel_Sizes( query->face, 192*37da2899SCharles.Forsyth query->width, 193*37da2899SCharles.Forsyth query->height ); 194*37da2899SCharles.Forsyth if ( error ) 195*37da2899SCharles.Forsyth FT_Done_Size( size ); 196*37da2899SCharles.Forsyth else 197*37da2899SCharles.Forsyth node->size = size; 198*37da2899SCharles.Forsyth } 199*37da2899SCharles.Forsyth return error; 200*37da2899SCharles.Forsyth } 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth 203*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) ftc_size_node_done(FTC_SizeNode node)204*37da2899SCharles.Forsyth ftc_size_node_done( FTC_SizeNode node ) 205*37da2899SCharles.Forsyth { 206*37da2899SCharles.Forsyth if ( node->size ) 207*37da2899SCharles.Forsyth { 208*37da2899SCharles.Forsyth FT_Done_Size( node->size ); 209*37da2899SCharles.Forsyth node->size = NULL; 210*37da2899SCharles.Forsyth } 211*37da2899SCharles.Forsyth } 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) ftc_size_node_flush(FTC_SizeNode node,FTC_SizeQuery query)215*37da2899SCharles.Forsyth ftc_size_node_flush( FTC_SizeNode node, 216*37da2899SCharles.Forsyth FTC_SizeQuery query ) 217*37da2899SCharles.Forsyth { 218*37da2899SCharles.Forsyth FT_Size size = node->size; 219*37da2899SCharles.Forsyth FT_Error error; 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth 222*37da2899SCharles.Forsyth if ( size->face == query->face ) 223*37da2899SCharles.Forsyth { 224*37da2899SCharles.Forsyth FT_Activate_Size( size ); 225*37da2899SCharles.Forsyth error = FT_Set_Pixel_Sizes( query->face, query->width, query->height ); 226*37da2899SCharles.Forsyth if ( error ) 227*37da2899SCharles.Forsyth { 228*37da2899SCharles.Forsyth FT_Done_Size( size ); 229*37da2899SCharles.Forsyth node->size = NULL; 230*37da2899SCharles.Forsyth } 231*37da2899SCharles.Forsyth } 232*37da2899SCharles.Forsyth else 233*37da2899SCharles.Forsyth { 234*37da2899SCharles.Forsyth FT_Done_Size( size ); 235*37da2899SCharles.Forsyth node->size = NULL; 236*37da2899SCharles.Forsyth 237*37da2899SCharles.Forsyth error = ftc_size_node_init( node, query ); 238*37da2899SCharles.Forsyth } 239*37da2899SCharles.Forsyth return error; 240*37da2899SCharles.Forsyth } 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Bool ) ftc_size_node_compare(FTC_SizeNode node,FTC_SizeQuery query)244*37da2899SCharles.Forsyth ftc_size_node_compare( FTC_SizeNode node, 245*37da2899SCharles.Forsyth FTC_SizeQuery query ) 246*37da2899SCharles.Forsyth { 247*37da2899SCharles.Forsyth FT_Size size = node->size; 248*37da2899SCharles.Forsyth 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth return FT_BOOL( size->face == query->face && 251*37da2899SCharles.Forsyth (FT_UInt)size->metrics.x_ppem == query->width && 252*37da2899SCharles.Forsyth (FT_UInt)size->metrics.y_ppem == query->height ); 253*37da2899SCharles.Forsyth } 254*37da2899SCharles.Forsyth 255*37da2899SCharles.Forsyth 256*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF 257*37da2899SCharles.Forsyth const FT_LruList_ClassRec ftc_size_list_class = 258*37da2899SCharles.Forsyth { 259*37da2899SCharles.Forsyth sizeof ( FT_LruListRec ), 260*37da2899SCharles.Forsyth (FT_LruList_InitFunc)0, 261*37da2899SCharles.Forsyth (FT_LruList_DoneFunc)0, 262*37da2899SCharles.Forsyth 263*37da2899SCharles.Forsyth sizeof ( FTC_SizeNodeRec ), 264*37da2899SCharles.Forsyth (FT_LruNode_InitFunc) ftc_size_node_init, 265*37da2899SCharles.Forsyth (FT_LruNode_DoneFunc) ftc_size_node_done, 266*37da2899SCharles.Forsyth (FT_LruNode_FlushFunc) ftc_size_node_flush, 267*37da2899SCharles.Forsyth (FT_LruNode_CompareFunc)ftc_size_node_compare 268*37da2899SCharles.Forsyth }; 269*37da2899SCharles.Forsyth 270*37da2899SCharles.Forsyth 271*37da2899SCharles.Forsyth /* documentation is in ftcache.h */ 272*37da2899SCharles.Forsyth 273*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Size(FTC_Manager manager,FTC_Font font,FT_Face * aface,FT_Size * asize)274*37da2899SCharles.Forsyth FTC_Manager_Lookup_Size( FTC_Manager manager, 275*37da2899SCharles.Forsyth FTC_Font font, 276*37da2899SCharles.Forsyth FT_Face *aface, 277*37da2899SCharles.Forsyth FT_Size *asize ) 278*37da2899SCharles.Forsyth { 279*37da2899SCharles.Forsyth FT_Error error; 280*37da2899SCharles.Forsyth 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */ 283*37da2899SCharles.Forsyth if ( aface ) 284*37da2899SCharles.Forsyth *aface = 0; 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth if ( asize ) 287*37da2899SCharles.Forsyth *asize = 0; 288*37da2899SCharles.Forsyth 289*37da2899SCharles.Forsyth error = FTC_Manager_Lookup_Face( manager, font->face_id, aface ); 290*37da2899SCharles.Forsyth if ( !error ) 291*37da2899SCharles.Forsyth { 292*37da2899SCharles.Forsyth FTC_SizeQueryRec query; 293*37da2899SCharles.Forsyth FTC_SizeNode node; 294*37da2899SCharles.Forsyth 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth query.face = *aface; 297*37da2899SCharles.Forsyth query.width = font->pix_width; 298*37da2899SCharles.Forsyth query.height = font->pix_height; 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth error = FT_LruList_Lookup( manager->sizes_list, 301*37da2899SCharles.Forsyth (FT_LruKey)&query, 302*37da2899SCharles.Forsyth (FT_LruNode*)&node ); 303*37da2899SCharles.Forsyth if ( !error ) 304*37da2899SCharles.Forsyth { 305*37da2899SCharles.Forsyth /* select the size as the current one for this face */ 306*37da2899SCharles.Forsyth FT_Activate_Size( node->size ); 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth if ( asize ) 309*37da2899SCharles.Forsyth *asize = node->size; 310*37da2899SCharles.Forsyth } 311*37da2899SCharles.Forsyth } 312*37da2899SCharles.Forsyth 313*37da2899SCharles.Forsyth return error; 314*37da2899SCharles.Forsyth } 315*37da2899SCharles.Forsyth 316*37da2899SCharles.Forsyth 317*37da2899SCharles.Forsyth /*************************************************************************/ 318*37da2899SCharles.Forsyth /*************************************************************************/ 319*37da2899SCharles.Forsyth /***** *****/ 320*37da2899SCharles.Forsyth /***** SET TABLE MANAGEMENT *****/ 321*37da2899SCharles.Forsyth /***** *****/ 322*37da2899SCharles.Forsyth /*************************************************************************/ 323*37da2899SCharles.Forsyth /*************************************************************************/ 324*37da2899SCharles.Forsyth 325*37da2899SCharles.Forsyth static void ftc_family_table_init(FTC_FamilyTable table)326*37da2899SCharles.Forsyth ftc_family_table_init( FTC_FamilyTable table ) 327*37da2899SCharles.Forsyth { 328*37da2899SCharles.Forsyth table->count = 0; 329*37da2899SCharles.Forsyth table->size = 0; 330*37da2899SCharles.Forsyth table->entries = NULL; 331*37da2899SCharles.Forsyth table->free = FTC_FAMILY_ENTRY_NONE; 332*37da2899SCharles.Forsyth } 333*37da2899SCharles.Forsyth 334*37da2899SCharles.Forsyth 335*37da2899SCharles.Forsyth static void ftc_family_table_done(FTC_FamilyTable table,FT_Memory memory)336*37da2899SCharles.Forsyth ftc_family_table_done( FTC_FamilyTable table, 337*37da2899SCharles.Forsyth FT_Memory memory ) 338*37da2899SCharles.Forsyth { 339*37da2899SCharles.Forsyth FT_FREE( table->entries ); 340*37da2899SCharles.Forsyth table->free = 0; 341*37da2899SCharles.Forsyth table->count = 0; 342*37da2899SCharles.Forsyth table->size = 0; 343*37da2899SCharles.Forsyth } 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth 346*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) ftc_family_table_alloc(FTC_FamilyTable table,FT_Memory memory,FTC_FamilyEntry * aentry)347*37da2899SCharles.Forsyth ftc_family_table_alloc( FTC_FamilyTable table, 348*37da2899SCharles.Forsyth FT_Memory memory, 349*37da2899SCharles.Forsyth FTC_FamilyEntry *aentry ) 350*37da2899SCharles.Forsyth { 351*37da2899SCharles.Forsyth FTC_FamilyEntry entry; 352*37da2899SCharles.Forsyth FT_Error error = 0; 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth /* re-allocate table size when needed */ 356*37da2899SCharles.Forsyth if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size ) 357*37da2899SCharles.Forsyth { 358*37da2899SCharles.Forsyth FT_UInt old_size = table->size; 359*37da2899SCharles.Forsyth FT_UInt new_size, idx; 360*37da2899SCharles.Forsyth 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth if ( old_size == 0 ) 363*37da2899SCharles.Forsyth new_size = 8; 364*37da2899SCharles.Forsyth else 365*37da2899SCharles.Forsyth { 366*37da2899SCharles.Forsyth new_size = old_size * 2; 367*37da2899SCharles.Forsyth 368*37da2899SCharles.Forsyth /* check for (unlikely) overflow */ 369*37da2899SCharles.Forsyth if ( new_size < old_size ) 370*37da2899SCharles.Forsyth new_size = 65534; 371*37da2899SCharles.Forsyth } 372*37da2899SCharles.Forsyth 373*37da2899SCharles.Forsyth if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) ) 374*37da2899SCharles.Forsyth return error; 375*37da2899SCharles.Forsyth 376*37da2899SCharles.Forsyth table->size = new_size; 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth entry = table->entries + old_size; 379*37da2899SCharles.Forsyth table->free = old_size; 380*37da2899SCharles.Forsyth 381*37da2899SCharles.Forsyth for ( idx = old_size; idx + 1 < new_size; idx++, entry++ ) 382*37da2899SCharles.Forsyth { 383*37da2899SCharles.Forsyth entry->link = idx + 1; 384*37da2899SCharles.Forsyth entry->index = idx; 385*37da2899SCharles.Forsyth } 386*37da2899SCharles.Forsyth 387*37da2899SCharles.Forsyth entry->link = FTC_FAMILY_ENTRY_NONE; 388*37da2899SCharles.Forsyth entry->index = idx; 389*37da2899SCharles.Forsyth } 390*37da2899SCharles.Forsyth 391*37da2899SCharles.Forsyth if ( table->free != FTC_FAMILY_ENTRY_NONE ) 392*37da2899SCharles.Forsyth { 393*37da2899SCharles.Forsyth entry = table->entries + table->free; 394*37da2899SCharles.Forsyth table->free = entry->link; 395*37da2899SCharles.Forsyth } 396*37da2899SCharles.Forsyth else if ( table->count < table->size ) 397*37da2899SCharles.Forsyth { 398*37da2899SCharles.Forsyth entry = table->entries + table->count++; 399*37da2899SCharles.Forsyth } 400*37da2899SCharles.Forsyth else 401*37da2899SCharles.Forsyth { 402*37da2899SCharles.Forsyth FT_ERROR(( "ftc_family_table_alloc: internal bug!" )); 403*37da2899SCharles.Forsyth return FTC_Err_Invalid_Argument; 404*37da2899SCharles.Forsyth } 405*37da2899SCharles.Forsyth 406*37da2899SCharles.Forsyth entry->link = FTC_FAMILY_ENTRY_NONE; 407*37da2899SCharles.Forsyth table->count++; 408*37da2899SCharles.Forsyth 409*37da2899SCharles.Forsyth *aentry = entry; 410*37da2899SCharles.Forsyth return error; 411*37da2899SCharles.Forsyth } 412*37da2899SCharles.Forsyth 413*37da2899SCharles.Forsyth 414*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) ftc_family_table_free(FTC_FamilyTable table,FT_UInt idx)415*37da2899SCharles.Forsyth ftc_family_table_free( FTC_FamilyTable table, 416*37da2899SCharles.Forsyth FT_UInt idx ) 417*37da2899SCharles.Forsyth { 418*37da2899SCharles.Forsyth /* simply add it to the linked list of free entries */ 419*37da2899SCharles.Forsyth if ( idx < table->count ) 420*37da2899SCharles.Forsyth { 421*37da2899SCharles.Forsyth FTC_FamilyEntry entry = table->entries + idx; 422*37da2899SCharles.Forsyth 423*37da2899SCharles.Forsyth 424*37da2899SCharles.Forsyth if ( entry->link != FTC_FAMILY_ENTRY_NONE ) 425*37da2899SCharles.Forsyth FT_ERROR(( "ftc_family_table_free: internal bug!\n" )); 426*37da2899SCharles.Forsyth else 427*37da2899SCharles.Forsyth { 428*37da2899SCharles.Forsyth entry->link = table->free; 429*37da2899SCharles.Forsyth table->free = entry->index; 430*37da2899SCharles.Forsyth table->count--; 431*37da2899SCharles.Forsyth } 432*37da2899SCharles.Forsyth } 433*37da2899SCharles.Forsyth } 434*37da2899SCharles.Forsyth 435*37da2899SCharles.Forsyth 436*37da2899SCharles.Forsyth /*************************************************************************/ 437*37da2899SCharles.Forsyth /*************************************************************************/ 438*37da2899SCharles.Forsyth /***** *****/ 439*37da2899SCharles.Forsyth /***** CACHE MANAGER ROUTINES *****/ 440*37da2899SCharles.Forsyth /***** *****/ 441*37da2899SCharles.Forsyth /*************************************************************************/ 442*37da2899SCharles.Forsyth /*************************************************************************/ 443*37da2899SCharles.Forsyth 444*37da2899SCharles.Forsyth 445*37da2899SCharles.Forsyth /* documentation is in ftcache.h */ 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth 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)448*37da2899SCharles.Forsyth FTC_Manager_New( FT_Library library, 449*37da2899SCharles.Forsyth FT_UInt max_faces, 450*37da2899SCharles.Forsyth FT_UInt max_sizes, 451*37da2899SCharles.Forsyth FT_ULong max_bytes, 452*37da2899SCharles.Forsyth FTC_Face_Requester requester, 453*37da2899SCharles.Forsyth FT_Pointer req_data, 454*37da2899SCharles.Forsyth FTC_Manager *amanager ) 455*37da2899SCharles.Forsyth { 456*37da2899SCharles.Forsyth FT_Error error; 457*37da2899SCharles.Forsyth FT_Memory memory; 458*37da2899SCharles.Forsyth FTC_Manager manager = 0; 459*37da2899SCharles.Forsyth 460*37da2899SCharles.Forsyth 461*37da2899SCharles.Forsyth if ( !library ) 462*37da2899SCharles.Forsyth return FTC_Err_Invalid_Library_Handle; 463*37da2899SCharles.Forsyth 464*37da2899SCharles.Forsyth memory = library->memory; 465*37da2899SCharles.Forsyth 466*37da2899SCharles.Forsyth if ( FT_NEW( manager ) ) 467*37da2899SCharles.Forsyth goto Exit; 468*37da2899SCharles.Forsyth 469*37da2899SCharles.Forsyth if ( max_faces == 0 ) 470*37da2899SCharles.Forsyth max_faces = FTC_MAX_FACES_DEFAULT; 471*37da2899SCharles.Forsyth 472*37da2899SCharles.Forsyth if ( max_sizes == 0 ) 473*37da2899SCharles.Forsyth max_sizes = FTC_MAX_SIZES_DEFAULT; 474*37da2899SCharles.Forsyth 475*37da2899SCharles.Forsyth if ( max_bytes == 0 ) 476*37da2899SCharles.Forsyth max_bytes = FTC_MAX_BYTES_DEFAULT; 477*37da2899SCharles.Forsyth 478*37da2899SCharles.Forsyth error = FT_LruList_New( &ftc_face_list_class, 479*37da2899SCharles.Forsyth max_faces, 480*37da2899SCharles.Forsyth manager, 481*37da2899SCharles.Forsyth memory, 482*37da2899SCharles.Forsyth &manager->faces_list ); 483*37da2899SCharles.Forsyth if ( error ) 484*37da2899SCharles.Forsyth goto Exit; 485*37da2899SCharles.Forsyth 486*37da2899SCharles.Forsyth error = FT_LruList_New( &ftc_size_list_class, 487*37da2899SCharles.Forsyth max_sizes, 488*37da2899SCharles.Forsyth manager, 489*37da2899SCharles.Forsyth memory, 490*37da2899SCharles.Forsyth &manager->sizes_list ); 491*37da2899SCharles.Forsyth if ( error ) 492*37da2899SCharles.Forsyth goto Exit; 493*37da2899SCharles.Forsyth 494*37da2899SCharles.Forsyth manager->library = library; 495*37da2899SCharles.Forsyth manager->max_weight = max_bytes; 496*37da2899SCharles.Forsyth manager->cur_weight = 0; 497*37da2899SCharles.Forsyth 498*37da2899SCharles.Forsyth manager->request_face = requester; 499*37da2899SCharles.Forsyth manager->request_data = req_data; 500*37da2899SCharles.Forsyth 501*37da2899SCharles.Forsyth ftc_family_table_init( &manager->families ); 502*37da2899SCharles.Forsyth 503*37da2899SCharles.Forsyth *amanager = manager; 504*37da2899SCharles.Forsyth 505*37da2899SCharles.Forsyth Exit: 506*37da2899SCharles.Forsyth if ( error && manager ) 507*37da2899SCharles.Forsyth { 508*37da2899SCharles.Forsyth FT_LruList_Destroy( manager->faces_list ); 509*37da2899SCharles.Forsyth FT_LruList_Destroy( manager->sizes_list ); 510*37da2899SCharles.Forsyth FT_FREE( manager ); 511*37da2899SCharles.Forsyth } 512*37da2899SCharles.Forsyth 513*37da2899SCharles.Forsyth return error; 514*37da2899SCharles.Forsyth } 515*37da2899SCharles.Forsyth 516*37da2899SCharles.Forsyth 517*37da2899SCharles.Forsyth /* documentation is in ftcache.h */ 518*37da2899SCharles.Forsyth 519*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FTC_Manager_Done(FTC_Manager manager)520*37da2899SCharles.Forsyth FTC_Manager_Done( FTC_Manager manager ) 521*37da2899SCharles.Forsyth { 522*37da2899SCharles.Forsyth FT_Memory memory; 523*37da2899SCharles.Forsyth FT_UInt idx; 524*37da2899SCharles.Forsyth 525*37da2899SCharles.Forsyth 526*37da2899SCharles.Forsyth if ( !manager || !manager->library ) 527*37da2899SCharles.Forsyth return; 528*37da2899SCharles.Forsyth 529*37da2899SCharles.Forsyth memory = manager->library->memory; 530*37da2899SCharles.Forsyth 531*37da2899SCharles.Forsyth /* now discard all caches */ 532*37da2899SCharles.Forsyth for (idx = 0; idx < FTC_MAX_CACHES; idx++ ) 533*37da2899SCharles.Forsyth { 534*37da2899SCharles.Forsyth FTC_Cache cache = manager->caches[idx]; 535*37da2899SCharles.Forsyth 536*37da2899SCharles.Forsyth 537*37da2899SCharles.Forsyth if ( cache ) 538*37da2899SCharles.Forsyth { 539*37da2899SCharles.Forsyth cache->clazz->cache_done( cache ); 540*37da2899SCharles.Forsyth FT_FREE( cache ); 541*37da2899SCharles.Forsyth manager->caches[idx] = 0; 542*37da2899SCharles.Forsyth } 543*37da2899SCharles.Forsyth } 544*37da2899SCharles.Forsyth 545*37da2899SCharles.Forsyth /* discard families table */ 546*37da2899SCharles.Forsyth ftc_family_table_done( &manager->families, memory ); 547*37da2899SCharles.Forsyth 548*37da2899SCharles.Forsyth /* discard faces and sizes */ 549*37da2899SCharles.Forsyth FT_LruList_Destroy( manager->faces_list ); 550*37da2899SCharles.Forsyth manager->faces_list = 0; 551*37da2899SCharles.Forsyth 552*37da2899SCharles.Forsyth FT_LruList_Destroy( manager->sizes_list ); 553*37da2899SCharles.Forsyth manager->sizes_list = 0; 554*37da2899SCharles.Forsyth 555*37da2899SCharles.Forsyth FT_FREE( manager ); 556*37da2899SCharles.Forsyth } 557*37da2899SCharles.Forsyth 558*37da2899SCharles.Forsyth 559*37da2899SCharles.Forsyth /* documentation is in ftcache.h */ 560*37da2899SCharles.Forsyth 561*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FTC_Manager_Reset(FTC_Manager manager)562*37da2899SCharles.Forsyth FTC_Manager_Reset( FTC_Manager manager ) 563*37da2899SCharles.Forsyth { 564*37da2899SCharles.Forsyth if ( manager ) 565*37da2899SCharles.Forsyth { 566*37da2899SCharles.Forsyth FT_LruList_Reset( manager->sizes_list ); 567*37da2899SCharles.Forsyth FT_LruList_Reset( manager->faces_list ); 568*37da2899SCharles.Forsyth } 569*37da2899SCharles.Forsyth /* XXX: FIXME: flush the caches? */ 570*37da2899SCharles.Forsyth } 571*37da2899SCharles.Forsyth 572*37da2899SCharles.Forsyth 573*37da2899SCharles.Forsyth #ifdef FT_DEBUG_ERROR 574*37da2899SCharles.Forsyth 575*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FTC_Manager_Check(FTC_Manager manager)576*37da2899SCharles.Forsyth FTC_Manager_Check( FTC_Manager manager ) 577*37da2899SCharles.Forsyth { 578*37da2899SCharles.Forsyth FTC_Node node, first; 579*37da2899SCharles.Forsyth 580*37da2899SCharles.Forsyth 581*37da2899SCharles.Forsyth first = manager->nodes_list; 582*37da2899SCharles.Forsyth 583*37da2899SCharles.Forsyth /* check node weights */ 584*37da2899SCharles.Forsyth if ( first ) 585*37da2899SCharles.Forsyth { 586*37da2899SCharles.Forsyth FT_ULong weight = 0; 587*37da2899SCharles.Forsyth 588*37da2899SCharles.Forsyth 589*37da2899SCharles.Forsyth node = first; 590*37da2899SCharles.Forsyth 591*37da2899SCharles.Forsyth do 592*37da2899SCharles.Forsyth { 593*37da2899SCharles.Forsyth FTC_FamilyEntry entry = manager->families.entries + node->fam_index; 594*37da2899SCharles.Forsyth FTC_Cache cache; 595*37da2899SCharles.Forsyth 596*37da2899SCharles.Forsyth if ( (FT_UInt)node->fam_index >= manager->families.count || 597*37da2899SCharles.Forsyth entry->link != FTC_FAMILY_ENTRY_NONE ) 598*37da2899SCharles.Forsyth FT_ERROR(( "FTC_Manager_Check: invalid node (family index = %ld\n", 599*37da2899SCharles.Forsyth node->fam_index )); 600*37da2899SCharles.Forsyth else 601*37da2899SCharles.Forsyth { 602*37da2899SCharles.Forsyth cache = entry->cache; 603*37da2899SCharles.Forsyth weight += cache->clazz->node_weight( node, cache ); 604*37da2899SCharles.Forsyth } 605*37da2899SCharles.Forsyth 606*37da2899SCharles.Forsyth node = node->mru_next; 607*37da2899SCharles.Forsyth 608*37da2899SCharles.Forsyth } while ( node != first ); 609*37da2899SCharles.Forsyth 610*37da2899SCharles.Forsyth if ( weight != manager->cur_weight ) 611*37da2899SCharles.Forsyth FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n", 612*37da2899SCharles.Forsyth manager->cur_weight, weight )); 613*37da2899SCharles.Forsyth } 614*37da2899SCharles.Forsyth 615*37da2899SCharles.Forsyth /* check circular list */ 616*37da2899SCharles.Forsyth if ( first ) 617*37da2899SCharles.Forsyth { 618*37da2899SCharles.Forsyth FT_UFast count = 0; 619*37da2899SCharles.Forsyth 620*37da2899SCharles.Forsyth 621*37da2899SCharles.Forsyth node = first; 622*37da2899SCharles.Forsyth do 623*37da2899SCharles.Forsyth { 624*37da2899SCharles.Forsyth count++; 625*37da2899SCharles.Forsyth node = node->mru_next; 626*37da2899SCharles.Forsyth 627*37da2899SCharles.Forsyth } while ( node != first ); 628*37da2899SCharles.Forsyth 629*37da2899SCharles.Forsyth if ( count != manager->num_nodes ) 630*37da2899SCharles.Forsyth FT_ERROR(( 631*37da2899SCharles.Forsyth "FTC_Manager_Check: invalid cache node count %d instead of %d\n", 632*37da2899SCharles.Forsyth manager->num_nodes, count )); 633*37da2899SCharles.Forsyth } 634*37da2899SCharles.Forsyth } 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth #endif /* FT_DEBUG_ERROR */ 637*37da2899SCharles.Forsyth 638*37da2899SCharles.Forsyth 639*37da2899SCharles.Forsyth /* `Compress' the manager's data, i.e., get rid of old cache nodes */ 640*37da2899SCharles.Forsyth /* that are not referenced anymore in order to limit the total */ 641*37da2899SCharles.Forsyth /* memory used by the cache. */ 642*37da2899SCharles.Forsyth 643*37da2899SCharles.Forsyth /* documentation is in ftcmanag.h */ 644*37da2899SCharles.Forsyth 645*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FTC_Manager_Compress(FTC_Manager manager)646*37da2899SCharles.Forsyth FTC_Manager_Compress( FTC_Manager manager ) 647*37da2899SCharles.Forsyth { 648*37da2899SCharles.Forsyth FTC_Node node, first; 649*37da2899SCharles.Forsyth 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth if ( !manager ) 652*37da2899SCharles.Forsyth return; 653*37da2899SCharles.Forsyth 654*37da2899SCharles.Forsyth first = manager->nodes_list; 655*37da2899SCharles.Forsyth 656*37da2899SCharles.Forsyth #ifdef FT_DEBUG_ERROR 657*37da2899SCharles.Forsyth FTC_Manager_Check( manager ); 658*37da2899SCharles.Forsyth 659*37da2899SCharles.Forsyth FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n", 660*37da2899SCharles.Forsyth manager->cur_weight, manager->max_weight, 661*37da2899SCharles.Forsyth manager->num_nodes )); 662*37da2899SCharles.Forsyth #endif 663*37da2899SCharles.Forsyth 664*37da2899SCharles.Forsyth if ( manager->cur_weight < manager->max_weight || first == NULL ) 665*37da2899SCharles.Forsyth return; 666*37da2899SCharles.Forsyth 667*37da2899SCharles.Forsyth /* go to last node - it's a circular list */ 668*37da2899SCharles.Forsyth node = first->mru_prev; 669*37da2899SCharles.Forsyth do 670*37da2899SCharles.Forsyth { 671*37da2899SCharles.Forsyth FTC_Node prev = node->mru_prev; 672*37da2899SCharles.Forsyth 673*37da2899SCharles.Forsyth 674*37da2899SCharles.Forsyth prev = ( node == first ) ? NULL : node->mru_prev; 675*37da2899SCharles.Forsyth 676*37da2899SCharles.Forsyth if ( node->ref_count <= 0 ) 677*37da2899SCharles.Forsyth ftc_node_destroy( node, manager ); 678*37da2899SCharles.Forsyth 679*37da2899SCharles.Forsyth node = prev; 680*37da2899SCharles.Forsyth 681*37da2899SCharles.Forsyth } while ( node && manager->cur_weight > manager->max_weight ); 682*37da2899SCharles.Forsyth } 683*37da2899SCharles.Forsyth 684*37da2899SCharles.Forsyth 685*37da2899SCharles.Forsyth /* documentation is in ftcmanag.h */ 686*37da2899SCharles.Forsyth 687*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FTC_Manager_Register_Cache(FTC_Manager manager,FTC_Cache_Class clazz,FTC_Cache * acache)688*37da2899SCharles.Forsyth FTC_Manager_Register_Cache( FTC_Manager manager, 689*37da2899SCharles.Forsyth FTC_Cache_Class clazz, 690*37da2899SCharles.Forsyth FTC_Cache *acache ) 691*37da2899SCharles.Forsyth { 692*37da2899SCharles.Forsyth FT_Error error = FTC_Err_Invalid_Argument; 693*37da2899SCharles.Forsyth FTC_Cache cache = NULL; 694*37da2899SCharles.Forsyth 695*37da2899SCharles.Forsyth 696*37da2899SCharles.Forsyth if ( manager && clazz && acache ) 697*37da2899SCharles.Forsyth { 698*37da2899SCharles.Forsyth FT_Memory memory = manager->library->memory; 699*37da2899SCharles.Forsyth FT_UInt idx = 0; 700*37da2899SCharles.Forsyth 701*37da2899SCharles.Forsyth 702*37da2899SCharles.Forsyth /* check for an empty cache slot in the manager's table */ 703*37da2899SCharles.Forsyth for ( idx = 0; idx < FTC_MAX_CACHES; idx++ ) 704*37da2899SCharles.Forsyth { 705*37da2899SCharles.Forsyth if ( manager->caches[idx] == 0 ) 706*37da2899SCharles.Forsyth break; 707*37da2899SCharles.Forsyth } 708*37da2899SCharles.Forsyth 709*37da2899SCharles.Forsyth /* return an error if there are too many registered caches */ 710*37da2899SCharles.Forsyth if ( idx >= FTC_MAX_CACHES ) 711*37da2899SCharles.Forsyth { 712*37da2899SCharles.Forsyth error = FTC_Err_Too_Many_Caches; 713*37da2899SCharles.Forsyth FT_ERROR(( "FTC_Manager_Register_Cache:" )); 714*37da2899SCharles.Forsyth FT_ERROR(( " too many registered caches\n" )); 715*37da2899SCharles.Forsyth goto Exit; 716*37da2899SCharles.Forsyth } 717*37da2899SCharles.Forsyth 718*37da2899SCharles.Forsyth if ( !FT_ALLOC( cache, clazz->cache_size ) ) 719*37da2899SCharles.Forsyth { 720*37da2899SCharles.Forsyth cache->manager = manager; 721*37da2899SCharles.Forsyth cache->memory = memory; 722*37da2899SCharles.Forsyth cache->clazz = clazz; 723*37da2899SCharles.Forsyth 724*37da2899SCharles.Forsyth /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */ 725*37da2899SCharles.Forsyth /* IF IT IS NOT SET CORRECTLY */ 726*37da2899SCharles.Forsyth cache->cache_index = idx; 727*37da2899SCharles.Forsyth 728*37da2899SCharles.Forsyth if ( clazz->cache_init ) 729*37da2899SCharles.Forsyth { 730*37da2899SCharles.Forsyth error = clazz->cache_init( cache ); 731*37da2899SCharles.Forsyth if ( error ) 732*37da2899SCharles.Forsyth { 733*37da2899SCharles.Forsyth if ( clazz->cache_done ) 734*37da2899SCharles.Forsyth clazz->cache_done( cache ); 735*37da2899SCharles.Forsyth 736*37da2899SCharles.Forsyth FT_FREE( cache ); 737*37da2899SCharles.Forsyth goto Exit; 738*37da2899SCharles.Forsyth } 739*37da2899SCharles.Forsyth } 740*37da2899SCharles.Forsyth 741*37da2899SCharles.Forsyth manager->caches[idx] = cache; 742*37da2899SCharles.Forsyth } 743*37da2899SCharles.Forsyth } 744*37da2899SCharles.Forsyth 745*37da2899SCharles.Forsyth Exit: 746*37da2899SCharles.Forsyth *acache = cache; 747*37da2899SCharles.Forsyth return error; 748*37da2899SCharles.Forsyth } 749*37da2899SCharles.Forsyth 750*37da2899SCharles.Forsyth 751*37da2899SCharles.Forsyth /* documentation is in ftcmanag.h */ 752*37da2899SCharles.Forsyth 753*37da2899SCharles.Forsyth FT_EXPORT_DEF( void ) FTC_Node_Unref(FTC_Node node,FTC_Manager manager)754*37da2899SCharles.Forsyth FTC_Node_Unref( FTC_Node node, 755*37da2899SCharles.Forsyth FTC_Manager manager ) 756*37da2899SCharles.Forsyth { 757*37da2899SCharles.Forsyth if ( node && (FT_UInt)node->fam_index < manager->families.count && 758*37da2899SCharles.Forsyth manager->families.entries[node->fam_index].cache ) 759*37da2899SCharles.Forsyth { 760*37da2899SCharles.Forsyth node->ref_count--; 761*37da2899SCharles.Forsyth } 762*37da2899SCharles.Forsyth } 763*37da2899SCharles.Forsyth 764*37da2899SCharles.Forsyth 765*37da2899SCharles.Forsyth /* END */ 766