ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftcmanag.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.