blob: a39e7fab921baa7d8680bf91e3a8ba707e450c13 [file] [log] [blame]
Werner Lemberg8728f292000-08-23 17:32:42 +00001/***************************************************************************/
2/* */
Werner Lembergd1b74752000-08-24 16:29:15 +00003/* ftcmanag.c */
Werner Lemberg8728f292000-08-23 17:32:42 +00004/* */
Werner Lembergd1b74752000-08-24 16:29:15 +00005/* FreeType Cache Manager (body). */
Werner Lemberg8728f292000-08-23 17:32:42 +00006/* */
7/* Copyright 2000 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
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. */
15/* */
16/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
20#include FT_CACHE_H
21#include FT_CACHE_MANAGER_H
22#include FT_INTERNAL_OBJECTS_H
23#include FT_INTERNAL_DEBUG_H
24#include FT_LIST_H
David Turnerb466a762000-08-23 11:22:30 +000025
Werner Lembergeddd9902000-10-12 05:05:40 +000026
27#undef FT_COMPONENT
28#define FT_COMPONENT trace_cache
David Turnerb466a762000-08-23 11:22:30 +000029
David Turner3b2c50e2000-08-23 21:11:13 +000030#define FTC_LRU_GET_MANAGER( lru ) (FTC_Manager)lru->user_data
Werner Lemberg8728f292000-08-23 17:32:42 +000031
32
Werner Lemberg4e9dae62000-08-29 16:50:01 +000033 /*************************************************************************/
34 /*************************************************************************/
35 /***** *****/
36 /***** FACE & SIZE LRU CALLBACKS *****/
37 /***** *****/
38 /*************************************************************************/
39 /*************************************************************************/
David Turnerb466a762000-08-23 11:22:30 +000040
Werner Lemberg4e9dae62000-08-29 16:50:01 +000041
David Turner76a5f622000-11-04 01:55:49 +000042 FT_CALLBACK_DEF
David Turnerb466a762000-08-23 11:22:30 +000043 FT_Error ftc_manager_init_face( FT_Lru lru,
44 FT_LruNode node )
45 {
Werner Lemberg8728f292000-08-23 17:32:42 +000046 FTC_Manager manager = FTC_LRU_GET_MANAGER( lru );
David Turnerb466a762000-08-23 11:22:30 +000047 FT_Error error;
David Turnerebdce832000-09-19 01:11:11 +000048 FT_Face face;
Werner Lembergeddd9902000-10-12 05:05:40 +000049
Werner Lemberg8728f292000-08-23 17:32:42 +000050
David Turnerb466a762000-08-23 11:22:30 +000051 error = manager->request_face( (FTC_FaceID)node->key,
David Turner3b2c50e2000-08-23 21:11:13 +000052 manager->library,
David Turnerb466a762000-08-23 11:22:30 +000053 manager->request_data,
54 (FT_Face*)&node->root.data );
Werner Lemberg8728f292000-08-23 17:32:42 +000055 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +000056 {
Werner Lemberg8728f292000-08-23 17:32:42 +000057 /* destroy initial size object; it will be re-created later */
David Turnerebdce832000-09-19 01:11:11 +000058 face = (FT_Face)node->root.data;
Werner Lembergab855232000-10-31 22:13:54 +000059 if ( face->size )
David Turnerece63792000-10-28 23:34:45 +000060 FT_Done_Size( face->size );
David Turnerb466a762000-08-23 11:22:30 +000061 }
Werner Lemberg8728f292000-08-23 17:32:42 +000062
David Turnerb466a762000-08-23 11:22:30 +000063 return error;
64 }
65
66
Werner Lembergeddd9902000-10-12 05:05:40 +000067 /* helper function for ftc_manager_done_face() */
David Turner76a5f622000-11-04 01:55:49 +000068 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +000069 FT_Bool ftc_manager_size_selector( FT_Lru lru,
70 FT_LruNode node,
71 FT_Pointer data )
72 {
73 FT_UNUSED( lru );
74
75 return ((FT_Size)node->root.data)->face == (FT_Face)data;
76 }
77
David Turnerb466a762000-08-23 11:22:30 +000078
David Turner76a5f622000-11-04 01:55:49 +000079 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +000080 void ftc_manager_done_face( FT_Lru lru,
81 FT_LruNode node )
David Turnerb466a762000-08-23 11:22:30 +000082 {
Werner Lemberg8728f292000-08-23 17:32:42 +000083 FTC_Manager manager = FTC_LRU_GET_MANAGER( lru );
David Turnerb466a762000-08-23 11:22:30 +000084 FT_Face face = (FT_Face)node->root.data;
Werner Lembergeddd9902000-10-12 05:05:40 +000085
Werner Lemberg8728f292000-08-23 17:32:42 +000086
David Turnerb466a762000-08-23 11:22:30 +000087 /* we must begin by removing all sizes for the target face */
Werner Lemberg8728f292000-08-23 17:32:42 +000088 /* from the manager's list */
David Turnerb466a762000-08-23 11:22:30 +000089 FT_Lru_Remove_Selection( manager->sizes_lru,
90 ftc_manager_size_selector,
91 face );
92
Werner Lembergeddd9902000-10-12 05:05:40 +000093 /* all right, we can discard the face now */
David Turnerb466a762000-08-23 11:22:30 +000094 FT_Done_Face( face );
95 node->root.data = 0;
96 }
97
98
David Turnerebdce832000-09-19 01:11:11 +000099 typedef struct FTC_FontRequest_
David Turnerb466a762000-08-23 11:22:30 +0000100 {
101 FT_Face face;
102 FT_UShort width;
103 FT_UShort height;
Werner Lembergeddd9902000-10-12 05:05:40 +0000104
David Turnerebdce832000-09-19 01:11:11 +0000105 } FTC_FontRequest;
David Turnerb466a762000-08-23 11:22:30 +0000106
107
David Turner76a5f622000-11-04 01:55:49 +0000108 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +0000109 FT_Error ftc_manager_init_size( FT_Lru lru,
110 FT_LruNode node )
David Turnerb466a762000-08-23 11:22:30 +0000111 {
David Turnerebdce832000-09-19 01:11:11 +0000112 FTC_FontRequest* font_req = (FTC_FontRequest*)node->key;
David Turnerb466a762000-08-23 11:22:30 +0000113 FT_Size size;
114 FT_Error error;
David Turnerebdce832000-09-19 01:11:11 +0000115 FT_Face face = font_req->face;
Werner Lembergeddd9902000-10-12 05:05:40 +0000116
Werner Lemberg8728f292000-08-23 17:32:42 +0000117 FT_UNUSED( lru );
118
Werner Lembergeddd9902000-10-12 05:05:40 +0000119
David Turnerb466a762000-08-23 11:22:30 +0000120 node->root.data = 0;
David Turner98d27012000-08-24 11:53:35 +0000121 error = FT_New_Size( face, &size );
Werner Lemberg8728f292000-08-23 17:32:42 +0000122 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +0000123 {
David Turner98d27012000-08-24 11:53:35 +0000124 face->size = size;
125 error = FT_Set_Pixel_Sizes( face,
David Turnerebdce832000-09-19 01:11:11 +0000126 font_req->width,
127 font_req->height );
Werner Lemberg8728f292000-08-23 17:32:42 +0000128 if ( error )
129 FT_Done_Size( size );
David Turnerb466a762000-08-23 11:22:30 +0000130 else
131 node->root.data = size;
132 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000133 return error;
David Turnerb466a762000-08-23 11:22:30 +0000134 }
135
136
David Turner76a5f622000-11-04 01:55:49 +0000137 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +0000138 void ftc_manager_done_size( FT_Lru lru,
139 FT_LruNode node )
David Turnerb466a762000-08-23 11:22:30 +0000140 {
Werner Lemberg8728f292000-08-23 17:32:42 +0000141 FT_UNUSED( lru );
142
David Turnerb466a762000-08-23 11:22:30 +0000143 FT_Done_Size( (FT_Size)node->root.data );
David Turner91bb1652000-12-05 22:23:12 +0000144 node->root.data = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +0000145 }
David Turnerb466a762000-08-23 11:22:30 +0000146
147
David Turner76a5f622000-11-04 01:55:49 +0000148 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +0000149 FT_Error ftc_manager_flush_size( FT_Lru lru,
150 FT_LruNode node,
151 FT_LruKey key )
David Turnerb466a762000-08-23 11:22:30 +0000152 {
David Turnerebdce832000-09-19 01:11:11 +0000153 FTC_FontRequest* req = (FTC_FontRequest*)key;
David Turnerb466a762000-08-23 11:22:30 +0000154 FT_Size size = (FT_Size)node->root.data;
155 FT_Error error;
Werner Lembergeddd9902000-10-12 05:05:40 +0000156
Werner Lemberg8728f292000-08-23 17:32:42 +0000157
David Turnerb466a762000-08-23 11:22:30 +0000158 if ( size->face == req->face )
159 {
160 size->face->size = size; /* set current size */
161 error = FT_Set_Pixel_Sizes( req->face, req->width, req->height );
Werner Lemberg8728f292000-08-23 17:32:42 +0000162 if ( error )
David Turnerb466a762000-08-23 11:22:30 +0000163 FT_Done_Size( size );
164 }
165 else
166 {
Werner Lemberg8728f292000-08-23 17:32:42 +0000167 FT_Done_Size( size );
David Turnerb466a762000-08-23 11:22:30 +0000168 node->key = key;
169 error = ftc_manager_init_size( lru, node );
170 }
171 return error;
172 }
173
174
David Turner76a5f622000-11-04 01:55:49 +0000175 FT_CALLBACK_DEF
Werner Lemberg8728f292000-08-23 17:32:42 +0000176 FT_Bool ftc_manager_compare_size( FT_LruNode node,
177 FT_LruKey key )
David Turnerb466a762000-08-23 11:22:30 +0000178 {
David Turnerebdce832000-09-19 01:11:11 +0000179 FTC_FontRequest* req = (FTC_FontRequest*)key;
David Turnerb466a762000-08-23 11:22:30 +0000180 FT_Size size = (FT_Size)node->root.data;
Werner Lembergeddd9902000-10-12 05:05:40 +0000181
Werner Lemberg8728f292000-08-23 17:32:42 +0000182 FT_UNUSED( node );
183
184
185 return ( size->face == req->face &&
186 size->metrics.x_ppem == req->width &&
David Turnerb466a762000-08-23 11:22:30 +0000187 size->metrics.y_ppem == req->height );
188 }
189
Werner Lembergeddd9902000-10-12 05:05:40 +0000190
David Turner76a5f622000-11-04 01:55:49 +0000191 FT_CALLBACK_TABLE_DEF
192 const FT_Lru_Class ftc_face_lru_class =
David Turnerb466a762000-08-23 11:22:30 +0000193 {
David Turner3b2c50e2000-08-23 21:11:13 +0000194 sizeof ( FT_LruRec ),
David Turnerb466a762000-08-23 11:22:30 +0000195 ftc_manager_init_face,
196 ftc_manager_done_face,
197 0,
198 0
199 };
200
Werner Lembergeddd9902000-10-12 05:05:40 +0000201
David Turner76a5f622000-11-04 01:55:49 +0000202 FT_CALLBACK_TABLE_DEF
203 const FT_Lru_Class ftc_size_lru_class =
David Turnerb466a762000-08-23 11:22:30 +0000204 {
David Turner3b2c50e2000-08-23 21:11:13 +0000205 sizeof ( FT_LruRec ),
David Turnerb466a762000-08-23 11:22:30 +0000206 ftc_manager_init_size,
207 ftc_manager_done_size,
208 ftc_manager_flush_size,
209 ftc_manager_compare_size
210 };
211
212
David Turner76a5f622000-11-04 01:55:49 +0000213 FT_EXPORT_DEF( FT_Error ) FTC_Manager_New( FT_Library library,
214 FT_UInt max_faces,
215 FT_UInt max_sizes,
216 FT_ULong max_bytes,
217 FTC_Face_Requester requester,
218 FT_Pointer req_data,
Werner Lemberg4b680072000-11-07 06:30:29 +0000219 FTC_Manager *amanager )
David Turnerb466a762000-08-23 11:22:30 +0000220 {
221 FT_Error error;
Werner Lembergd1b74752000-08-24 16:29:15 +0000222 FT_Memory memory;
David Turnerb466a762000-08-23 11:22:30 +0000223 FTC_Manager manager = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +0000224
225
Werner Lembergd1b74752000-08-24 16:29:15 +0000226 if ( !library )
227 return FT_Err_Invalid_Library_Handle;
228
229 memory = library->memory;
230
Werner Lemberg8728f292000-08-23 17:32:42 +0000231 if ( ALLOC( manager, sizeof ( *manager ) ) )
David Turnerb466a762000-08-23 11:22:30 +0000232 goto Exit;
Werner Lembergeddd9902000-10-12 05:05:40 +0000233
Werner Lembergd1b74752000-08-24 16:29:15 +0000234 if ( max_faces == 0 )
David Turnerebdce832000-09-19 01:11:11 +0000235 max_faces = FTC_MAX_FACES_DEFAULT;
Werner Lembergeddd9902000-10-12 05:05:40 +0000236
Werner Lembergd1b74752000-08-24 16:29:15 +0000237 if ( max_sizes == 0 )
David Turnerebdce832000-09-19 01:11:11 +0000238 max_sizes = FTC_MAX_SIZES_DEFAULT;
Werner Lembergeddd9902000-10-12 05:05:40 +0000239
David Turnerebdce832000-09-19 01:11:11 +0000240 if ( max_bytes == 0 )
241 max_bytes = FTC_MAX_BYTES_DEFAULT;
Werner Lembergeddd9902000-10-12 05:05:40 +0000242
David Turnerb466a762000-08-23 11:22:30 +0000243 error = FT_Lru_New( &ftc_face_lru_class,
David Turner98d27012000-08-24 11:53:35 +0000244 max_faces,
David Turner3b2c50e2000-08-23 21:11:13 +0000245 manager,
David Turnerb466a762000-08-23 11:22:30 +0000246 memory,
247 1, /* pre_alloc = TRUE */
248 (FT_Lru*)&manager->faces_lru );
Werner Lemberg8728f292000-08-23 17:32:42 +0000249 if ( error )
David Turnerb466a762000-08-23 11:22:30 +0000250 goto Exit;
Werner Lembergeddd9902000-10-12 05:05:40 +0000251
David Turnerb466a762000-08-23 11:22:30 +0000252 error = FT_Lru_New( &ftc_size_lru_class,
David Turner98d27012000-08-24 11:53:35 +0000253 max_sizes,
David Turner3b2c50e2000-08-23 21:11:13 +0000254 manager,
David Turnerb466a762000-08-23 11:22:30 +0000255 memory,
256 1, /* pre_alloc = TRUE */
Werner Lembergeddd9902000-10-12 05:05:40 +0000257 (FT_Lru*)&manager->sizes_lru );
Werner Lemberg8728f292000-08-23 17:32:42 +0000258 if ( error )
David Turnerb466a762000-08-23 11:22:30 +0000259 goto Exit;
Werner Lembergeddd9902000-10-12 05:05:40 +0000260
David Turnerb466a762000-08-23 11:22:30 +0000261 manager->library = library;
David Turnerebdce832000-09-19 01:11:11 +0000262 manager->max_bytes = max_bytes;
David Turnerb466a762000-08-23 11:22:30 +0000263 manager->request_face = requester;
264 manager->request_data = req_data;
265 *amanager = manager;
Werner Lembergeddd9902000-10-12 05:05:40 +0000266
David Turnerb466a762000-08-23 11:22:30 +0000267 Exit:
Werner Lemberg8728f292000-08-23 17:32:42 +0000268 if ( error && manager )
David Turnerb466a762000-08-23 11:22:30 +0000269 {
David Turnerb466a762000-08-23 11:22:30 +0000270 FT_Lru_Done( manager->faces_lru );
David Turner940d3062000-12-05 23:07:16 +0000271 FT_Lru_Done( manager->sizes_lru );
David Turnerb466a762000-08-23 11:22:30 +0000272 FREE( manager );
273 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000274
David Turnerb466a762000-08-23 11:22:30 +0000275 return error;
276 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000277
Werner Lemberg8728f292000-08-23 17:32:42 +0000278
Werner Lembergada95032000-11-29 17:48:57 +0000279 FT_EXPORT_DEF( void ) FTC_Manager_Done( FTC_Manager manager )
David Turnerb466a762000-08-23 11:22:30 +0000280 {
Werner Lembergd1b74752000-08-24 16:29:15 +0000281 FT_Memory memory;
David Turnerebdce832000-09-19 01:11:11 +0000282 FT_UInt index;
Werner Lembergeddd9902000-10-12 05:05:40 +0000283
Werner Lemberg8728f292000-08-23 17:32:42 +0000284
Werner Lembergd1b74752000-08-24 16:29:15 +0000285 if ( !manager || !manager->library )
286 return;
287
288 memory = manager->library->memory;
289
David Turnerebdce832000-09-19 01:11:11 +0000290 /* now discard all caches */
291 for (index = 0; index < FTC_MAX_CACHES; index++ )
292 {
293 FTC_Cache cache = manager->caches[index];
Werner Lembergeddd9902000-10-12 05:05:40 +0000294
295
296 if ( cache )
David Turnerebdce832000-09-19 01:11:11 +0000297 {
298 cache->clazz->done_cache( cache );
Werner Lembergeddd9902000-10-12 05:05:40 +0000299 FREE( cache );
David Turnerebdce832000-09-19 01:11:11 +0000300 manager->caches[index] = 0;
301 }
302 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000303
David Turnerebdce832000-09-19 01:11:11 +0000304 /* discard faces and sizes */
David Turnerb466a762000-08-23 11:22:30 +0000305 FT_Lru_Done( manager->faces_lru );
David Turner91bb1652000-12-05 22:23:12 +0000306 manager->faces_lru = 0;
307
308 FT_Lru_Done( manager->sizes_lru );
David Turner940d3062000-12-05 23:07:16 +0000309 manager->sizes_lru = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +0000310
David Turnerb466a762000-08-23 11:22:30 +0000311 FREE( manager );
312 }
313
314
Werner Lembergada95032000-11-29 17:48:57 +0000315 FT_EXPORT_DEF( void ) FTC_Manager_Reset( FTC_Manager manager )
David Turnerb466a762000-08-23 11:22:30 +0000316 {
David Turnerebdce832000-09-19 01:11:11 +0000317 if (manager )
318 {
319 FT_Lru_Reset( manager->sizes_lru );
320 FT_Lru_Reset( manager->faces_lru );
321 }
Werner Lembergab855232000-10-31 22:13:54 +0000322 /* XXX: FIXME: flush the caches? */
David Turnerb466a762000-08-23 11:22:30 +0000323 }
324
325
Werner Lembergada95032000-11-29 17:48:57 +0000326 FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Face( FTC_Manager manager,
327 FTC_FaceID face_id,
328 FT_Face *aface )
David Turnerb466a762000-08-23 11:22:30 +0000329 {
Werner Lembergd1b74752000-08-24 16:29:15 +0000330 if ( !manager )
Werner Lemberg95853c82000-08-26 22:16:44 +0000331 return FT_Err_Invalid_Cache_Handle;
Werner Lembergd1b74752000-08-24 16:29:15 +0000332
David Turnerb466a762000-08-23 11:22:30 +0000333 return FT_Lru_Lookup( manager->faces_lru,
Werner Lembergeddd9902000-10-12 05:05:40 +0000334 (FT_LruKey)face_id,
Werner Lemberg8728f292000-08-23 17:32:42 +0000335 (FT_Pointer*)aface );
David Turnerb466a762000-08-23 11:22:30 +0000336 }
David Turnerebdce832000-09-19 01:11:11 +0000337
338
Werner Lembergada95032000-11-29 17:48:57 +0000339 FT_EXPORT_DEF( FT_Error ) FTC_Manager_Lookup_Size( FTC_Manager manager,
340 FTC_Font font,
341 FT_Face *aface,
342 FT_Size *asize )
David Turnerb466a762000-08-23 11:22:30 +0000343 {
David Turnerebdce832000-09-19 01:11:11 +0000344 FTC_FontRequest req;
David Turnerb466a762000-08-23 11:22:30 +0000345 FT_Error error;
Werner Lembergeddd9902000-10-12 05:05:40 +0000346
Werner Lemberg8728f292000-08-23 17:32:42 +0000347
Werner Lembergd1b74752000-08-24 16:29:15 +0000348 /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
349
350 if ( aface )
David Turner3b2c50e2000-08-23 21:11:13 +0000351 *aface = 0;
Werner Lembergeddd9902000-10-12 05:05:40 +0000352
Werner Lembergd1b74752000-08-24 16:29:15 +0000353 if ( asize )
David Turner3b2c50e2000-08-23 21:11:13 +0000354 *asize = 0;
Werner Lemberg8728f292000-08-23 17:32:42 +0000355
Werner Lembergeddd9902000-10-12 05:05:40 +0000356 error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
Werner Lemberg8728f292000-08-23 17:32:42 +0000357 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +0000358 {
David Turner3b2c50e2000-08-23 21:11:13 +0000359 FT_Size size;
Werner Lembergeddd9902000-10-12 05:05:40 +0000360
Werner Lembergd1b74752000-08-24 16:29:15 +0000361
David Turnerf88969a2000-10-12 00:28:00 +0000362 req.face = *aface;
David Turnerebdce832000-09-19 01:11:11 +0000363 req.width = font->pix_width;
364 req.height = font->pix_height;
Werner Lembergeddd9902000-10-12 05:05:40 +0000365
Werner Lemberg8728f292000-08-23 17:32:42 +0000366 error = FT_Lru_Lookup( manager->sizes_lru,
367 (FT_LruKey)&req,
David Turner3b2c50e2000-08-23 21:11:13 +0000368 (FT_Pointer*)&size );
Werner Lemberg8728f292000-08-23 17:32:42 +0000369 if ( !error )
David Turnerb466a762000-08-23 11:22:30 +0000370 {
371 /* select the size as the current one for this face */
Werner Lembergeddd9902000-10-12 05:05:40 +0000372 (*aface)->size = size;
373
Werner Lembergd1b74752000-08-24 16:29:15 +0000374 if ( asize )
David Turner3b2c50e2000-08-23 21:11:13 +0000375 *asize = size;
David Turnerb466a762000-08-23 11:22:30 +0000376 }
377 }
Werner Lemberg8728f292000-08-23 17:32:42 +0000378
David Turnerb466a762000-08-23 11:22:30 +0000379 return error;
380 }
381
382
Werner Lembergeddd9902000-10-12 05:05:40 +0000383 /* `Compress' the manager's data, i.e., get rid of old cache nodes */
David Turnerebdce832000-09-19 01:11:11 +0000384 /* that are not referenced anymore in order to limit the total */
Werner Lembergeddd9902000-10-12 05:05:40 +0000385 /* memory used by the cache. */
David Turner76a5f622000-11-04 01:55:49 +0000386 FT_EXPORT_DEF( void ) FTC_Manager_Compress( FTC_Manager manager )
David Turnerebdce832000-09-19 01:11:11 +0000387 {
388 FT_ListNode node;
Werner Lembergeddd9902000-10-12 05:05:40 +0000389
390
David Turnerebdce832000-09-19 01:11:11 +0000391 node = manager->global_lru.tail;
Werner Lembergeddd9902000-10-12 05:05:40 +0000392 while ( manager->num_bytes > manager->max_bytes && node )
David Turnerebdce832000-09-19 01:11:11 +0000393 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000394 FTC_CacheNode cache_node = FTC_LIST_TO_CACHENODE( node );
395 FTC_CacheNode_Data* data = FTC_CACHENODE_TO_DATA_P( cache_node );
David Turnerebdce832000-09-19 01:11:11 +0000396 FTC_Cache cache;
397 FT_ListNode prev = node->prev;
Werner Lembergeddd9902000-10-12 05:05:40 +0000398
399
400 if ( data->ref_count <= 0 )
David Turnerebdce832000-09-19 01:11:11 +0000401 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000402 /* ok, we are going to remove this node */
David Turnerebdce832000-09-19 01:11:11 +0000403 FT_List_Remove( &manager->global_lru, node );
Werner Lembergeddd9902000-10-12 05:05:40 +0000404
David Turnerebdce832000-09-19 01:11:11 +0000405 /* finalize cache node */
406 cache = manager->caches[data->cache_index];
Werner Lembergeddd9902000-10-12 05:05:40 +0000407 if ( cache )
David Turnerebdce832000-09-19 01:11:11 +0000408 {
409 FTC_CacheNode_Class* clazz = cache->node_clazz;
Werner Lembergeddd9902000-10-12 05:05:40 +0000410
411
David Turnerebdce832000-09-19 01:11:11 +0000412 manager->num_bytes -= clazz->size_node( cache_node,
David Turnerece63792000-10-28 23:34:45 +0000413 cache->cache_data );
Werner Lembergeddd9902000-10-12 05:05:40 +0000414
David Turnerece63792000-10-28 23:34:45 +0000415 clazz->destroy_node( cache_node, cache->cache_data );
David Turnerebdce832000-09-19 01:11:11 +0000416 }
417 else
418 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000419 /* this should never happen! */
420 FT_ERROR(( "FTC_Manager_Compress: Cache Manager is corrupted!\n" ));
David Turnerebdce832000-09-19 01:11:11 +0000421 }
Werner Lemberge4b32a52000-10-31 20:42:18 +0000422
David Turnerece63792000-10-28 23:34:45 +0000423 /* check, just in case of general corruption :-) */
Werner Lembergab855232000-10-31 22:13:54 +0000424 if ( manager->num_nodes <= 0 )
425 FT_ERROR(( "FTC_Manager_Compress: Invalid cache node count!\n" ));
David Turnerece63792000-10-28 23:34:45 +0000426 else
427 manager->num_nodes--;
David Turnerebdce832000-09-19 01:11:11 +0000428 }
429 node = prev;
430 }
431 }
432
433
Werner Lembergada95032000-11-29 17:48:57 +0000434 FT_EXPORT_DEF( FT_Error ) FTC_Manager_Register_Cache(
435 FTC_Manager manager,
436 FTC_Cache_Class* clazz,
437 FTC_Cache *acache )
David Turnerebdce832000-09-19 01:11:11 +0000438 {
Werner Lembergeddd9902000-10-12 05:05:40 +0000439 FT_Error error = FT_Err_Invalid_Argument;
440
441
David Turnerebdce832000-09-19 01:11:11 +0000442 if ( manager && clazz && acache )
443 {
444 FT_Memory memory = manager->library->memory;
445 FTC_Cache cache;
446 FT_UInt index = 0;
447
Werner Lembergeddd9902000-10-12 05:05:40 +0000448
David Turnerebdce832000-09-19 01:11:11 +0000449 /* by default, return 0 */
450 *acache = 0;
451
452 /* check for an empty cache slot in the manager's table */
453 for ( index = 0; index < FTC_MAX_CACHES; index++ )
454 {
455 if ( manager->caches[index] == 0 )
456 break;
457 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000458
David Turnerebdce832000-09-19 01:11:11 +0000459 /* return an error if there are too many registered caches */
Werner Lembergeddd9902000-10-12 05:05:40 +0000460 if ( index >= FTC_MAX_CACHES )
David Turnerebdce832000-09-19 01:11:11 +0000461 {
462 error = FT_Err_Too_Many_Caches;
463 FT_ERROR(( "FTC_Manager_Register_Cache:" ));
Werner Lembergeddd9902000-10-12 05:05:40 +0000464 FT_ERROR(( " too many registered caches\n" ));
David Turnerebdce832000-09-19 01:11:11 +0000465 goto Exit;
466 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000467
David Turnerebdce832000-09-19 01:11:11 +0000468 if ( !ALLOC( cache, clazz->cache_byte_size ) )
469 {
470 cache->manager = manager;
471 cache->memory = memory;
472 cache->clazz = clazz;
Werner Lemberge4b32a52000-10-31 20:42:18 +0000473
Werner Lembergab855232000-10-31 22:13:54 +0000474 /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
475 /* IF IT IS NOT SET CORRECTLY */
David Turner29094752000-10-31 10:58:23 +0000476 cache->cache_index = index;
David Turnerebdce832000-09-19 01:11:11 +0000477
Werner Lembergeddd9902000-10-12 05:05:40 +0000478 if ( clazz->init_cache )
David Turnerebdce832000-09-19 01:11:11 +0000479 error = clazz->init_cache( cache );
Werner Lembergeddd9902000-10-12 05:05:40 +0000480
481 if ( error )
482 FREE( cache );
David Turnerebdce832000-09-19 01:11:11 +0000483 else
Werner Lembergeddd9902000-10-12 05:05:40 +0000484 manager->caches[index] = *acache = cache;
David Turnerebdce832000-09-19 01:11:11 +0000485 }
486 }
Werner Lembergeddd9902000-10-12 05:05:40 +0000487
David Turnerebdce832000-09-19 01:11:11 +0000488 Exit:
489 return error;
490 }
491
Werner Lembergeddd9902000-10-12 05:05:40 +0000492
Werner Lemberg8728f292000-08-23 17:32:42 +0000493/* END */