1
/***************************************************************************/
5
/* FreeType Cache Manager (body). */
7
/* Copyright 2000-2001, 2002, 2003, 2004 by */
8
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10
/* This file is part of the FreeType project, and may only be used, */
11
/* modified, and distributed under the terms of the FreeType project */
12
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13
/* this file you indicate that you have read the license and */
14
/* understand and accept it fully. */
16
/***************************************************************************/
21
#include FT_CACHE_INTERNAL_MANAGER_H
22
#include FT_INTERNAL_OBJECTS_H
23
#include FT_INTERNAL_DEBUG_H
30
#define FT_COMPONENT trace_cache
32
#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )
36
ftc_scaler_lookup_size( FTC_Manager manager,
45
error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
49
error = FT_New_Size( face, &size );
53
FT_Activate_Size( size );
56
error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
58
error = FT_Set_Char_Size( face, scaler->width, scaler->height,
59
scaler->x_res, scaler->y_res );
72
typedef struct FTC_SizeNodeRec_
78
} FTC_SizeNodeRec, *FTC_SizeNode;
81
FT_CALLBACK_DEF( void )
82
ftc_size_node_done( FTC_MruNode ftcnode,
85
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
86
FT_Size size = node->size;
95
FT_CALLBACK_DEF( FT_Bool )
96
ftc_size_node_compare( FTC_MruNode ftcnode,
97
FT_Pointer ftcscaler )
99
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
100
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
101
FTC_Scaler scaler0 = &node->scaler;
104
if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
106
FT_Activate_Size( node->size );
113
FT_CALLBACK_DEF( FT_Error )
114
ftc_size_node_init( FTC_MruNode ftcnode,
115
FT_Pointer ftcscaler,
116
FT_Pointer ftcmanager )
118
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
119
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
120
FTC_Manager manager = (FTC_Manager)ftcmanager;
123
node->scaler = scaler[0];
125
return ftc_scaler_lookup_size( manager, scaler, &node->size );
129
FT_CALLBACK_DEF( FT_Error )
130
ftc_size_node_reset( FTC_MruNode ftcnode,
131
FT_Pointer ftcscaler,
132
FT_Pointer ftcmanager )
134
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
135
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
136
FTC_Manager manager = (FTC_Manager)ftcmanager;
139
FT_Done_Size( node->size );
141
node->scaler = scaler[0];
143
return ftc_scaler_lookup_size( manager, scaler, &node->size );
147
FT_CALLBACK_TABLE_DEF
148
const FTC_MruListClassRec ftc_size_list_class =
150
sizeof ( FTC_SizeNodeRec ),
151
ftc_size_node_compare,
158
/* helper function used by ftc_face_node_done */
160
ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
161
FT_Pointer ftcface_id )
163
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
164
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
167
return node->scaler.face_id == face_id;
171
/* documentation is in ftcache.h */
173
FT_EXPORT_DEF( FT_Error )
174
FTC_Manager_LookupSize( FTC_Manager manager,
183
return FTC_Err_Bad_Argument;
188
return FTC_Err_Invalid_Cache_Handle;
192
FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
196
error = FTC_MruList_Lookup( &manager->sizes, scaler, (FTC_MruNode*)&node );
206
/*************************************************************************/
207
/*************************************************************************/
209
/***** FACE MRU IMPLEMENTATION *****/
211
/*************************************************************************/
212
/*************************************************************************/
214
typedef struct FTC_FaceNodeRec_
220
} FTC_FaceNodeRec, *FTC_FaceNode;
223
FT_CALLBACK_DEF( FT_Error )
224
ftc_face_node_init( FTC_MruNode ftcnode,
225
FT_Pointer ftcface_id,
226
FT_Pointer ftcmanager )
228
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
229
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
230
FTC_Manager manager = (FTC_Manager)ftcmanager;
234
node->face_id = face_id;
236
error = manager->request_face( face_id,
238
manager->request_data,
242
/* destroy initial size object; it will be re-created later */
243
if ( node->face->size )
244
FT_Done_Size( node->face->size );
251
FT_CALLBACK_DEF( void )
252
ftc_face_node_done( FTC_MruNode ftcnode,
253
FT_Pointer ftcmanager )
255
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
256
FTC_Manager manager = (FTC_Manager)ftcmanager;
259
/* we must begin by removing all scalers for the target face */
260
/* from the manager's list */
261
FTC_MruList_RemoveSelection( &manager->sizes,
262
ftc_size_node_compare_faceid,
265
/* all right, we can discard the face now */
266
FT_Done_Face( node->face );
268
node->face_id = NULL;
272
FT_CALLBACK_DEF( FT_Bool )
273
ftc_face_node_compare( FTC_MruNode ftcnode,
274
FT_Pointer ftcface_id )
276
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
277
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
280
return FT_BOOL( node->face_id == face_id );
284
FT_CALLBACK_TABLE_DEF
285
const FTC_MruListClassRec ftc_face_list_class =
287
sizeof ( FTC_FaceNodeRec),
289
ftc_face_node_compare,
291
0, /* FTC_MruNode_ResetFunc */
296
/* documentation is in ftcache.h */
298
FT_EXPORT_DEF( FT_Error )
299
FTC_Manager_LookupFace( FTC_Manager manager,
308
return FTC_Err_Bad_Argument;
313
return FTC_Err_Invalid_Cache_Handle;
315
/* we break encapsulation for the sake of speed */
318
FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
322
error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node );
332
/*************************************************************************/
333
/*************************************************************************/
335
/***** CACHE MANAGER ROUTINES *****/
337
/*************************************************************************/
338
/*************************************************************************/
341
/* documentation is in ftcache.h */
343
FT_EXPORT_DEF( FT_Error )
344
FTC_Manager_New( FT_Library library,
348
FTC_Face_Requester requester,
350
FTC_Manager *amanager )
354
FTC_Manager manager = 0;
358
return FTC_Err_Invalid_Library_Handle;
360
memory = library->memory;
362
if ( FT_NEW( manager ) )
365
if ( max_faces == 0 )
366
max_faces = FTC_MAX_FACES_DEFAULT;
368
if ( max_sizes == 0 )
369
max_sizes = FTC_MAX_SIZES_DEFAULT;
371
if ( max_bytes == 0 )
372
max_bytes = FTC_MAX_BYTES_DEFAULT;
374
manager->library = library;
375
manager->memory = memory;
376
manager->max_weight = max_bytes;
378
manager->request_face = requester;
379
manager->request_data = req_data;
381
FTC_MruList_Init( &manager->faces,
382
&ftc_face_list_class,
387
FTC_MruList_Init( &manager->sizes,
388
&ftc_size_list_class,
400
/* documentation is in ftcache.h */
402
FT_EXPORT_DEF( void )
403
FTC_Manager_Done( FTC_Manager manager )
409
if ( !manager || !manager->library )
412
memory = manager->memory;
414
/* now discard all caches */
415
for (idx = manager->num_caches; idx-- > 0; )
417
FTC_Cache cache = manager->caches[idx];
422
cache->clazz.cache_done( cache );
424
manager->caches[idx] = NULL;
427
manager->num_caches = 0;
429
/* discard faces and sizes */
430
FTC_MruList_Done( &manager->sizes );
431
FTC_MruList_Done( &manager->faces );
433
manager->library = NULL;
434
manager->memory = NULL;
440
/* documentation is in ftcache.h */
442
FT_EXPORT_DEF( void )
443
FTC_Manager_Reset( FTC_Manager manager )
447
FTC_MruList_Reset( &manager->sizes );
448
FTC_MruList_Reset( &manager->faces );
450
/* XXX: FIXME: flush the caches? */
454
#ifdef FT_DEBUG_ERROR
456
FT_EXPORT_DEF( void )
457
FTC_Manager_Check( FTC_Manager manager )
459
FTC_Node node, first;
462
first = manager->nodes_list;
464
/* check node weights */
474
FTC_Cache cache = manager->caches[node->cache_index];
477
if ( (FT_UInt)node->cache_index >= manager->num_caches )
478
FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
479
node->cache_index ));
481
weight += cache->clazz.node_weight( node, cache );
483
node = FTC_NODE__NEXT( node );
485
} while ( node != first );
487
if ( weight != manager->cur_weight )
488
FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
489
manager->cur_weight, weight ));
492
/* check circular list */
502
node = FTC_NODE__NEXT( node );
504
} while ( node != first );
506
if ( count != manager->num_nodes )
508
"FTC_Manager_Check: invalid cache node count %d instead of %d\n",
509
manager->num_nodes, count ));
513
#endif /* FT_DEBUG_ERROR */
516
/* `Compress' the manager's data, i.e., get rid of old cache nodes */
517
/* that are not referenced anymore in order to limit the total */
518
/* memory used by the cache. */
520
/* documentation is in ftcmanag.h */
522
FT_EXPORT_DEF( void )
523
FTC_Manager_Compress( FTC_Manager manager )
525
FTC_Node node, first;
531
first = manager->nodes_list;
533
#ifdef FT_DEBUG_ERROR
534
FTC_Manager_Check( manager );
536
FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
537
manager->cur_weight, manager->max_weight,
538
manager->num_nodes ));
541
if ( manager->cur_weight < manager->max_weight || first == NULL )
544
/* go to last node -- it's a circular list */
545
node = FTC_NODE__PREV( first );
551
prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
553
if ( node->ref_count <= 0 )
554
ftc_node_destroy( node, manager );
558
} while ( node && manager->cur_weight > manager->max_weight );
562
/* documentation is in ftcmanag.h */
564
FT_EXPORT_DEF( FT_Error )
565
FTC_Manager_RegisterCache( FTC_Manager manager,
566
FTC_CacheClass clazz,
569
FT_Error error = FTC_Err_Invalid_Argument;
570
FTC_Cache cache = NULL;
573
if ( manager && clazz && acache )
575
FT_Memory memory = manager->memory;
578
if ( manager->num_caches >= FTC_MAX_CACHES )
580
error = FTC_Err_Too_Many_Caches;
581
FT_ERROR(( "%s: too many registered caches\n",
582
"FTC_Manager_Register_Cache" ));
586
if ( !FT_ALLOC( cache, clazz->cache_size ) )
588
cache->manager = manager;
589
cache->memory = memory;
590
cache->clazz = clazz[0];
591
cache->org_class = clazz;
593
/* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
594
/* IF IT IS NOT SET CORRECTLY */
595
cache->index = manager->num_caches;
597
error = clazz->cache_init( cache );
600
clazz->cache_done( cache );
605
manager->caches[manager->num_caches++] = cache;
615
FT_EXPORT_DEF( FT_UInt )
616
FTC_Manager_FlushN( FTC_Manager manager,
619
FTC_Node first = manager->nodes_list;
624
/* try to remove `count' nodes from the list */
625
if ( first == NULL ) /* empty list! */
628
/* go to last node - it's a circular list */
629
node = FTC_NODE__PREV(first);
630
for ( result = 0; result < count; )
632
FTC_Node prev = FTC_NODE__PREV( node );
635
/* don't touch locked nodes */
636
if ( node->ref_count <= 0 )
638
ftc_node_destroy( node, manager );
642
if ( prev == manager->nodes_list )
651
/* documentation is in ftcache.h */
653
FT_EXPORT_DEF( void )
654
FTC_Manager_RemoveFaceID( FTC_Manager manager,
659
/* this will remove all FTC_SizeNode that correspond to
660
* the face_id as well
662
FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id );
664
for ( nn = 0; nn < manager->num_caches; nn++ )
665
FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
669
/* documentation is in ftcache.h */
671
FT_EXPORT_DEF( void )
672
FTC_Node_Unref( FTC_Node node,
673
FTC_Manager manager )
675
if ( node && (FT_UInt)node->cache_index < manager->num_caches )