Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftcmanag.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ftcmanag.c */ 00004 /* */ 00005 /* FreeType Cache Manager (body). */ 00006 /* */ 00007 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include <ft2build.h> 00020 #include FT_CACHE_H 00021 #include "ftcmanag.h" 00022 #include FT_INTERNAL_OBJECTS_H 00023 #include FT_INTERNAL_DEBUG_H 00024 #include FT_SIZES_H 00025 00026 #include "ftccback.h" 00027 #include "ftcerror.h" 00028 00029 #ifdef FT_CONFIG_OPTION_PIC 00030 #error "cache system does not support PIC yet" 00031 #endif 00032 00033 00034 #undef FT_COMPONENT 00035 #define FT_COMPONENT trace_cache 00036 00037 #define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data ) 00038 00039 00040 static FT_Error 00041 ftc_scaler_lookup_size( FTC_Manager manager, 00042 FTC_Scaler scaler, 00043 FT_Size *asize ) 00044 { 00045 FT_Face face; 00046 FT_Size size = NULL; 00047 FT_Error error; 00048 00049 00050 error = FTC_Manager_LookupFace( manager, scaler->face_id, &face ); 00051 if ( error ) 00052 goto Exit; 00053 00054 error = FT_New_Size( face, &size ); 00055 if ( error ) 00056 goto Exit; 00057 00058 FT_Activate_Size( size ); 00059 00060 if ( scaler->pixel ) 00061 error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height ); 00062 else 00063 error = FT_Set_Char_Size( face, scaler->width, scaler->height, 00064 scaler->x_res, scaler->y_res ); 00065 if ( error ) 00066 { 00067 FT_Done_Size( size ); 00068 size = NULL; 00069 } 00070 00071 Exit: 00072 *asize = size; 00073 return error; 00074 } 00075 00076 00077 typedef struct FTC_SizeNodeRec_ 00078 { 00079 FTC_MruNodeRec node; 00080 FT_Size size; 00081 FTC_ScalerRec scaler; 00082 00083 } FTC_SizeNodeRec, *FTC_SizeNode; 00084 00085 #define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) ) 00086 00087 00088 FT_CALLBACK_DEF( void ) 00089 ftc_size_node_done( FTC_MruNode ftcnode, 00090 FT_Pointer data ) 00091 { 00092 FTC_SizeNode node = (FTC_SizeNode)ftcnode; 00093 FT_Size size = node->size; 00094 FT_UNUSED( data ); 00095 00096 00097 if ( size ) 00098 FT_Done_Size( size ); 00099 } 00100 00101 00102 FT_CALLBACK_DEF( FT_Bool ) 00103 ftc_size_node_compare( FTC_MruNode ftcnode, 00104 FT_Pointer ftcscaler ) 00105 { 00106 FTC_SizeNode node = (FTC_SizeNode)ftcnode; 00107 FTC_Scaler scaler = (FTC_Scaler)ftcscaler; 00108 FTC_Scaler scaler0 = &node->scaler; 00109 00110 00111 if ( FTC_SCALER_COMPARE( scaler0, scaler ) ) 00112 { 00113 FT_Activate_Size( node->size ); 00114 return 1; 00115 } 00116 return 0; 00117 } 00118 00119 00120 FT_CALLBACK_DEF( FT_Error ) 00121 ftc_size_node_init( FTC_MruNode ftcnode, 00122 FT_Pointer ftcscaler, 00123 FT_Pointer ftcmanager ) 00124 { 00125 FTC_SizeNode node = (FTC_SizeNode)ftcnode; 00126 FTC_Scaler scaler = (FTC_Scaler)ftcscaler; 00127 FTC_Manager manager = (FTC_Manager)ftcmanager; 00128 00129 00130 node->scaler = scaler[0]; 00131 00132 return ftc_scaler_lookup_size( manager, scaler, &node->size ); 00133 } 00134 00135 00136 FT_CALLBACK_DEF( FT_Error ) 00137 ftc_size_node_reset( FTC_MruNode ftcnode, 00138 FT_Pointer ftcscaler, 00139 FT_Pointer ftcmanager ) 00140 { 00141 FTC_SizeNode node = (FTC_SizeNode)ftcnode; 00142 FTC_Scaler scaler = (FTC_Scaler)ftcscaler; 00143 FTC_Manager manager = (FTC_Manager)ftcmanager; 00144 00145 00146 FT_Done_Size( node->size ); 00147 00148 node->scaler = scaler[0]; 00149 00150 return ftc_scaler_lookup_size( manager, scaler, &node->size ); 00151 } 00152 00153 00154 FT_CALLBACK_TABLE_DEF 00155 const FTC_MruListClassRec ftc_size_list_class = 00156 { 00157 sizeof ( FTC_SizeNodeRec ), 00158 ftc_size_node_compare, 00159 ftc_size_node_init, 00160 ftc_size_node_reset, 00161 ftc_size_node_done 00162 }; 00163 00164 00165 /* helper function used by ftc_face_node_done */ 00166 static FT_Bool 00167 ftc_size_node_compare_faceid( FTC_MruNode ftcnode, 00168 FT_Pointer ftcface_id ) 00169 { 00170 FTC_SizeNode node = (FTC_SizeNode)ftcnode; 00171 FTC_FaceID face_id = (FTC_FaceID)ftcface_id; 00172 00173 00174 return FT_BOOL( node->scaler.face_id == face_id ); 00175 } 00176 00177 00178 /* documentation is in ftcache.h */ 00179 00180 FT_EXPORT_DEF( FT_Error ) 00181 FTC_Manager_LookupSize( FTC_Manager manager, 00182 FTC_Scaler scaler, 00183 FT_Size *asize ) 00184 { 00185 FT_Error error; 00186 FTC_MruNode mrunode; 00187 00188 00189 if ( asize == NULL ) 00190 return FTC_Err_Invalid_Argument; 00191 00192 *asize = NULL; 00193 00194 if ( !manager ) 00195 return FTC_Err_Invalid_Cache_Handle; 00196 00197 #ifdef FTC_INLINE 00198 00199 FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare, 00200 mrunode, error ); 00201 00202 #else 00203 error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode ); 00204 #endif 00205 00206 if ( !error ) 00207 *asize = FTC_SIZE_NODE( mrunode )->size; 00208 00209 return error; 00210 } 00211 00212 00213 /*************************************************************************/ 00214 /*************************************************************************/ 00215 /***** *****/ 00216 /***** FACE MRU IMPLEMENTATION *****/ 00217 /***** *****/ 00218 /*************************************************************************/ 00219 /*************************************************************************/ 00220 00221 typedef struct FTC_FaceNodeRec_ 00222 { 00223 FTC_MruNodeRec node; 00224 FTC_FaceID face_id; 00225 FT_Face face; 00226 00227 } FTC_FaceNodeRec, *FTC_FaceNode; 00228 00229 #define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) ) 00230 00231 00232 FT_CALLBACK_DEF( FT_Error ) 00233 ftc_face_node_init( FTC_MruNode ftcnode, 00234 FT_Pointer ftcface_id, 00235 FT_Pointer ftcmanager ) 00236 { 00237 FTC_FaceNode node = (FTC_FaceNode)ftcnode; 00238 FTC_FaceID face_id = (FTC_FaceID)ftcface_id; 00239 FTC_Manager manager = (FTC_Manager)ftcmanager; 00240 FT_Error error; 00241 00242 00243 node->face_id = face_id; 00244 00245 error = manager->request_face( face_id, 00246 manager->library, 00247 manager->request_data, 00248 &node->face ); 00249 if ( !error ) 00250 { 00251 /* destroy initial size object; it will be re-created later */ 00252 if ( node->face->size ) 00253 FT_Done_Size( node->face->size ); 00254 } 00255 00256 return error; 00257 } 00258 00259 00260 FT_CALLBACK_DEF( void ) 00261 ftc_face_node_done( FTC_MruNode ftcnode, 00262 FT_Pointer ftcmanager ) 00263 { 00264 FTC_FaceNode node = (FTC_FaceNode)ftcnode; 00265 FTC_Manager manager = (FTC_Manager)ftcmanager; 00266 00267 00268 /* we must begin by removing all scalers for the target face */ 00269 /* from the manager's list */ 00270 FTC_MruList_RemoveSelection( &manager->sizes, 00271 ftc_size_node_compare_faceid, 00272 node->face_id ); 00273 00274 /* all right, we can discard the face now */ 00275 FT_Done_Face( node->face ); 00276 node->face = NULL; 00277 node->face_id = NULL; 00278 } 00279 00280 00281 FT_CALLBACK_DEF( FT_Bool ) 00282 ftc_face_node_compare( FTC_MruNode ftcnode, 00283 FT_Pointer ftcface_id ) 00284 { 00285 FTC_FaceNode node = (FTC_FaceNode)ftcnode; 00286 FTC_FaceID face_id = (FTC_FaceID)ftcface_id; 00287 00288 00289 return FT_BOOL( node->face_id == face_id ); 00290 } 00291 00292 00293 FT_CALLBACK_TABLE_DEF 00294 const FTC_MruListClassRec ftc_face_list_class = 00295 { 00296 sizeof ( FTC_FaceNodeRec), 00297 00298 ftc_face_node_compare, 00299 ftc_face_node_init, 00300 0, /* FTC_MruNode_ResetFunc */ 00301 ftc_face_node_done 00302 }; 00303 00304 00305 /* documentation is in ftcache.h */ 00306 00307 FT_EXPORT_DEF( FT_Error ) 00308 FTC_Manager_LookupFace( FTC_Manager manager, 00309 FTC_FaceID face_id, 00310 FT_Face *aface ) 00311 { 00312 FT_Error error; 00313 FTC_MruNode mrunode; 00314 00315 00316 if ( aface == NULL ) 00317 return FTC_Err_Invalid_Argument; 00318 00319 *aface = NULL; 00320 00321 if ( !manager ) 00322 return FTC_Err_Invalid_Cache_Handle; 00323 00324 /* we break encapsulation for the sake of speed */ 00325 #ifdef FTC_INLINE 00326 00327 FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare, 00328 mrunode, error ); 00329 00330 #else 00331 error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode ); 00332 #endif 00333 00334 if ( !error ) 00335 *aface = FTC_FACE_NODE( mrunode )->face; 00336 00337 return error; 00338 } 00339 00340 00341 /*************************************************************************/ 00342 /*************************************************************************/ 00343 /***** *****/ 00344 /***** CACHE MANAGER ROUTINES *****/ 00345 /***** *****/ 00346 /*************************************************************************/ 00347 /*************************************************************************/ 00348 00349 00350 /* documentation is in ftcache.h */ 00351 00352 FT_EXPORT_DEF( FT_Error ) 00353 FTC_Manager_New( FT_Library library, 00354 FT_UInt max_faces, 00355 FT_UInt max_sizes, 00356 FT_ULong max_bytes, 00357 FTC_Face_Requester requester, 00358 FT_Pointer req_data, 00359 FTC_Manager *amanager ) 00360 { 00361 FT_Error error; 00362 FT_Memory memory; 00363 FTC_Manager manager = 0; 00364 00365 00366 if ( !library ) 00367 return FTC_Err_Invalid_Library_Handle; 00368 00369 memory = library->memory; 00370 00371 if ( FT_NEW( manager ) ) 00372 goto Exit; 00373 00374 if ( max_faces == 0 ) 00375 max_faces = FTC_MAX_FACES_DEFAULT; 00376 00377 if ( max_sizes == 0 ) 00378 max_sizes = FTC_MAX_SIZES_DEFAULT; 00379 00380 if ( max_bytes == 0 ) 00381 max_bytes = FTC_MAX_BYTES_DEFAULT; 00382 00383 manager->library = library; 00384 manager->memory = memory; 00385 manager->max_weight = max_bytes; 00386 00387 manager->request_face = requester; 00388 manager->request_data = req_data; 00389 00390 FTC_MruList_Init( &manager->faces, 00391 &ftc_face_list_class, 00392 max_faces, 00393 manager, 00394 memory ); 00395 00396 FTC_MruList_Init( &manager->sizes, 00397 &ftc_size_list_class, 00398 max_sizes, 00399 manager, 00400 memory ); 00401 00402 *amanager = manager; 00403 00404 Exit: 00405 return error; 00406 } 00407 00408 00409 /* documentation is in ftcache.h */ 00410 00411 FT_EXPORT_DEF( void ) 00412 FTC_Manager_Done( FTC_Manager manager ) 00413 { 00414 FT_Memory memory; 00415 FT_UInt idx; 00416 00417 00418 if ( !manager || !manager->library ) 00419 return; 00420 00421 memory = manager->memory; 00422 00423 /* now discard all caches */ 00424 for (idx = manager->num_caches; idx-- > 0; ) 00425 { 00426 FTC_Cache cache = manager->caches[idx]; 00427 00428 00429 if ( cache ) 00430 { 00431 cache->clazz.cache_done( cache ); 00432 FT_FREE( cache ); 00433 manager->caches[idx] = NULL; 00434 } 00435 } 00436 manager->num_caches = 0; 00437 00438 /* discard faces and sizes */ 00439 FTC_MruList_Done( &manager->sizes ); 00440 FTC_MruList_Done( &manager->faces ); 00441 00442 manager->library = NULL; 00443 manager->memory = NULL; 00444 00445 FT_FREE( manager ); 00446 } 00447 00448 00449 /* documentation is in ftcache.h */ 00450 00451 FT_EXPORT_DEF( void ) 00452 FTC_Manager_Reset( FTC_Manager manager ) 00453 { 00454 if ( manager ) 00455 { 00456 FTC_MruList_Reset( &manager->sizes ); 00457 FTC_MruList_Reset( &manager->faces ); 00458 } 00459 /* XXX: FIXME: flush the caches? */ 00460 } 00461 00462 00463 #ifdef FT_DEBUG_ERROR 00464 00465 static void 00466 FTC_Manager_Check( FTC_Manager manager ) 00467 { 00468 FTC_Node node, first; 00469 00470 00471 first = manager->nodes_list; 00472 00473 /* check node weights */ 00474 if ( first ) 00475 { 00476 FT_ULong weight = 0; 00477 00478 00479 node = first; 00480 00481 do 00482 { 00483 FTC_Cache cache = manager->caches[node->cache_index]; 00484 00485 00486 if ( (FT_UInt)node->cache_index >= manager->num_caches ) 00487 FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n", 00488 node->cache_index )); 00489 else 00490 weight += cache->clazz.node_weight( node, cache ); 00491 00492 node = FTC_NODE__NEXT( node ); 00493 00494 } while ( node != first ); 00495 00496 if ( weight != manager->cur_weight ) 00497 FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n", 00498 manager->cur_weight, weight )); 00499 } 00500 00501 /* check circular list */ 00502 if ( first ) 00503 { 00504 FT_UFast count = 0; 00505 00506 00507 node = first; 00508 do 00509 { 00510 count++; 00511 node = FTC_NODE__NEXT( node ); 00512 00513 } while ( node != first ); 00514 00515 if ( count != manager->num_nodes ) 00516 FT_TRACE0(( "FTC_Manager_Check:" 00517 " invalid cache node count %d instead of %d\n", 00518 manager->num_nodes, count )); 00519 } 00520 } 00521 00522 #endif /* FT_DEBUG_ERROR */ 00523 00524 00525 /* `Compress' the manager's data, i.e., get rid of old cache nodes */ 00526 /* that are not referenced anymore in order to limit the total */ 00527 /* memory used by the cache. */ 00528 00529 /* documentation is in ftcmanag.h */ 00530 00531 FT_LOCAL_DEF( void ) 00532 FTC_Manager_Compress( FTC_Manager manager ) 00533 { 00534 FTC_Node node, first; 00535 00536 00537 if ( !manager ) 00538 return; 00539 00540 first = manager->nodes_list; 00541 00542 #ifdef FT_DEBUG_ERROR 00543 FTC_Manager_Check( manager ); 00544 00545 FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n", 00546 manager->cur_weight, manager->max_weight, 00547 manager->num_nodes )); 00548 #endif 00549 00550 if ( manager->cur_weight < manager->max_weight || first == NULL ) 00551 return; 00552 00553 /* go to last node -- it's a circular list */ 00554 node = FTC_NODE__PREV( first ); 00555 do 00556 { 00557 FTC_Node prev; 00558 00559 00560 prev = ( node == first ) ? NULL : FTC_NODE__PREV( node ); 00561 00562 if ( node->ref_count <= 0 ) 00563 ftc_node_destroy( node, manager ); 00564 00565 node = prev; 00566 00567 } while ( node && manager->cur_weight > manager->max_weight ); 00568 } 00569 00570 00571 /* documentation is in ftcmanag.h */ 00572 00573 FT_LOCAL_DEF( FT_Error ) 00574 FTC_Manager_RegisterCache( FTC_Manager manager, 00575 FTC_CacheClass clazz, 00576 FTC_Cache *acache ) 00577 { 00578 FT_Error error = FTC_Err_Invalid_Argument; 00579 FTC_Cache cache = NULL; 00580 00581 00582 if ( manager && clazz && acache ) 00583 { 00584 FT_Memory memory = manager->memory; 00585 00586 00587 if ( manager->num_caches >= FTC_MAX_CACHES ) 00588 { 00589 error = FTC_Err_Too_Many_Caches; 00590 FT_ERROR(( "FTC_Manager_RegisterCache:" 00591 " too many registered caches\n" )); 00592 goto Exit; 00593 } 00594 00595 if ( !FT_ALLOC( cache, clazz->cache_size ) ) 00596 { 00597 cache->manager = manager; 00598 cache->memory = memory; 00599 cache->clazz = clazz[0]; 00600 cache->org_class = clazz; 00601 00602 /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */ 00603 /* IF IT IS NOT SET CORRECTLY */ 00604 cache->index = manager->num_caches; 00605 00606 error = clazz->cache_init( cache ); 00607 if ( error ) 00608 { 00609 clazz->cache_done( cache ); 00610 FT_FREE( cache ); 00611 goto Exit; 00612 } 00613 00614 manager->caches[manager->num_caches++] = cache; 00615 } 00616 } 00617 00618 Exit: 00619 if ( acache ) 00620 *acache = cache; 00621 return error; 00622 } 00623 00624 00625 FT_LOCAL_DEF( FT_UInt ) 00626 FTC_Manager_FlushN( FTC_Manager manager, 00627 FT_UInt count ) 00628 { 00629 FTC_Node first = manager->nodes_list; 00630 FTC_Node node; 00631 FT_UInt result; 00632 00633 00634 /* try to remove `count' nodes from the list */ 00635 if ( first == NULL ) /* empty list! */ 00636 return 0; 00637 00638 /* go to last node - it's a circular list */ 00639 node = FTC_NODE__PREV(first); 00640 for ( result = 0; result < count; ) 00641 { 00642 FTC_Node prev = FTC_NODE__PREV( node ); 00643 00644 00645 /* don't touch locked nodes */ 00646 if ( node->ref_count <= 0 ) 00647 { 00648 ftc_node_destroy( node, manager ); 00649 result++; 00650 } 00651 00652 if ( node == first ) 00653 break; 00654 00655 node = prev; 00656 } 00657 return result; 00658 } 00659 00660 00661 /* documentation is in ftcache.h */ 00662 00663 FT_EXPORT_DEF( void ) 00664 FTC_Manager_RemoveFaceID( FTC_Manager manager, 00665 FTC_FaceID face_id ) 00666 { 00667 FT_UInt nn; 00668 00669 /* this will remove all FTC_SizeNode that correspond to 00670 * the face_id as well 00671 */ 00672 FTC_MruList_RemoveSelection( &manager->faces, 00673 ftc_face_node_compare, 00674 face_id ); 00675 00676 for ( nn = 0; nn < manager->num_caches; nn++ ) 00677 FTC_Cache_RemoveFaceID( manager->caches[nn], face_id ); 00678 } 00679 00680 00681 /* documentation is in ftcache.h */ 00682 00683 FT_EXPORT_DEF( void ) 00684 FTC_Node_Unref( FTC_Node node, 00685 FTC_Manager manager ) 00686 { 00687 if ( node && (FT_UInt)node->cache_index < manager->num_caches ) 00688 node->ref_count--; 00689 } 00690 00691 00692 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 00693 00694 FT_EXPORT_DEF( FT_Error ) 00695 FTC_Manager_Lookup_Face( FTC_Manager manager, 00696 FTC_FaceID face_id, 00697 FT_Face *aface ) 00698 { 00699 return FTC_Manager_LookupFace( manager, face_id, aface ); 00700 } 00701 00702 00703 FT_EXPORT( FT_Error ) 00704 FTC_Manager_Lookup_Size( FTC_Manager manager, 00705 FTC_Font font, 00706 FT_Face *aface, 00707 FT_Size *asize ) 00708 { 00709 FTC_ScalerRec scaler; 00710 FT_Error error; 00711 FT_Size size; 00712 FT_Face face; 00713 00714 00715 scaler.face_id = font->face_id; 00716 scaler.width = font->pix_width; 00717 scaler.height = font->pix_height; 00718 scaler.pixel = TRUE; 00719 scaler.x_res = 0; 00720 scaler.y_res = 0; 00721 00722 error = FTC_Manager_LookupSize( manager, &scaler, &size ); 00723 if ( error ) 00724 { 00725 face = NULL; 00726 size = NULL; 00727 } 00728 else 00729 face = size->face; 00730 00731 if ( aface ) 00732 *aface = face; 00733 00734 if ( asize ) 00735 *asize = size; 00736 00737 return error; 00738 } 00739 00740 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ 00741 00742 00743 /* END */ Generated on Sun May 27 2012 04:33:48 for ReactOS by
1.7.6.1
|